Merge "aaudio: fix warning for use after free"
diff --git a/drm/mediacas/plugins/clearkey/ClearKeySessionLibrary.cpp b/drm/mediacas/plugins/clearkey/ClearKeySessionLibrary.cpp
index faea008..4b4051d 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeySessionLibrary.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeySessionLibrary.cpp
@@ -95,7 +95,7 @@
void ClearKeySessionLibrary::destroyPlugin(CasPlugin *plugin) {
Mutex::Autolock lock(mSessionsLock);
- for (ssize_t index = mIDToSessionMap.size() - 1; index >= 0; index--) {
+ for (ssize_t index = (ssize_t)mIDToSessionMap.size() - 1; index >= 0; index--) {
sp<ClearKeyCasSession> session = mIDToSessionMap.valueAt(index);
if (session->getPlugin() == plugin) {
mIDToSessionMap.removeItemsAt(index);
diff --git a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
index 6e1004c..ee8dba3 100644
--- a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
+++ b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
@@ -36,8 +36,6 @@
const String8 kCasTypeTag("cas_type");
const String8 kBase64Padding("=");
-const uint32_t kKeyLength = 16;
-
JsonAssetLoader::JsonAssetLoader() {
}
diff --git a/drm/mediacas/plugins/clearkey/ecm_generator.cpp b/drm/mediacas/plugins/clearkey/ecm_generator.cpp
index 7d29659..218ce35 100644
--- a/drm/mediacas/plugins/clearkey/ecm_generator.cpp
+++ b/drm/mediacas/plugins/clearkey/ecm_generator.cpp
@@ -38,8 +38,6 @@
const uint16_t kTotalEcmSize =
kEcmClearFieldsSize + kContentKeyByteSize; // clear fields + clear key
-const uint32_t kKeyLength = 16;
-
#define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32_t *>(_p))
static uint32_t Load32(const void *p) {
diff --git a/drm/mediacas/plugins/clearkey/tests/ClearKeyFetcherTest.cpp b/drm/mediacas/plugins/clearkey/tests/ClearKeyFetcherTest.cpp
index ace086a..d12cfeb 100644
--- a/drm/mediacas/plugins/clearkey/tests/ClearKeyFetcherTest.cpp
+++ b/drm/mediacas/plugins/clearkey/tests/ClearKeyFetcherTest.cpp
@@ -93,7 +93,7 @@
uint64_t asset_id;
std::vector<KeyFetcher::KeyInfo> keys;
EXPECT_EQ(OK, fetcher.ObtainKey(ecm_, &asset_id, &keys));
- EXPECT_EQ(2, keys.size());
+ EXPECT_EQ(2U, keys.size());
EXPECT_EQ(0, keys[0].key_id);
EXPECT_EQ(content_key_[0]->size(), keys[0].key_bytes->size());
EXPECT_EQ(0, memcmp(content_key_[0]->data(),
diff --git a/drm/mediacas/plugins/mock/MockCasPlugin.cpp b/drm/mediacas/plugins/mock/MockCasPlugin.cpp
index 500208b..06516b5 100644
--- a/drm/mediacas/plugins/mock/MockCasPlugin.cpp
+++ b/drm/mediacas/plugins/mock/MockCasPlugin.cpp
@@ -49,8 +49,8 @@
status_t MockCasFactory::createPlugin(
int32_t CA_system_id,
- uint64_t appData,
- CasPluginCallback callback,
+ uint64_t /*appData*/,
+ CasPluginCallback /*callback*/,
CasPlugin **plugin) {
if (!isSystemIdSupported(CA_system_id)) {
return BAD_VALUE;
@@ -98,7 +98,7 @@
MockSessionLibrary::get()->destroyPlugin(this);
}
-status_t MockCasPlugin::setPrivateData(const CasData &data) {
+status_t MockCasPlugin::setPrivateData(const CasData& /*data*/) {
ALOGV("setPrivateData");
return OK;
}
@@ -123,7 +123,7 @@
}
status_t MockCasPlugin::setSessionPrivateData(
- const CasSessionId &sessionId, const CasData &data) {
+ const CasSessionId &sessionId, const CasData& /*data*/) {
ALOGV("setSessionPrivateData: sessionId=%s",
arrayToString(sessionId).string());
Mutex::Autolock lock(mLock);
@@ -163,7 +163,7 @@
}
status_t MockCasPlugin::sendEvent(
- int32_t event, int arg, const CasData &eventData) {
+ int32_t event, int /*arg*/, const CasData& /*eventData*/) {
ALOGV("sendEvent: event=%d", event);
Mutex::Autolock lock(mLock);
@@ -178,7 +178,7 @@
}
status_t MockCasPlugin::refreshEntitlements(
- int32_t refreshType, const CasData &refreshData) {
+ int32_t /*refreshType*/, const CasData &refreshData) {
ALOGV("refreshEntitlements: refreshData=%s", arrayToString(refreshData).string());
Mutex::Autolock lock(mLock);
@@ -216,7 +216,7 @@
int32_t srcOffset,
void *dstPtr,
int32_t dstOffset,
- AString *errorDetailMsg) {
+ AString* /*errorDetailMsg*/) {
ALOGV("MockDescramblerPlugin::descramble(secure=%d, sctrl=%d,"
"subSamples=%s, srcPtr=%p, dstPtr=%p, srcOffset=%d, dstOffset=%d)",
(int)secure, (int)scramblingControl,
diff --git a/include/media/AudioClient.h b/include/media/AudioClient.h
index feac9b9..a0530e4 120000
--- a/include/media/AudioClient.h
+++ b/include/media/AudioClient.h
@@ -1 +1 @@
-media/libaudioclient/include/media/AudioClient.h
\ No newline at end of file
+../../media/libaudioclient/include/media/AudioClient.h
\ No newline at end of file
diff --git a/media/extractors/aac/Android.bp b/media/extractors/aac/Android.bp
index 65f9b96..7937a29 100644
--- a/media/extractors/aac/Android.bp
+++ b/media/extractors/aac/Android.bp
@@ -23,6 +23,7 @@
"-Wall",
"-fvisibility=hidden",
],
+ version_script: "exports.lds",
sanitize: {
cfi: true,
diff --git a/media/extractors/aac/exports.lds b/media/extractors/aac/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/aac/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/amr/Android.bp b/media/extractors/amr/Android.bp
index 01bbfa2..e5bbe31 100644
--- a/media/extractors/amr/Android.bp
+++ b/media/extractors/amr/Android.bp
@@ -23,6 +23,7 @@
"-Wall",
"-fvisibility=hidden",
],
+ version_script: "exports.lds",
sanitize: {
cfi: true,
diff --git a/media/extractors/amr/exports.lds b/media/extractors/amr/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/amr/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 80a4125..84ba6d3 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -28,6 +28,7 @@
"-Wall",
"-fvisibility=hidden",
],
+ version_script: "exports.lds",
sanitize: {
cfi: true,
diff --git a/media/extractors/flac/exports.lds b/media/extractors/flac/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/flac/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/midi/Android.bp b/media/extractors/midi/Android.bp
index 68f8766..9af128e 100644
--- a/media/extractors/midi/Android.bp
+++ b/media/extractors/midi/Android.bp
@@ -27,6 +27,7 @@
"-Wall",
"-fvisibility=hidden",
],
+ version_script: "exports.lds",
sanitize: {
cfi: true,
diff --git a/media/extractors/midi/exports.lds b/media/extractors/midi/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/midi/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/mkv/Android.bp b/media/extractors/mkv/Android.bp
index 350c6fe..0301ffa 100644
--- a/media/extractors/mkv/Android.bp
+++ b/media/extractors/mkv/Android.bp
@@ -31,6 +31,7 @@
"-Wall",
"-fvisibility=hidden",
],
+ version_script: "exports.lds",
sanitize: {
cfi: true,
diff --git a/media/extractors/mkv/exports.lds b/media/extractors/mkv/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/mkv/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/mp3/Android.bp b/media/extractors/mp3/Android.bp
index 6912ef1..d93562c 100644
--- a/media/extractors/mp3/Android.bp
+++ b/media/extractors/mp3/Android.bp
@@ -31,6 +31,7 @@
"-Wall",
"-fvisibility=hidden",
],
+ version_script: "exports.lds",
sanitize: {
cfi: true,
diff --git a/media/extractors/mp3/exports.lds b/media/extractors/mp3/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/mp3/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/mp4/Android.bp b/media/extractors/mp4/Android.bp
index 49a3714..fce8dd6 100644
--- a/media/extractors/mp4/Android.bp
+++ b/media/extractors/mp4/Android.bp
@@ -33,6 +33,7 @@
"-Wall",
"-fvisibility=hidden",
],
+ version_script: "exports.lds",
sanitize: {
cfi: true,
diff --git a/media/extractors/mp4/exports.lds b/media/extractors/mp4/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/mp4/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index 50f740b..18f9ee4 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -22,7 +22,6 @@
"liblog",
"libmedia", // Needed for IStreamListener
"libmediaextractor",
- "libstagefright", // Needed for AnotherPacketSource and more
"libstagefright_foundation",
"libutils",
],
@@ -41,6 +40,7 @@
"-Wall",
"-fvisibility=hidden",
],
+ version_script: "exports.lds",
sanitize: {
cfi: true,
diff --git a/media/extractors/mpeg2/exports.lds b/media/extractors/mpeg2/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/mpeg2/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/ogg/Android.bp b/media/extractors/ogg/Android.bp
index 6bd8025..2c09a5f 100644
--- a/media/extractors/ogg/Android.bp
+++ b/media/extractors/ogg/Android.bp
@@ -28,6 +28,7 @@
"-Wall",
"-fvisibility=hidden",
],
+ version_script: "exports.lds",
sanitize: {
cfi: true,
diff --git a/media/extractors/ogg/exports.lds b/media/extractors/ogg/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/ogg/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/wav/Android.bp b/media/extractors/wav/Android.bp
index f310892..65c71ef 100644
--- a/media/extractors/wav/Android.bp
+++ b/media/extractors/wav/Android.bp
@@ -27,6 +27,7 @@
"-Wall",
"-fvisibility=hidden",
],
+ version_script: "exports.lds",
sanitize: {
cfi: true,
diff --git a/media/extractors/wav/exports.lds b/media/extractors/wav/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/wav/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index fc5830a..f709f41 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -291,7 +291,7 @@
const int32_t maxBytesPerFrame = maxChannels * sizeof(float);
// Prevent overflow by limiting multiplicands.
if (bytesPerFrame > maxBytesPerFrame || numFrames > (0x3FFFFFFF / maxBytesPerFrame)) {
- ALOGE("size overflow, numFrames = %d, frameSize = %zd", numFrames, bytesPerFrame);
+ ALOGE("size overflow, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
return AAUDIO_ERROR_OUT_OF_RANGE;
}
*sizeInBytes = numFrames * bytesPerFrame;
diff --git a/media/libaaudio/tests/test_various.cpp b/media/libaaudio/tests/test_various.cpp
index de386da..dc19985 100644
--- a/media/libaaudio/tests/test_various.cpp
+++ b/media/libaaudio/tests/test_various.cpp
@@ -16,17 +16,19 @@
// Test various AAudio features including AAudioStream_setBufferSizeInFrames().
+#include <condition_variable>
+#include <mutex>
#include <stdio.h>
-//#include <stdlib.h>
-//#include <math.h>
#include <android-base/macros.h>
#include <aaudio/AAudio.h>
#include <gtest/gtest.h>
+#include <unistd.h>
+
// Callback function that does nothing.
-aaudio_data_callback_result_t MyDataCallbackProc(
+aaudio_data_callback_result_t NoopDataCallbackProc(
AAudioStream *stream,
void *userData,
void *audioData,
@@ -52,7 +54,7 @@
ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
// Request stream properties.
- AAudioStreamBuilder_setDataCallback(aaudioBuilder, MyDataCallbackProc, nullptr);
+ AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
// Create an AAudioStream using the Builder.
@@ -85,7 +87,7 @@
ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
// Request stream properties.
- AAudioStreamBuilder_setDataCallback(aaudioBuilder, MyDataCallbackProc, nullptr);
+ AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
// Create an AAudioStream using the Builder.
@@ -111,6 +113,7 @@
//int main() { // To fix Android Studio formatting when editing.
TEST(test_various, aaudio_set_buffer_size) {
+
int32_t bufferCapacity;
int32_t framesPerBurst = 0;
int32_t actualSize = 0;
@@ -122,7 +125,7 @@
ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
// Request stream properties.
- AAudioStreamBuilder_setDataCallback(aaudioBuilder, MyDataCallbackProc, nullptr);
+ AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
// Create an AAudioStream using the Builder.
@@ -170,3 +173,155 @@
AAudioStream_close(aaudioStream);
AAudioStreamBuilder_delete(aaudioBuilder);
}
+
+
+// ************************************************************
+// Test to make sure that AAUDIO_CALLBACK_RESULT_STOP works.
+
+// Callback function that counts calls.
+aaudio_data_callback_result_t CallbackOnceProc(
+ AAudioStream *stream,
+ void *userData,
+ void *audioData,
+ int32_t numFrames
+) {
+ (void) stream;
+ (void) audioData;
+ (void) numFrames;
+
+ std::atomic<int32_t> *callbackCountPtr = (std::atomic<int32_t> *)userData;
+ (*callbackCountPtr)++;
+
+ return AAUDIO_CALLBACK_RESULT_STOP;
+}
+
+void checkCallbackOnce(aaudio_performance_mode_t perfMode) {
+
+ std::atomic<int32_t> callbackCount{0};
+
+ AAudioStreamBuilder *aaudioBuilder = nullptr;
+ AAudioStream *aaudioStream = nullptr;
+
+ // Use an AAudioStreamBuilder to contain requested parameters.
+ ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
+
+ // Request stream properties.
+ AAudioStreamBuilder_setDataCallback(aaudioBuilder, CallbackOnceProc, &callbackCount);
+ AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
+
+ // Create an AAudioStream using the Builder.
+ ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
+ AAudioStreamBuilder_delete(aaudioBuilder);
+
+ ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
+
+ sleep(1); // Give callback a chance to run many times.
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
+
+ EXPECT_EQ(1, callbackCount.load()); // should stop after first call
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
+}
+
+TEST(test_various, aaudio_callback_once_none) {
+ checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_NONE);
+}
+
+TEST(test_various, aaudio_callback_once_lowlat) {
+ checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+}
+
+// ************************************************************
+struct WakeUpCallbackData {
+ void wakeOther() {
+ // signal waiting test to wake up
+ {
+ std::lock_guard <std::mutex> lock(mutex);
+ finished = true;
+ }
+ conditionVariable.notify_one();
+ }
+
+ void waitForFinished() {
+ std::unique_lock <std::mutex> aLock(mutex);
+ conditionVariable.wait(aLock, [=] { return finished; });
+ }
+
+ // For signalling foreground test when callback finished
+ std::mutex mutex;
+ std::condition_variable conditionVariable;
+ bool finished = false;
+};
+
+// Test to make sure we cannot call recursively into the system from a callback.
+struct DangerousData : public WakeUpCallbackData {
+ aaudio_result_t resultStart = AAUDIO_OK;
+ aaudio_result_t resultStop = AAUDIO_OK;
+ aaudio_result_t resultPause = AAUDIO_OK;
+ aaudio_result_t resultFlush = AAUDIO_OK;
+ aaudio_result_t resultClose = AAUDIO_OK;
+};
+
+// Callback function that tries to call back into the stream.
+aaudio_data_callback_result_t DangerousDataCallbackProc(
+ AAudioStream *stream,
+ void *userData,
+ void *audioData,
+ int32_t numFrames) {
+ (void) audioData;
+ (void) numFrames;
+
+ DangerousData *data = (DangerousData *)userData;
+ data->resultStart = AAudioStream_requestStart(stream);
+ data->resultStop = AAudioStream_requestStop(stream);
+ data->resultPause = AAudioStream_requestPause(stream);
+ data->resultFlush = AAudioStream_requestFlush(stream);
+ data->resultClose = AAudioStream_close(stream);
+
+ data->wakeOther();
+
+ return AAUDIO_CALLBACK_RESULT_STOP;
+}
+
+//int main() { // To fix Android Studio formatting when editing.
+void checkDangerousCallback(aaudio_performance_mode_t perfMode) {
+ DangerousData dangerousData;
+ AAudioStreamBuilder *aaudioBuilder = nullptr;
+ AAudioStream *aaudioStream = nullptr;
+
+ // Use an AAudioStreamBuilder to contain requested parameters.
+ ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
+
+ // Request stream properties.
+ AAudioStreamBuilder_setDataCallback(aaudioBuilder, DangerousDataCallbackProc, &dangerousData);
+ AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
+
+ // Create an AAudioStream using the Builder.
+ ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
+ AAudioStreamBuilder_delete(aaudioBuilder);
+
+ ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
+
+ dangerousData.waitForFinished();
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
+
+ EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStart);
+ EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStop);
+ EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultPause);
+ EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultFlush);
+ EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultClose);
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
+}
+
+//int main() { // To fix Android Studio formatting when editing.
+
+TEST(test_various, aaudio_callback_blockers_none) {
+ checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_NONE);
+}
+
+TEST(test_various, aaudio_callback_blockers_lowlat) {
+ checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+}
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 95e95de..d18f611 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -180,7 +180,6 @@
],
shared_libs: [
- "libui",
"liblog",
"libcutils",
"libutils",
@@ -196,8 +195,6 @@
"libdl",
"libaudioutils",
"libaudioclient",
- "libhidlbase",
- "libhidltransport",
"libmedia_omx",
],
diff --git a/media/libmedia/MediaPlayer2Factory.cpp b/media/libmedia/MediaPlayer2Factory.cpp
index ca7b96f..d6aab70 100644
--- a/media/libmedia/MediaPlayer2Factory.cpp
+++ b/media/libmedia/MediaPlayer2Factory.cpp
@@ -126,8 +126,8 @@
sp<MediaPlayer2Base> MediaPlayer2Factory::createPlayer(
player2_type playerType,
- void* cookie,
- notify_callback_f notifyFunc,
+ const wp<MediaPlayer2Engine> &client,
+ MediaPlayer2Base::NotifyCallback notifyFunc,
pid_t pid) {
sp<MediaPlayer2Base> p;
IFactory* factory;
@@ -152,7 +152,7 @@
init_result = p->initCheck();
if (init_result == NO_ERROR) {
- p->setNotifyCallback(cookie, notifyFunc);
+ p->setNotifyCallback(client, notifyFunc);
} else {
ALOGE("Failed to create player object of type %d, initCheck failed"
" (res = %d)", playerType, init_result);
diff --git a/media/libmedia/MediaPlayer2Factory.h b/media/libmedia/MediaPlayer2Factory.h
index 5813b2e..799b5f3 100644
--- a/media/libmedia/MediaPlayer2Factory.h
+++ b/media/libmedia/MediaPlayer2Factory.h
@@ -65,8 +65,8 @@
const sp<DataSource> &source);
static sp<MediaPlayer2Base> createPlayer(player2_type playerType,
- void* cookie,
- notify_callback_f notifyFunc,
+ const wp<MediaPlayer2Engine> &client,
+ MediaPlayer2Base::NotifyCallback notifyFunc,
pid_t pid);
static void registerBuiltinFactories();
diff --git a/media/libmedia/MediaPlayer2Manager.cpp b/media/libmedia/MediaPlayer2Manager.cpp
index 9b7f98a..637214e 100644
--- a/media/libmedia/MediaPlayer2Manager.cpp
+++ b/media/libmedia/MediaPlayer2Manager.cpp
@@ -1258,12 +1258,13 @@
}
void MediaPlayer2Manager::Client::notify(
- void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
+ const wp<MediaPlayer2Engine> &listener, int msg, int ext1, int ext2, const Parcel *obj)
{
- Client* client = static_cast<Client*>(cookie);
- if (client == NULL) {
+ sp<MediaPlayer2Engine> spListener = listener.promote();
+ if (spListener == NULL) {
return;
}
+ Client* client = static_cast<Client*>(spListener.get());
sp<MediaPlayer2EngineClient> c;
sp<Client> nextClient;
@@ -1311,7 +1312,7 @@
}
if (c != NULL) {
- ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
+ ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, spListener.get(), msg, ext1, ext2);
c->notify(msg, ext1, ext2, obj);
}
}
@@ -1405,7 +1406,9 @@
#if CALLBACK_ANTAGONIZER
const int Antagonizer::interval = 10000; // 10 msecs
-Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
+Antagonizer::Antagonizer(
+ MediaPlayer2Manager::NotifyCallback cb,
+ const wp<MediaPlayer2Engine> &client) :
mExit(false), mActive(false), mClient(client), mCb(cb)
{
createThread(callbackThread, this);
diff --git a/media/libmedia/MediaPlayer2Manager.h b/media/libmedia/MediaPlayer2Manager.h
index b346f40..8f0c491 100644
--- a/media/libmedia/MediaPlayer2Manager.h
+++ b/media/libmedia/MediaPlayer2Manager.h
@@ -46,20 +46,22 @@
#if CALLBACK_ANTAGONIZER
class Antagonizer {
public:
- Antagonizer(notify_callback_f cb, void* client);
+ Antagonizer(
+ MediaPlayer2Base::NotifyCallback cb,
+ const wp<MediaPlayer2Engine> &client);
void start() { mActive = true; }
void stop() { mActive = false; }
void kill();
private:
static const int interval;
Antagonizer();
- static int callbackThread(void* cookie);
- Mutex mLock;
- Condition mCondition;
- bool mExit;
- bool mActive;
- void* mClient;
- notify_callback_f mCb;
+ static int callbackThread(void *cookie);
+ Mutex mLock;
+ Condition mCondition;
+ bool mExit;
+ bool mActive;
+ wp<MediaPlayer2Engine> mClient;
+ MediaPlayer2Base::NotifyCallback mCb;
};
#endif
@@ -301,7 +303,7 @@
status_t setDataSource_post(const sp<MediaPlayer2Base>& p,
status_t status);
- static void notify(void* cookie, int msg,
+ static void notify(const wp<MediaPlayer2Engine> &listener, int msg,
int ext1, int ext2, const Parcel *obj);
pid_t pid() const { return mPid; }
diff --git a/media/libmedia/include/media/MediaHTTPConnection.h b/media/libmedia/include/media/MediaHTTPConnection.h
index 82a79e5..17813a2 100644
--- a/media/libmedia/include/media/MediaHTTPConnection.h
+++ b/media/libmedia/include/media/MediaHTTPConnection.h
@@ -20,6 +20,8 @@
#include <media/stagefright/foundation/ABase.h>
#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
namespace android {
diff --git a/media/libmedia/include/media/MediaPlayer2Interface.h b/media/libmedia/include/media/MediaPlayer2Interface.h
index bd1146d..7c8e3e6 100644
--- a/media/libmedia/include/media/MediaPlayer2Interface.h
+++ b/media/libmedia/include/media/MediaPlayer2Interface.h
@@ -25,13 +25,14 @@
#include <utils/String8.h>
#include <utils/RefBase.h>
-#include <media/mediaplayer2.h>
#include <media/AudioResamplerPublic.h>
#include <media/AudioSystem.h>
#include <media/AudioTimestamp.h>
#include <media/AVSyncSettings.h>
#include <media/BufferingSettings.h>
#include <media/Metadata.h>
+#include <media/mediaplayer2.h>
+#include <media/stagefright/foundation/AHandler.h>
// Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
// global, and not in android::
@@ -67,14 +68,14 @@
// duration below which we do not allow deep audio buffering
#define AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US 5000000
-// callback mechanism for passing messages to MediaPlayer2 object
-typedef void (*notify_callback_f)(void* cookie,
- int msg, int ext1, int ext2, const Parcel *obj);
-
// abstract base class - use MediaPlayer2Interface
-class MediaPlayer2Base : public RefBase
+class MediaPlayer2Base : public AHandler
{
public:
+ // callback mechanism for passing messages to MediaPlayer2 object
+ typedef void (*NotifyCallback)(const wp<MediaPlayer2Engine> &listener,
+ int msg, int ext1, int ext2, const Parcel *obj);
+
// AudioSink: abstraction layer for audio output
class AudioSink : public RefBase {
public:
@@ -158,7 +159,7 @@
virtual status_t enableAudioDeviceCallback(bool enabled);
};
- MediaPlayer2Base() : mCookie(0), mNotify(0) {}
+ MediaPlayer2Base() : mClient(0), mNotify(0) {}
virtual ~MediaPlayer2Base() {}
virtual status_t initCheck() = 0;
virtual bool hardwareOutput() = 0;
@@ -272,28 +273,30 @@
};
void setNotifyCallback(
- void* cookie, notify_callback_f notifyFunc) {
+ const wp<MediaPlayer2Engine> &client, NotifyCallback notifyFunc) {
Mutex::Autolock autoLock(mNotifyLock);
- mCookie = cookie; mNotify = notifyFunc;
+ mClient = client; mNotify = notifyFunc;
}
void sendEvent(int msg, int ext1=0, int ext2=0,
const Parcel *obj=NULL) {
- notify_callback_f notifyCB;
- void* cookie;
+ NotifyCallback notifyCB;
+ wp<MediaPlayer2Engine> client;
{
Mutex::Autolock autoLock(mNotifyLock);
notifyCB = mNotify;
- cookie = mCookie;
+ client = mClient;
}
- if (notifyCB) notifyCB(cookie, msg, ext1, ext2, obj);
+ if (notifyCB) notifyCB(client, msg, ext1, ext2, obj);
}
virtual status_t dump(int /* fd */, const Vector<String16>& /* args */) const {
return INVALID_OPERATION;
}
+ virtual void onMessageReceived(const sp<AMessage> & /* msg */) override { }
+
// Modular DRM
virtual status_t prepareDrm(const uint8_t /* uuid */[16], const Vector<uint8_t>& /* drmSessionId */) {
return INVALID_OPERATION;
@@ -305,9 +308,9 @@
private:
friend class MediaPlayer2Manager;
- Mutex mNotifyLock;
- void* mCookie;
- notify_callback_f mNotify;
+ Mutex mNotifyLock;
+ wp<MediaPlayer2Engine> mClient;
+ NotifyCallback mNotify;
};
// Implement this class for media players that use the AudioFlinger software mixer
diff --git a/media/libmedia/nuplayer2/GenericSource.cpp b/media/libmedia/nuplayer2/GenericSource.cpp
index 900c78b..6f78b6b 100644
--- a/media/libmedia/nuplayer2/GenericSource.cpp
+++ b/media/libmedia/nuplayer2/GenericSource.cpp
@@ -162,15 +162,30 @@
status_t NuPlayer2::GenericSource::initFromDataSource() {
sp<IMediaExtractor> extractor;
- CHECK(mDataSource != NULL);
+ CHECK(mDataSource != NULL || mFd != -1);
sp<DataSource> dataSource = mDataSource;
+ const int fd = mFd;
+ const int64_t offset = mOffset;
+ const int64_t length = mLength;
mLock.unlock();
// This might take long time if data source is not reliable.
- extractor = MediaExtractorFactory::Create(dataSource, NULL);
+ if (dataSource != nullptr) {
+ extractor = MediaExtractorFactory::Create(dataSource, NULL /* mime */);
+ } else {
+ extractor = MediaExtractorFactory::CreateFromFd(
+ fd, offset, length, NULL /* mime */, &dataSource);
+ }
+
+ if (dataSource == nullptr) {
+ ALOGE("initFromDataSource, failed to create data source!");
+ mLock.lock();
+ return UNKNOWN_ERROR;
+ }
if (extractor == NULL) {
ALOGE("initFromDataSource, cannot create extractor!");
+ mLock.lock();
return UNKNOWN_ERROR;
}
@@ -179,10 +194,13 @@
size_t numtracks = extractor->countTracks();
if (numtracks == 0) {
ALOGE("initFromDataSource, source has no track!");
+ mLock.lock();
return UNKNOWN_ERROR;
}
mLock.lock();
+ mFd = -1;
+ mDataSource = dataSource;
mFileMeta = fileMeta;
if (mFileMeta != NULL) {
int64_t duration;
@@ -395,51 +413,16 @@
if (!mDisconnected) {
mDataSource = dataSource;
}
- } else {
- if (property_get_bool("media.stagefright.extractremote", true) &&
- !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
- sp<IBinder> binder =
- defaultServiceManager()->getService(String16("media.extractor"));
- if (binder != nullptr) {
- ALOGD("FileSource remote");
- sp<IMediaExtractorService> mediaExService(
- interface_cast<IMediaExtractorService>(binder));
- sp<IDataSource> source =
- mediaExService->makeIDataSource(mFd, mOffset, mLength);
- ALOGV("IDataSource(FileSource): %p %d %lld %lld",
- source.get(), mFd, (long long)mOffset, (long long)mLength);
- if (source.get() != nullptr) {
- mDataSource = CreateDataSourceFromIDataSource(source);
- if (mDataSource != nullptr) {
- // Close the local file descriptor as it is not needed anymore.
- close(mFd);
- mFd = -1;
- }
- } else {
- ALOGW("extractor service cannot make data source");
- }
- } else {
- ALOGW("extractor service not running");
- }
- }
- if (mDataSource == nullptr) {
- ALOGD("FileSource local");
- mDataSource = new FileSource(mFd, mOffset, mLength);
- }
- // TODO: close should always be done on mFd, see the lines following
- // CreateDataSourceFromIDataSource above,
- // and the FileSource constructor should dup the mFd argument as needed.
- mFd = -1;
}
- if (mDataSource == NULL) {
+ if (mFd == -1 && mDataSource == NULL) {
ALOGE("Failed to create data source!");
notifyPreparedAndCleanup(UNKNOWN_ERROR);
return;
}
}
- if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
+ if (mDataSource != nullptr && mDataSource->flags() & DataSource::kIsCachingDataSource) {
mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
}
diff --git a/media/libmedia/nuplayer2/NuPlayer2Decoder.cpp b/media/libmedia/nuplayer2/NuPlayer2Decoder.cpp
index 18207b0..d78a8e8 100644
--- a/media/libmedia/nuplayer2/NuPlayer2Decoder.cpp
+++ b/media/libmedia/nuplayer2/NuPlayer2Decoder.cpp
@@ -766,6 +766,8 @@
reply->setInt32("eos", true);
}
+ mNumFramesTotal += !mIsAudio;
+
if (mSkipRenderingUntilMediaTimeUs >= 0) {
if (timeUs < mSkipRenderingUntilMediaTimeUs) {
ALOGV("[%s] dropping buffer at time %lld as requested.",
@@ -784,8 +786,6 @@
mSkipRenderingUntilMediaTimeUs = -1;
}
- mNumFramesTotal += !mIsAudio;
-
// wait until 1st frame comes out to signal resume complete
notifyResumeCompleteIfNecessary();
diff --git a/media/libmedia/nuplayer2/NuPlayer2Driver.cpp b/media/libmedia/nuplayer2/NuPlayer2Driver.cpp
index c0f0bad..dd0da8a 100644
--- a/media/libmedia/nuplayer2/NuPlayer2Driver.cpp
+++ b/media/libmedia/nuplayer2/NuPlayer2Driver.cpp
@@ -41,7 +41,7 @@
namespace android {
// key for media statistics
-static const char *kKeyPlayer = "nuplayer";
+static const char *kKeyPlayer = "nuplayer2";
// attrs for media statistics
static const char *kPlayerVMime = "android.media.mediaplayer.video.mime";
static const char *kPlayerVCodec = "android.media.mediaplayer.video.codec";
@@ -55,6 +55,7 @@
static const char *kPlayerPlaying = "android.media.mediaplayer.playingMs";
static const char *kPlayerError = "android.media.mediaplayer.err";
static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
+static const char *kPlayerErrorState = "android.media.mediaplayer.errstate";
static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
//
static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
@@ -75,6 +76,7 @@
mRebufferingEvents(0),
mRebufferingAtExit(false),
mLooper(new ALooper),
+ mNuPlayer2Looper(new ALooper),
mMediaClock(new MediaClock),
mPlayer(new NuPlayer2(pid, mMediaClock)),
mPlayerFlags(0),
@@ -85,6 +87,7 @@
mAutoLoop(false) {
ALOGD("NuPlayer2Driver(%p) created, clientPid(%d)", this, pid);
mLooper->setName("NuPlayer2Driver Looper");
+ mNuPlayer2Looper->setName("NuPlayer2 Looper");
mMediaClock->init();
@@ -92,18 +95,19 @@
mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
mAnalyticsItem->generateSessionID();
- mLooper->start(
+ mNuPlayer2Looper->start(
false, /* runOnCallingThread */
true, /* canCallJava */
PRIORITY_AUDIO);
- mLooper->registerHandler(mPlayer);
+ mNuPlayer2Looper->registerHandler(mPlayer);
mPlayer->setDriver(this);
}
NuPlayer2Driver::~NuPlayer2Driver() {
ALOGV("~NuPlayer2Driver(%p)", this);
+ mNuPlayer2Looper->stop();
mLooper->stop();
// finalize any pending metrics, usually a no-op.
@@ -117,6 +121,12 @@
}
status_t NuPlayer2Driver::initCheck() {
+ mLooper->start(
+ false, /* runOnCallingThread */
+ true, /* canCallJava */
+ PRIORITY_AUDIO);
+
+ mLooper->registerHandler(this);
return OK;
}
@@ -381,7 +391,7 @@
case STATE_PAUSED:
mState = STATE_STOPPED;
- notifyListener_l(MEDIA2_STOPPED);
+ sendNotifyOnLooper(MEDIA2_STOPPED);
break;
case STATE_PREPARED:
@@ -416,7 +426,7 @@
case STATE_RUNNING:
mState = STATE_PAUSED;
- notifyListener_l(MEDIA2_PAUSED);
+ sendNotifyOnLooper(MEDIA2_PAUSED);
mPlayer->pause();
break;
@@ -440,7 +450,7 @@
Mutex::Autolock autoLock(mLock);
if (rate.mSpeed == 0.f && mState == STATE_RUNNING) {
mState = STATE_PAUSED;
- notifyListener_l(MEDIA2_PAUSED);
+ sendNotifyOnLooper(MEDIA2_PAUSED);
} else if (rate.mSpeed != 0.f
&& (mState == STATE_PAUSED
|| mState == STATE_STOPPED_AND_PREPARED
@@ -478,7 +488,7 @@
mAtEOS = false;
mSeekInProgress = true;
// seeks can take a while, so we essentially paused
- notifyListener_l(MEDIA2_PAUSED);
+ sendNotifyOnLooper(MEDIA2_PAUSED);
mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
break;
}
@@ -651,7 +661,7 @@
{
CHECK(mIsAsyncPrepare);
- notifyListener_l(MEDIA2_PREPARED);
+ sendNotifyOnLooper(MEDIA2_PREPARED);
break;
}
@@ -660,7 +670,7 @@
}
if (mState != STATE_STOPPED) {
- notifyListener_l(MEDIA2_STOPPED);
+ sendNotifyOnLooper(MEDIA2_STOPPED);
}
mState = STATE_RESET_IN_PROGRESS;
@@ -704,7 +714,7 @@
int32_t methodId;
status_t ret = request.readInt32(&methodId);
if (ret != OK) {
- ALOGE("Failed to retrieve the requested method to invoke");
+ ALOGE("Failed to retrieve the requested method to invoke, err(%d)", ret);
return ret;
}
@@ -939,6 +949,19 @@
return OK;
}
+void NuPlayer2Driver::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatNotifyListener: {
+ int32_t msgId;
+ CHECK(msg->findInt32("messageId", &msgId));
+ notifyListener(msgId);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
void NuPlayer2Driver::notifyListener(
int msg, int ext1, int ext2, const Parcel *in) {
Mutex::Autolock autoLock(mLock);
@@ -993,6 +1016,7 @@
if (ext2 != 0) {
mAnalyticsItem->setInt32(kPlayerErrorCode, ext2);
}
+ mAnalyticsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
}
mAtEOS = true;
break;
@@ -1007,6 +1031,12 @@
mLock.lock();
}
+void NuPlayer2Driver::sendNotifyOnLooper(int msgId) {
+ sp<AMessage> msg = new AMessage(kWhatNotifyListener, this);
+ msg->setInt32("messageId", msgId);
+ msg->post();
+}
+
void NuPlayer2Driver::notifySetDataSourceCompleted(status_t err) {
Mutex::Autolock autoLock(mLock);
@@ -1089,4 +1119,30 @@
return ret;
}
+std::string NuPlayer2Driver::stateString(State state) {
+ const char *rval = NULL;
+ char rawbuffer[16]; // allows "%d"
+
+ switch (state) {
+ case STATE_IDLE: rval = "IDLE"; break;
+ case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
+ case STATE_UNPREPARED: rval = "UNPREPARED"; break;
+ case STATE_PREPARING: rval = "PREPARING"; break;
+ case STATE_PREPARED: rval = "PREPARED"; break;
+ case STATE_RUNNING: rval = "RUNNING"; break;
+ case STATE_PAUSED: rval = "PAUSED"; break;
+ case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
+ case STATE_STOPPED: rval = "STOPPED"; break;
+ case STATE_STOPPED_AND_PREPARING: rval = "STOPPED_AND_PREPARING"; break;
+ case STATE_STOPPED_AND_PREPARED: rval = "STOPPED_AND_PREPARED"; break;
+ default:
+ // yes, this buffer is shared and vulnerable to races
+ snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
+ rval = rawbuffer;
+ break;
+ }
+
+ return rval;
+}
+
} // namespace android
diff --git a/media/libmedia/nuplayer2/NuPlayer2Driver.h b/media/libmedia/nuplayer2/NuPlayer2Driver.h
index edd4556..0028d05 100644
--- a/media/libmedia/nuplayer2/NuPlayer2Driver.h
+++ b/media/libmedia/nuplayer2/NuPlayer2Driver.h
@@ -78,6 +78,8 @@
virtual status_t dump(int fd, const Vector<String16> &args) const;
+ virtual void onMessageReceived(const sp<AMessage> &msg) override;
+
void notifySetDataSourceCompleted(status_t err);
void notifyPrepareCompleted(status_t err);
void notifyResetComplete();
@@ -113,6 +115,12 @@
STATE_STOPPED_AND_PREPARED, // equivalent to PAUSED, but seek complete
};
+ std::string stateString(State state);
+
+ enum {
+ kWhatNotifyListener,
+ };
+
mutable Mutex mLock;
Condition mCondition;
@@ -134,6 +142,7 @@
// <<<
sp<ALooper> mLooper;
+ sp<ALooper> mNuPlayer2Looper;
const sp<MediaClock> mMediaClock;
const sp<NuPlayer2> mPlayer;
sp<AudioSink> mAudioSink;
@@ -146,13 +155,13 @@
bool mLooping;
bool mAutoLoop;
-
void updateMetrics(const char *where);
void logMetrics(const char *where);
status_t prepare_l();
status_t start_l();
void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL);
+ void sendNotifyOnLooper(int msgId);
DISALLOW_EVIL_CONSTRUCTORS(NuPlayer2Driver);
};
diff --git a/media/libmediaextractor/DataSource.cpp b/media/libmediaextractor/DataSource.cpp
index c22e4cb..72959c6 100644
--- a/media/libmediaextractor/DataSource.cpp
+++ b/media/libmediaextractor/DataSource.cpp
@@ -17,7 +17,6 @@
#define LOG_TAG "DataSource"
#include <media/DataSource.h>
-#include <media/IDataSource.h>
#include <media/stagefright/foundation/ByteUtils.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/String8.h>
@@ -124,10 +123,6 @@
return ERROR_UNSUPPORTED;
}
-sp<IDataSource> DataSource::getIDataSource() const {
- return nullptr;
-}
-
String8 DataSource::getMIMEType() const {
return String8("application/octet-stream");
}
diff --git a/media/libmediaextractor/include/media/DataSource.h b/media/libmediaextractor/include/media/DataSource.h
index e917f4e..0b4bc27 100644
--- a/media/libmediaextractor/include/media/DataSource.h
+++ b/media/libmediaextractor/include/media/DataSource.h
@@ -112,9 +112,6 @@
virtual void close() {};
- // returns a pointer to IDataSource if it is wrapped.
- virtual sp<IDataSource> getIDataSource() const;
-
protected:
virtual ~DataSource() {}
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp
index 055d5ab..3209c6d 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.cpp
+++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp
@@ -126,7 +126,7 @@
sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
player_type playerType,
- void* cookie,
+ const wp<IMediaPlayer> &client,
notify_callback_f notifyFunc,
pid_t pid) {
sp<MediaPlayerBase> p;
@@ -152,7 +152,7 @@
init_result = p->initCheck();
if (init_result == NO_ERROR) {
- p->setNotifyCallback(cookie, notifyFunc);
+ p->setNotifyCallback(client, notifyFunc);
} else {
ALOGE("Failed to create player object of type %d, initCheck failed"
" (res = %d)", playerType, init_result);
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.h b/media/libmediaplayerservice/MediaPlayerFactory.h
index e22a56f..6aedeb2 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.h
+++ b/media/libmediaplayerservice/MediaPlayerFactory.h
@@ -65,7 +65,7 @@
const sp<DataSource> &source);
static sp<MediaPlayerBase> createPlayer(player_type playerType,
- void* cookie,
+ const wp<IMediaPlayer> &client,
notify_callback_f notifyFunc,
pid_t pid);
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 495c418..88221ed 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1421,12 +1421,13 @@
}
void MediaPlayerService::Client::notify(
- void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
+ const wp<IMediaPlayer> &listener, int msg, int ext1, int ext2, const Parcel *obj)
{
- Client* client = static_cast<Client*>(cookie);
- if (client == NULL) {
+ sp<IMediaPlayer> spListener = listener.promote();
+ if (spListener == NULL) {
return;
}
+ Client* client = static_cast<Client*>(spListener.get());
sp<IMediaPlayerClient> c;
sp<Client> nextClient;
@@ -1474,7 +1475,7 @@
}
if (c != NULL) {
- ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
+ ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, spListener.get(), msg, ext1, ext2);
c->notify(msg, ext1, ext2, obj);
}
}
@@ -1568,7 +1569,7 @@
#if CALLBACK_ANTAGONIZER
const int Antagonizer::interval = 10000; // 10 msecs
-Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
+Antagonizer::Antagonizer(notify_callback_f cb, const wp<IMediaPlayer> &client) :
mExit(false), mActive(false), mClient(client), mCb(cb)
{
createThread(callbackThread, this);
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index eefdd7d..58efa8c 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -51,7 +51,7 @@
#if CALLBACK_ANTAGONIZER
class Antagonizer {
public:
- Antagonizer(notify_callback_f cb, void* client);
+ Antagonizer(notify_callback_f cb, const wp<IMediaPlayer> &client);
void start() { mActive = true; }
void stop() { mActive = false; }
void kill();
@@ -63,7 +63,7 @@
Condition mCondition;
bool mExit;
bool mActive;
- void* mClient;
+ wp<IMediaPlayer> mClient;
notify_callback_f mCb;
};
#endif
@@ -377,7 +377,7 @@
status_t setDataSource_post(const sp<MediaPlayerBase>& p,
status_t status);
- static void notify(void* cookie, int msg,
+ static void notify(const wp<IMediaPlayer> &cookie, int msg,
int ext1, int ext2, const Parcel *obj);
pid_t pid() const { return mPid; }
diff --git a/media/libmediaplayerservice/include/MediaPlayerInterface.h b/media/libmediaplayerservice/include/MediaPlayerInterface.h
index a03884f..4b33e61 100644
--- a/media/libmediaplayerservice/include/MediaPlayerInterface.h
+++ b/media/libmediaplayerservice/include/MediaPlayerInterface.h
@@ -67,7 +67,7 @@
#define AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US 5000000
// callback mechanism for passing messages to MediaPlayer object
-typedef void (*notify_callback_f)(void* cookie,
+typedef void (*notify_callback_f)(const wp<IMediaPlayer> &listener,
int msg, int ext1, int ext2, const Parcel *obj);
// abstract base class - use MediaPlayerInterface
@@ -157,7 +157,7 @@
virtual status_t enableAudioDeviceCallback(bool enabled);
};
- MediaPlayerBase() : mCookie(0), mNotify(0) {}
+ MediaPlayerBase() : mClient(0), mNotify(0) {}
virtual ~MediaPlayerBase() {}
virtual status_t initCheck() = 0;
virtual bool hardwareOutput() = 0;
@@ -271,22 +271,22 @@
};
void setNotifyCallback(
- void* cookie, notify_callback_f notifyFunc) {
+ const wp<IMediaPlayer> &client, notify_callback_f notifyFunc) {
Mutex::Autolock autoLock(mNotifyLock);
- mCookie = cookie; mNotify = notifyFunc;
+ mClient = client; mNotify = notifyFunc;
}
void sendEvent(int msg, int ext1=0, int ext2=0,
const Parcel *obj=NULL) {
notify_callback_f notifyCB;
- void* cookie;
+ wp<IMediaPlayer> client;
{
Mutex::Autolock autoLock(mNotifyLock);
notifyCB = mNotify;
- cookie = mCookie;
+ client = mClient;
}
- if (notifyCB) notifyCB(cookie, msg, ext1, ext2, obj);
+ if (notifyCB) notifyCB(client, msg, ext1, ext2, obj);
}
virtual status_t dump(int /* fd */, const Vector<String16>& /* args */) const {
@@ -305,7 +305,7 @@
friend class MediaPlayerService;
Mutex mNotifyLock;
- void* mCookie;
+ wp<IMediaPlayer> mClient;
notify_callback_f mNotify;
};
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index a3f4efb..cbbf34d 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -26,7 +26,6 @@
#include <media/DataSource.h>
#include <media/MediaExtractor.h>
#include <media/MediaSource.h>
-#include <media/IMediaExtractorService.h>
#include <media/IMediaHTTPService.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -161,15 +160,30 @@
status_t NuPlayer::GenericSource::initFromDataSource() {
sp<IMediaExtractor> extractor;
- CHECK(mDataSource != NULL);
+ CHECK(mDataSource != NULL || mFd != -1);
sp<DataSource> dataSource = mDataSource;
+ const int fd = mFd;
+ const int64_t offset = mOffset;
+ const int64_t length = mLength;
mLock.unlock();
// This might take long time if data source is not reliable.
- extractor = MediaExtractorFactory::Create(dataSource, NULL);
+ if (dataSource != nullptr) {
+ extractor = MediaExtractorFactory::Create(dataSource, NULL /* mime */);
+ } else {
+ extractor = MediaExtractorFactory::CreateFromFd(
+ fd, offset, length, NULL /* mime */, &dataSource);
+ }
+
+ if (dataSource == nullptr) {
+ ALOGE("initFromDataSource, failed to create data source!");
+ mLock.lock();
+ return UNKNOWN_ERROR;
+ }
if (extractor == NULL) {
ALOGE("initFromDataSource, cannot create extractor!");
+ mLock.lock();
return UNKNOWN_ERROR;
}
@@ -178,10 +192,13 @@
size_t numtracks = extractor->countTracks();
if (numtracks == 0) {
ALOGE("initFromDataSource, source has no track!");
+ mLock.lock();
return UNKNOWN_ERROR;
}
mLock.lock();
+ mFd = -1;
+ mDataSource = dataSource;
mFileMeta = fileMeta;
if (mFileMeta != NULL) {
int64_t duration;
@@ -394,51 +411,15 @@
if (!mDisconnected) {
mDataSource = dataSource;
}
- } else {
- if (property_get_bool("media.stagefright.extractremote", true) &&
- !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
- sp<IBinder> binder =
- defaultServiceManager()->getService(String16("media.extractor"));
- if (binder != nullptr) {
- ALOGD("FileSource remote");
- sp<IMediaExtractorService> mediaExService(
- interface_cast<IMediaExtractorService>(binder));
- sp<IDataSource> source =
- mediaExService->makeIDataSource(mFd, mOffset, mLength);
- ALOGV("IDataSource(FileSource): %p %d %lld %lld",
- source.get(), mFd, (long long)mOffset, (long long)mLength);
- if (source.get() != nullptr) {
- mDataSource = CreateDataSourceFromIDataSource(source);
- if (mDataSource != nullptr) {
- // Close the local file descriptor as it is not needed anymore.
- close(mFd);
- mFd = -1;
- }
- } else {
- ALOGW("extractor service cannot make data source");
- }
- } else {
- ALOGW("extractor service not running");
- }
- }
- if (mDataSource == nullptr) {
- ALOGD("FileSource local");
- mDataSource = new FileSource(mFd, mOffset, mLength);
- }
- // TODO: close should always be done on mFd, see the lines following
- // CreateDataSourceFromIDataSource above,
- // and the FileSource constructor should dup the mFd argument as needed.
- mFd = -1;
}
-
- if (mDataSource == NULL) {
+ if (mFd == -1 && mDataSource == NULL) {
ALOGE("Failed to create data source!");
notifyPreparedAndCleanup(UNKNOWN_ERROR);
return;
}
}
- if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
+ if (mDataSource != nullptr && mDataSource->flags() & DataSource::kIsCachingDataSource) {
mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index a84d0e5..1b02adb 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -752,6 +752,8 @@
reply->setInt32("eos", true);
}
+ mNumFramesTotal += !mIsAudio;
+
if (mSkipRenderingUntilMediaTimeUs >= 0) {
if (timeUs < mSkipRenderingUntilMediaTimeUs) {
ALOGV("[%s] dropping buffer at time %lld as requested.",
@@ -770,8 +772,6 @@
mSkipRenderingUntilMediaTimeUs = -1;
}
- mNumFramesTotal += !mIsAudio;
-
// wait until 1st frame comes out to signal resume complete
notifyResumeCompleteIfNecessary();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index ebf57c6..8aa06fc 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -55,6 +55,7 @@
static const char *kPlayerPlaying = "android.media.mediaplayer.playingMs";
static const char *kPlayerError = "android.media.mediaplayer.err";
static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
+static const char *kPlayerErrorState = "android.media.mediaplayer.errstate";
static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
//
static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
@@ -993,6 +994,7 @@
if (ext2 != 0) {
mAnalyticsItem->setInt32(kPlayerErrorCode, ext2);
}
+ mAnalyticsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
}
mAtEOS = true;
break;
@@ -1089,4 +1091,30 @@
return ret;
}
+std::string NuPlayerDriver::stateString(State state) {
+ const char *rval = NULL;
+ char rawbuffer[16]; // allows "%d"
+
+ switch (state) {
+ case STATE_IDLE: rval = "IDLE"; break;
+ case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
+ case STATE_UNPREPARED: rval = "UNPREPARED"; break;
+ case STATE_PREPARING: rval = "PREPARING"; break;
+ case STATE_PREPARED: rval = "PREPARED"; break;
+ case STATE_RUNNING: rval = "RUNNING"; break;
+ case STATE_PAUSED: rval = "PAUSED"; break;
+ case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
+ case STATE_STOPPED: rval = "STOPPED"; break;
+ case STATE_STOPPED_AND_PREPARING: rval = "STOPPED_AND_PREPARING"; break;
+ case STATE_STOPPED_AND_PREPARED: rval = "STOPPED_AND_PREPARED"; break;
+ default:
+ // yes, this buffer is shared and vulnerable to races
+ snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
+ rval = rawbuffer;
+ break;
+ }
+
+ return rval;
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 13b46c3..ad878f8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -113,6 +113,8 @@
STATE_STOPPED_AND_PREPARED, // equivalent to PAUSED, but seek complete
};
+ std::string stateString(State state);
+
mutable Mutex mLock;
Condition mCondition;
diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp
index 6dfe2de..f479644 100644
--- a/media/libstagefright/CallbackDataSource.cpp
+++ b/media/libstagefright/CallbackDataSource.cpp
@@ -113,10 +113,6 @@
return mIDataSource->DrmInitialization(mime);
}
-sp<IDataSource> CallbackDataSource::getIDataSource() const {
- return mIDataSource;
-}
-
TinyCacheSource::TinyCacheSource(const sp<DataSource>& source)
: mSource(source), mCachedOffset(0), mCachedSize(0) {
mName = String8::format("TinyCacheSource(%s)", mSource->toString().string());
@@ -194,8 +190,4 @@
return mSource->DrmInitialization(mime);
}
-sp<IDataSource> TinyCacheSource::getIDataSource() const {
- return mSource->getIDataSource();
-}
-
} // namespace android
diff --git a/media/libstagefright/MediaAdapter.cpp b/media/libstagefright/MediaAdapter.cpp
index d680e0c..74eb1ff 100644
--- a/media/libstagefright/MediaAdapter.cpp
+++ b/media/libstagefright/MediaAdapter.cpp
@@ -45,17 +45,24 @@
}
status_t MediaAdapter::stop() {
- Mutex::Autolock autoLock(mAdapterLock);
- if (mStarted) {
- mStarted = false;
- // If stop() happens immediately after a pushBuffer(), we should
- // clean up the mCurrentMediaBuffer
- if (mCurrentMediaBuffer != NULL) {
- mCurrentMediaBuffer->release();
+ MediaBuffer *currentBuffer = NULL;
+ {
+ Mutex::Autolock autoLock(mAdapterLock);
+ if (mStarted) {
+ mStarted = false;
+ // If stop() happens immediately after a pushBuffer(), we should
+ // clean up the mCurrentMediaBuffer. But need to release without
+ // the lock as signalBufferReturned() will acquire the lock.
+ currentBuffer = mCurrentMediaBuffer;
mCurrentMediaBuffer = NULL;
+
+ // While read() is still waiting, we should signal it to finish.
+ mBufferReadCond.signal();
}
- // While read() is still waiting, we should signal it to finish.
- mBufferReadCond.signal();
+ }
+ if (currentBuffer != NULL) {
+ currentBuffer->release();
+ currentBuffer = NULL;
}
return OK;
}
@@ -97,7 +104,6 @@
*buffer = mCurrentMediaBuffer;
mCurrentMediaBuffer = NULL;
- (*buffer)->setObserver(this);
return OK;
}
@@ -114,6 +120,7 @@
return INVALID_OPERATION;
}
mCurrentMediaBuffer = buffer;
+ mCurrentMediaBuffer->setObserver(this);
mBufferReadCond.signal();
ALOGV("wait for the buffer returned @ pushBuffer! %p", buffer);
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 1b12510..e1e04eb 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -23,6 +23,7 @@
#include <media/MediaAnalyticsItem.h>
#include <media/MediaExtractor.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/FileSource.h>
#include <media/stagefright/InterfaceUtils.h>
#include <media/stagefright/MediaExtractorFactory.h>
#include <media/stagefright/MetaData.h>
@@ -44,7 +45,7 @@
// static
sp<IMediaExtractor> MediaExtractorFactory::Create(
const sp<DataSource> &source, const char *mime) {
- ALOGV("MediaExtractorFactory::Create %s", mime);
+ ALOGV("MediaExtractorFactory::%s %s", __func__, mime);
if (!property_get_bool("media.stagefright.extractremote", true)) {
// local extractor
@@ -69,10 +70,48 @@
return NULL;
}
+// static
+sp<IMediaExtractor> MediaExtractorFactory::CreateFromFd(
+ int fd, int64_t offset, int64_t length, const char *mime, sp<DataSource> *out) {
+ ALOGV("MediaExtractorFactory::%s %s", __func__, mime);
+
+ if (property_get_bool("media.stagefright.extractremote", true)) {
+ // remote extractor
+ ALOGV("get service manager");
+ sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor"));
+
+ if (binder != 0) {
+ sp<IMediaExtractorService> mediaExService(
+ interface_cast<IMediaExtractorService>(binder));
+ if (!FileSource::requiresDrm(fd, offset, length, nullptr /* mime */)) {
+ ALOGD("FileSource remote");
+ sp<IDataSource> remoteSource =
+ mediaExService->makeIDataSource(fd, offset, length);
+ ALOGV("IDataSource(FileSource): %p %d %lld %lld",
+ remoteSource.get(), fd, (long long)offset, (long long)length);
+ if (remoteSource.get() != nullptr) {
+ // replace the caller's local source with remote source.
+ *out = CreateDataSourceFromIDataSource(remoteSource);
+ return mediaExService->makeExtractor(remoteSource, mime);
+ } else {
+ ALOGW("extractor service cannot make file source."
+ " falling back to local file source.");
+ }
+ }
+ // Falls back.
+ } else {
+ ALOGE("extractor service not running");
+ return nullptr;
+ }
+ }
+ *out = new FileSource(fd, offset, length);
+ return Create(*out, mime);
+}
+
sp<MediaExtractor> MediaExtractorFactory::CreateFromService(
const sp<DataSource> &source, const char *mime) {
- ALOGV("MediaExtractorFactory::CreateFromService %s", mime);
+ ALOGV("MediaExtractorFactory::%s %s", __func__, mime);
RegisterDefaultSniffers();
// initialize source decryption if needed
diff --git a/media/libstagefright/codecs/avcdec/Android.bp b/media/libstagefright/codecs/avcdec/Android.bp
index 983005f..259fb25 100644
--- a/media/libstagefright/codecs/avcdec/Android.bp
+++ b/media/libstagefright/codecs/avcdec/Android.bp
@@ -11,7 +11,6 @@
cflags: [
"-Wall",
"-Werror",
- "-Wno-unused-variable",
],
include_dirs: [
@@ -51,6 +50,11 @@
],
srcs: ["C2SoftAvcDec.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
include_dirs: [
"external/libavc/decoder",
"external/libavc/common",
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 9d88895..af73c4e 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -20,6 +20,7 @@
#include <cmath>
#include <thread>
+#include <cinttypes>
#include "ih264_typedefs.h"
#include "iv.h"
@@ -1044,7 +1045,8 @@
work->worklets.front()->output.ordinal = work->input.ordinal;
};
if (buffer.capacity() == 0) {
- ALOGV("empty input: %llu", work->input.ordinal.frame_index);
+ ALOGV("empty input: %" PRIu64, work->input.ordinal.frame_index);
+
// TODO: result?
fillEmptyWork(work);
if ((work->input.flags & C2BufferPack::FLAG_END_OF_STREAM)) {
@@ -1052,7 +1054,7 @@
}
done = true;
} else if (work->input.flags & C2BufferPack::FLAG_END_OF_STREAM) {
- ALOGV("input EOS: %llu", work->input.ordinal.frame_index);
+ ALOGV("input EOS: %" PRIu64, work->input.ordinal.frame_index);
eos = true;
}
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index 1622561..3924fc2 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -304,7 +304,6 @@
}
status_t SoftAVC::deInitDecoder() {
- size_t i;
IV_API_CALL_STATUS_T status;
if (mCodecCtx) {
@@ -451,7 +450,6 @@
ivd_video_decode_ip_t s_dec_ip;
ivd_video_decode_op_t s_dec_op;
IV_API_CALL_STATUS_T status;
- size_t sizeY, sizeUV;
setDecodeArgs(&s_dec_ip, &s_dec_op, NULL, NULL, 0);
@@ -563,7 +561,6 @@
ivd_video_decode_ip_t s_dec_ip;
ivd_video_decode_op_t s_dec_op;
nsecs_t timeDelay, timeTaken;
- size_t sizeY, sizeUV;
if (!setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx)) {
ALOGE("Decoder arg setup failed");
diff --git a/media/libstagefright/include/CallbackDataSource.h b/media/libstagefright/include/CallbackDataSource.h
index 9f413cd..32556d6 100644
--- a/media/libstagefright/include/CallbackDataSource.h
+++ b/media/libstagefright/include/CallbackDataSource.h
@@ -42,7 +42,6 @@
return mName;
}
virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
- virtual sp<IDataSource> getIDataSource() const;
private:
sp<IDataSource> mIDataSource;
@@ -71,7 +70,6 @@
return mName;
}
virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
- virtual sp<IDataSource> getIDataSource() const;
private:
// 2kb comes from experimenting with the time-to-first-frame from a MediaPlayer
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 96298f9..f216ff8 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -31,6 +31,12 @@
public:
static sp<IMediaExtractor> Create(
const sp<DataSource> &source, const char *mime = NULL);
+ // Creates media extractor from the given file descriptor. To avoid binder calls for
+ // reading file data, this tries to create remote file source in extractor service.
+ // If that fails, this falls back to local file source. The data source used for extractor
+ // will be alsp returned with |out|.
+ static sp<IMediaExtractor> CreateFromFd(
+ int fd, int64_t offset, int64_t length, const char *mime, sp<DataSource> *out);
static sp<MediaExtractor> CreateFromService(
const sp<DataSource> &source, const char *mime = NULL);
diff --git a/media/libstagefright/include/media/stagefright/RemoteDataSource.h b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
index e191e6a..4ddc5e3 100644
--- a/media/libstagefright/include/media/stagefright/RemoteDataSource.h
+++ b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
@@ -31,9 +31,6 @@
if (source.get() == nullptr) {
return nullptr;
}
- if (source->getIDataSource().get() != nullptr) {
- return source->getIDataSource();
- }
return new RemoteDataSource(source);
}
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index 72917dd..f2bc6d0 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -24,7 +24,6 @@
],
shared_libs: [
"libbinder",
- "libcutils",
"liblog",
"libutils",
"libmemunreachable",
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index bfb0fe2..979908a 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -67,11 +67,15 @@
: mPinned(pinned),
mThread(thread), mChain(chain), mId(id), mSessionId(sessionId),
mDescriptor(*desc),
- // mConfig is set by configure() and not used before then
+ // clear mConfig to ensure consistent initial value of buffer framecount
+ // in case buffers are associated by setInBuffer() or setOutBuffer()
+ // prior to configure().
+ mConfig{{}, {}},
mStatus(NO_INIT), mState(IDLE),
- // mMaxDisableWaitCnt is set by configure() and not used before then
- // mDisableWaitCnt is set by process() and updateState() and not used before then
+ mMaxDisableWaitCnt(1), // set by configure(), should be >= 1
+ mDisableWaitCnt(0), // set by process() and updateState()
mSuspended(false),
+ mOffloaded(false),
mAudioFlinger(thread->mAudioFlinger)
#ifdef FLOAT_EFFECT_CHAIN
, mSupportsFloat(false)
@@ -574,10 +578,14 @@
}
}
- mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
- (1000 * mConfig.outputCfg.buffer.frameCount);
+ // mConfig.outputCfg.buffer.frameCount cannot be zero.
+ mMaxDisableWaitCnt = (uint32_t)std::max(
+ (uint64_t)1, // mMaxDisableWaitCnt must be greater than zero.
+ (uint64_t)MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate
+ / ((uint64_t)1000 * mConfig.outputCfg.buffer.frameCount));
exit:
+ // TODO: consider clearing mConfig on error.
mStatus = status;
ALOGVV("configure ended");
return status;
@@ -892,6 +900,8 @@
void AudioFlinger::EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
ALOGVV("setInBuffer %p",(&buffer));
+
+ // mConfig.inputCfg.buffer.frameCount may be zero if configure() is not called yet.
if (buffer != 0) {
mConfig.inputCfg.buffer.raw = buffer->audioBuffer()->raw;
buffer->setFrameCount(mConfig.inputCfg.buffer.frameCount);
@@ -934,6 +944,8 @@
void AudioFlinger::EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
ALOGVV("setOutBuffer %p",(&buffer));
+
+ // mConfig.outputCfg.buffer.frameCount may be zero if configure() is not called yet.
if (buffer != 0) {
mConfig.outputCfg.buffer.raw = buffer->audioBuffer()->raw;
buffer->setFrameCount(mConfig.outputCfg.buffer.frameCount);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 92d98a8..43f6ed6 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -39,14 +39,13 @@
DeviceVector &availableOutputDevices,
DeviceVector &availableInputDevices,
sp<DeviceDescriptor> &defaultOutputDevices,
- bool &isSpeakerDrcEnabled,
VolumeCurvesCollection *volumes = nullptr)
: mHwModules(hwModules),
mAvailableOutputDevices(availableOutputDevices),
mAvailableInputDevices(availableInputDevices),
mDefaultOutputDevices(defaultOutputDevices),
mVolumeCurves(volumes),
- mIsSpeakerDrcEnabled(isSpeakerDrcEnabled)
+ mIsSpeakerDrcEnabled(false)
{}
void setVolumes(const VolumeCurvesCollection &volumes)
@@ -80,6 +79,8 @@
mAvailableOutputDevices.add(availableOutputDevices);
}
+ bool isSpeakerDrcEnabled() const { return mIsSpeakerDrcEnabled; }
+
void setSpeakerDrcEnabled(bool isSpeakerDrcEnabled)
{
mIsSpeakerDrcEnabled = isSpeakerDrcEnabled;
@@ -140,7 +141,10 @@
DeviceVector &mAvailableInputDevices;
sp<DeviceDescriptor> &mDefaultOutputDevices;
VolumeCurvesCollection *mVolumeCurves;
- bool &mIsSpeakerDrcEnabled;
+ // TODO: remove when legacy conf file is removed. true on devices that use DRC on the
+ // DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.
+ // Note: remove also speaker_drc_enabled from global configuration of XML config file.
+ bool mIsSpeakerDrcEnabled;
};
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurvesCollection.h b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurvesCollection.h
index 7b35f66..e1f6b08 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurvesCollection.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurvesCollection.h
@@ -25,6 +25,8 @@
class IVolumeCurvesCollection
{
public:
+ virtual ~IVolumeCurvesCollection() = default;
+
virtual void clearCurrentVolumeIndex(audio_stream_type_t stream) = 0;
virtual void addCurrentVolumeIndex(audio_stream_type_t stream, audio_devices_t device,
int index) = 0;
@@ -46,9 +48,6 @@
audio_devices_t device) const = 0;
virtual status_t dump(int fd) const = 0;
-
-protected:
- virtual ~IVolumeCurvesCollection() {}
};
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
index db25ed8..3e6b2b4 100644
--- a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
+++ b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
@@ -135,7 +135,13 @@
float volIndexToDb(device_category deviceCat, int indexInUi) const
{
- return getCurvesFor(deviceCat)->volIndexToDb(indexInUi, mIndexMin, mIndexMax);
+ sp<VolumeCurve> vc = getCurvesFor(deviceCat);
+ if (vc != 0) {
+ return vc->volIndexToDb(indexInUi, mIndexMin, mIndexMax);
+ } else {
+ ALOGE("Invalid device category %d for Volume Curve", deviceCat);
+ return 0.0f;
+ }
}
void dump(int fd, int spaces, bool curvePoints = false) const;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index f589743..92332fb 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -223,6 +223,9 @@
__FUNCTION__, mDevice, device);
if (status == NO_ERROR) {
+ LOG_ALWAYS_FATAL_IF(*input == AUDIO_IO_HANDLE_NONE,
+ "%s openInput returned input handle %d for device %08x",
+ __FUNCTION__, *input, device);
mSamplingRate = lConfig.sample_rate;
mChannelMask = lConfig.channel_mask;
mFormat = lConfig.format;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 6e677e4..044d6db 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -431,6 +431,9 @@
__FUNCTION__, mDevice, device);
if (status == NO_ERROR) {
+ LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
+ "%s openOutput returned output handle %d for device %08x",
+ __FUNCTION__, *output, device);
mSamplingRate = lConfig.sample_rate;
mChannelMask = lConfig.channel_mask;
mFormat = lConfig.format;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 0e11c5c..ae3dd08 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -3474,10 +3474,22 @@
}
#endif
-AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
+AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface,
+ bool /*forTesting*/)
:
+ mUidCached(getuid()),
+ mpClientInterface(clientInterface),
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mA2dpSuspended(false),
+#ifdef USE_XML_AUDIO_POLICY_CONF
+ mVolumeCurves(new VolumeCurvesCollection()),
+ mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
+ mDefaultOutputDevice, static_cast<VolumeCurvesCollection*>(mVolumeCurves.get())),
+#else
+ mVolumeCurves(new StreamDescriptorCollection()),
+ mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
+ mDefaultOutputDevice),
+#endif
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
@@ -3487,49 +3499,48 @@
mMusicEffectOutput(AUDIO_IO_HANDLE_NONE),
mHasComputedSoundTriggerSupportsConcurrentCapture(false)
{
- mUidCached = getuid();
- mpClientInterface = clientInterface;
+}
- // TODO: remove when legacy conf file is removed. true on devices that use DRC on the
- // DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.
- // Note: remove also speaker_drc_enabled from global configuration of XML config file.
- bool speakerDrcEnabled = false;
+AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
+ : AudioPolicyManager(clientInterface, false /*forTesting*/)
+{
+ loadConfig();
+ initialize();
+}
+void AudioPolicyManager::loadConfig() {
#ifdef USE_XML_AUDIO_POLICY_CONF
- mVolumeCurves = new VolumeCurvesCollection();
- AudioPolicyConfig config(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
- mDefaultOutputDevice, speakerDrcEnabled,
- static_cast<VolumeCurvesCollection *>(mVolumeCurves));
- if (deserializeAudioPolicyXmlConfig(config) != NO_ERROR) {
+ if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {
#else
- mVolumeCurves = new StreamDescriptorCollection();
- AudioPolicyConfig config(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
- mDefaultOutputDevice, speakerDrcEnabled);
- if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
- (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
+ if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, getConfig()) != NO_ERROR)
+ && (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, getConfig()) != NO_ERROR)) {
#endif
ALOGE("could not load audio policy configuration file, setting defaults");
- config.setDefault();
+ getConfig().setDefault();
}
- // must be done after reading the policy (since conditionned by Speaker Drc Enabling)
- mVolumeCurves->initializeVolumeCurves(speakerDrcEnabled);
+}
+
+status_t AudioPolicyManager::initialize() {
+ mVolumeCurves->initializeVolumeCurves(getConfig().isSpeakerDrcEnabled());
// Once policy config has been parsed, retrieve an instance of the engine and initialize it.
audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
if (!engineInstance) {
ALOGE("%s: Could not get an instance of policy engine", __FUNCTION__);
- return;
+ return NO_INIT;
}
// Retrieve the Policy Manager Interface
mEngine = engineInstance->queryInterface<AudioPolicyManagerInterface>();
if (mEngine == NULL) {
ALOGE("%s: Failed to get Policy Engine Interface", __FUNCTION__);
- return;
+ return NO_INIT;
}
mEngine->setObserver(this);
status_t status = mEngine->initCheck();
- (void) status;
- ALOG_ASSERT(status == NO_ERROR, "Policy engine not initialized(err=%d)", status);
+ if (status != NO_ERROR) {
+ LOG_FATAL("Policy engine not initialized(err=%d)", status);
+ return status;
+ }
// mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
// open all output streams needed to access attached devices
@@ -3692,11 +3703,16 @@
// make sure default device is reachable
if (mDefaultOutputDevice == 0 || mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) {
ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->type());
+ status = NO_INIT;
}
- ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output");
+ if (mPrimaryOutput == 0) {
+ ALOGE("Failed to open primary output");
+ status = NO_INIT;
+ }
updateDevicesAndOutputs();
+ return status;
}
AudioPolicyManager::~AudioPolicyManager()
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 6038e33..611edec 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -17,6 +17,7 @@
#pragma once
#include <atomic>
+#include <memory>
#include <stdint.h>
#include <sys/types.h>
@@ -33,6 +34,7 @@
#include <AudioPolicyManagerInterface.h>
#include <AudioPolicyManagerObserver.h>
#include <AudioGain.h>
+#include <AudioPolicyConfig.h>
#include <AudioPort.h>
#include <AudioPatch.h>
#include <DeviceDescriptor.h>
@@ -234,6 +236,21 @@
routing_strategy getStrategy(audio_stream_type_t stream) const;
protected:
+ // A constructor that allows more fine-grained control over initialization process,
+ // used in automatic tests.
+ AudioPolicyManager(AudioPolicyClientInterface *clientInterface, bool forTesting);
+
+ // These methods should be used when finer control over APM initialization
+ // is needed, e.g. in tests. Must be used in conjunction with the constructor
+ // that only performs fields initialization. The public constructor comprises
+ // these steps in the following sequence:
+ // - field initializing constructor;
+ // - loadConfig;
+ // - initialize.
+ AudioPolicyConfig& getConfig() { return mConfig; }
+ void loadConfig();
+ status_t initialize();
+
// From AudioPolicyManagerObserver
virtual const AudioPatchCollection &getAudioPatches() const
{
@@ -526,18 +543,18 @@
SessionRouteMap mOutputRoutes = SessionRouteMap(SessionRouteMap::MAPTYPE_OUTPUT);
SessionRouteMap mInputRoutes = SessionRouteMap(SessionRouteMap::MAPTYPE_INPUT);
- IVolumeCurvesCollection *mVolumeCurves; // Volume Curves per use case and device category
-
bool mLimitRingtoneVolume; // limit ringtone volume to music volume if headset connected
audio_devices_t mDeviceForStrategy[NUM_STRATEGIES];
float mLastVoiceVolume; // last voice volume value sent to audio HAL
-
- EffectDescriptorCollection mEffects; // list of registered audio effects
bool mA2dpSuspended; // true if A2DP output is suspended
+
+ std::unique_ptr<IVolumeCurvesCollection> mVolumeCurves; // Volume Curves per use case and device category
+ EffectDescriptorCollection mEffects; // list of registered audio effects
sp<DeviceDescriptor> mDefaultOutputDevice; // output device selected by default at boot time
HwModuleCollection mHwModules; // contains only modules that have been loaded successfully
HwModuleCollection mHwModulesAll; // normally not needed, used during construction and for
// dumps
+ AudioPolicyConfig mConfig;
std::atomic<uint32_t> mAudioPortGeneration;
diff --git a/services/audiopolicy/tests/Android.mk b/services/audiopolicy/tests/Android.mk
new file mode 100644
index 0000000..a43daea
--- /dev/null
+++ b/services/audiopolicy/tests/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES := \
+ frameworks/av/services/audiopolicy \
+ frameworks/av/services/audiopolicy/common/include \
+ frameworks/av/services/audiopolicy/engine/interface \
+ frameworks/av/services/audiopolicy/utilities
+
+LOCAL_SHARED_LIBRARIES := \
+ libaudiopolicymanagerdefault \
+ libbase \
+ liblog \
+ libmedia_helper \
+ libutils \
+
+LOCAL_STATIC_LIBRARIES := \
+ libaudiopolicycomponents \
+
+LOCAL_SRC_FILES := \
+ audiopolicymanager_tests.cpp \
+
+LOCAL_MODULE := audiopolicy_tests
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_CFLAGS := -Werror -Wall
+
+LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
+
+include $(BUILD_NATIVE_TEST)
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
new file mode 100644
index 0000000..7e0450d
--- /dev/null
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include "AudioPolicyInterface.h"
+
+namespace android {
+
+class AudioPolicyTestClient : public AudioPolicyClientInterface
+{
+public:
+ virtual ~AudioPolicyTestClient() = default;
+
+ // AudioPolicyClientInterface Implementation
+ audio_module_handle_t loadHwModule(const char* /*name*/) override { return 0; }
+ status_t openOutput(audio_module_handle_t /*module*/,
+ audio_io_handle_t* /*output*/,
+ audio_config_t* /*config*/,
+ audio_devices_t* /*devices*/,
+ const String8& /*address*/,
+ uint32_t* /*latencyMs*/,
+ audio_output_flags_t /*flags*/) override { return 0; }
+ audio_io_handle_t openDuplicateOutput(audio_io_handle_t /*output1*/,
+ audio_io_handle_t /*output2*/) override { return 0; }
+ status_t closeOutput(audio_io_handle_t /*output*/) override { return 0; }
+ status_t suspendOutput(audio_io_handle_t /*output*/) override { return 0; }
+ status_t restoreOutput(audio_io_handle_t /*output*/) override { return 0; }
+ status_t openInput(audio_module_handle_t /*module*/,
+ audio_io_handle_t* /*input*/,
+ audio_config_t* /*config*/,
+ audio_devices_t* /*device*/,
+ const String8& /*address*/,
+ audio_source_t /*source*/,
+ audio_input_flags_t /*flags*/) override { return 0; }
+ status_t closeInput(audio_io_handle_t /*input*/) override { return 0; }
+ status_t setStreamVolume(audio_stream_type_t /*stream*/,
+ float /*volume*/,
+ audio_io_handle_t /*output*/,
+ int /*delayMs*/) override { return 0; }
+ status_t invalidateStream(audio_stream_type_t /*stream*/) override { return 0; }
+ void setParameters(audio_io_handle_t /*ioHandle*/,
+ const String8& /*keyValuePairs*/,
+ int /*delayMs*/) override { }
+ String8 getParameters(audio_io_handle_t /*ioHandle*/,
+ const String8& /*keys*/) override { return String8(); }
+ status_t startTone(audio_policy_tone_t /*tone*/,
+ audio_stream_type_t /*stream*/) override { return 0; }
+ status_t stopTone() override { return 0; }
+ status_t setVoiceVolume(float /*volume*/, int /*delayMs*/) override { return 0; }
+ status_t moveEffects(audio_session_t /*session*/,
+ audio_io_handle_t /*srcOutput*/,
+ audio_io_handle_t /*dstOutput*/) override { return 0; }
+ status_t createAudioPatch(const struct audio_patch* /*patch*/,
+ audio_patch_handle_t* /*handle*/,
+ int /*delayMs*/) override { return 0; }
+ status_t releaseAudioPatch(audio_patch_handle_t /*handle*/,
+ int /*delayMs*/) override { return 0; }
+ status_t setAudioPortConfig(const struct audio_port_config* /*config*/,
+ int /*delayMs*/) override { return 0; }
+ void onAudioPortListUpdate() override { }
+ void onAudioPatchListUpdate() override { }
+ audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t /*use*/) override { return 0; }
+ void onDynamicPolicyMixStateUpdate(String8 /*regId*/, int32_t /*state*/) override { }
+ void onRecordingConfigurationUpdate(int /*event*/,
+ const record_client_info_t* /*clientInfo*/,
+ const struct audio_config_base* /*clientConfig*/,
+ const struct audio_config_base* /*deviceConfig*/,
+ audio_patch_handle_t /*patchHandle*/) override { }
+};
+
+} // namespace android
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
new file mode 100644
index 0000000..fe543a6
--- /dev/null
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include "managerdefault/AudioPolicyManager.h"
+
+namespace android {
+
+class AudioPolicyTestManager : public AudioPolicyManager {
+ public:
+ explicit AudioPolicyTestManager(AudioPolicyClientInterface *clientInterface)
+ : AudioPolicyManager(clientInterface, true /*forTesting*/) { }
+ using AudioPolicyManager::getConfig;
+ using AudioPolicyManager::initialize;
+};
+
+} // namespace android
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
new file mode 100644
index 0000000..de26ab0
--- /dev/null
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include "AudioPolicyTestClient.h"
+#include "AudioPolicyTestManager.h"
+
+using namespace android;
+
+TEST(AudioPolicyManager, InitFailure) {
+ AudioPolicyTestClient client;
+ AudioPolicyTestManager manager(&client);
+ manager.getConfig().setDefault();
+ // Since the default client fails to open anything,
+ // APM should indicate that the initialization didn't succeed.
+ ASSERT_EQ(NO_INIT, manager.initialize());
+ ASSERT_EQ(NO_INIT, manager.initCheck());
+}
+
+
+// A client that provides correct module and IO handles for inputs and outputs.
+class AudioPolicyTestClientWithModulesIoHandles : public AudioPolicyTestClient {
+ public:
+ audio_module_handle_t loadHwModule(const char* /*name*/) override {
+ return mNextModule++;
+ }
+ status_t openOutput(audio_module_handle_t module,
+ audio_io_handle_t* output,
+ audio_config_t* /*config*/,
+ audio_devices_t* /*devices*/,
+ const String8& /*address*/,
+ uint32_t* /*latencyMs*/,
+ audio_output_flags_t /*flags*/) override {
+ if (module >= mNextModule) {
+ ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
+ __func__, module, mNextModule);
+ return BAD_VALUE;
+ }
+ *output = mNextIoHandle++;
+ return NO_ERROR;
+ }
+ status_t openInput(audio_module_handle_t module,
+ audio_io_handle_t* input,
+ audio_config_t* /*config*/,
+ audio_devices_t* /*device*/,
+ const String8& /*address*/,
+ audio_source_t /*source*/,
+ audio_input_flags_t /*flags*/) override {
+ if (module >= mNextModule) {
+ ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
+ __func__, module, mNextModule);
+ return BAD_VALUE;
+ }
+ *input = mNextIoHandle++;
+ return NO_ERROR;
+ }
+ private:
+ audio_module_handle_t mNextModule = AUDIO_MODULE_HANDLE_NONE + 1;
+ audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
+};
+
+TEST(AudioPolicyManager, InitSuccess) {
+ AudioPolicyTestClientWithModulesIoHandles client;
+ AudioPolicyTestManager manager(&client);
+ manager.getConfig().setDefault();
+ ASSERT_EQ(NO_ERROR, manager.initialize());
+ ASSERT_EQ(NO_ERROR, manager.initCheck());
+}
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index a376ab4..24b0816 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -672,7 +672,7 @@
if (mInputStream.configured) {
String8 msg = String8::format("Camera %s: Already has an input stream "
- "configured (ID %zd)", mCameraIdStr.string(), mInputStream.id);
+ "configured (ID %d)", mCameraIdStr.string(), mInputStream.id);
ALOGE("%s: %s", __FUNCTION__, msg.string() );
return STATUS_ERROR(CameraService::ERROR_ALREADY_EXISTS, msg.string());
}
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index 120a717..ca31691 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -25,10 +25,6 @@
LOCAL_32_BIT_ONLY := true
LOCAL_INIT_RC := android.hardware.media.omx@1.0-service.rc
-ifeq ($(PRODUCT_FULL_TREBLE),true)
-LOCAL_CFLAGS += -DUSE_VNDBINDER
-endif
-
include $(BUILD_EXECUTABLE)
# service seccomp policy
diff --git a/services/mediacodec/main_codecservice.cpp b/services/mediacodec/main_codecservice.cpp
index 6f14a42..701ca6e 100644
--- a/services/mediacodec/main_codecservice.cpp
+++ b/services/mediacodec/main_codecservice.cpp
@@ -40,10 +40,8 @@
signal(SIGPIPE, SIG_IGN);
SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
-#ifdef USE_VNDBINDER
android::ProcessState::initWithDriver("/dev/vndbinder");
android::ProcessState::self()->startThreadPool();
-#endif // USE_VNDBINDER
::android::hardware::configureRpcThreadpool(64, false);