Merge "Handle nullptr if memory allocation fails" into sc-dev
diff --git a/media/libeffects/preprocessing/Android.bp b/media/libeffects/preprocessing/Android.bp
index eb3ce34..87ed8b6 100644
--- a/media/libeffects/preprocessing/Android.bp
+++ b/media/libeffects/preprocessing/Android.bp
@@ -22,6 +22,7 @@
name: "libaudiopreprocessing",
vendor: true,
relative_install_path: "soundfx",
+ host_supported: true,
srcs: ["PreProcessing.cpp"],
local_include_dirs: [
".",
@@ -47,4 +48,9 @@
"libhardware_headers",
"libwebrtc_absl_headers",
],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
}
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index e8ae58e..3b0b6d6 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -670,8 +670,8 @@
return 0;
}
-int NsGetParameter(preproc_effect_t* effect __unused, void* pParam __unused,
- uint32_t* pValueSize __unused, void* pValue __unused) {
+int NsGetParameter(preproc_effect_t* /*effect __unused*/, void* /*pParam __unused*/,
+ uint32_t* /*pValueSize __unused*/, void* /*pValue __unused*/) {
int status = 0;
return status;
}
@@ -1551,7 +1551,7 @@
}
int PreProcessingFx_ProcessReverse(effect_handle_t self, audio_buffer_t* inBuffer,
- audio_buffer_t* outBuffer __unused) {
+ audio_buffer_t* outBuffer) {
preproc_effect_t* effect = (preproc_effect_t*)self;
if (effect == NULL) {
diff --git a/media/libeffects/preprocessing/tests/Android.bp b/media/libeffects/preprocessing/tests/Android.bp
index 8848e79..6413945 100644
--- a/media/libeffects/preprocessing/tests/Android.bp
+++ b/media/libeffects/preprocessing/tests/Android.bp
@@ -13,6 +13,8 @@
cc_test {
name: "AudioPreProcessingTest",
vendor: true,
+ host_supported: true,
+ gtest: false,
srcs: ["PreProcessingTest.cpp"],
shared_libs: [
"libaudioutils",
@@ -27,7 +29,11 @@
"libaudioeffects",
"libhardware_headers",
],
- gtest: false,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
}
cc_test {
diff --git a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
index 5f223c9..e0025fe 100644
--- a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
+++ b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
@@ -24,6 +24,7 @@
#include <audio_effects/effect_agc.h>
#include <audio_effects/effect_agc2.h>
#include <audio_effects/effect_ns.h>
+#include <audio_utils/channels.h>
#include <log/log.h>
// This is the only symbol that needs to be imported
@@ -55,7 +56,9 @@
ARG_NS_LVL,
ARG_AGC2_GAIN,
ARG_AGC2_LVL,
- ARG_AGC2_SAT_MGN
+ ARG_AGC2_SAT_MGN,
+ ARG_FILE_CHANNELS,
+ ARG_MONO_MODE
};
struct preProcConfigParams_t {
@@ -68,6 +71,8 @@
float agc2SaturationMargin = 2.f; // in dB
int agc2Level = 0; // either kRms(0) or kPeak(1)
int aecDelay = 0; // in ms
+ int fileChannels = 1;
+ int monoMode = 0;
};
const effect_uuid_t kPreProcUuids[PREPROC_NUM_EFFECTS] = {
@@ -106,7 +111,7 @@
printf("\n Prints this usage information");
printf("\n --fs <sampling_freq>");
printf("\n Sampling frequency in Hz, default 16000.");
- printf("\n -ch_mask <channel_mask>\n");
+ printf("\n --ch_mask <channel_mask>\n");
printf("\n 0 - AUDIO_CHANNEL_IN_MONO");
printf("\n 1 - AUDIO_CHANNEL_IN_STEREO");
printf("\n 2 - AUDIO_CHANNEL_IN_FRONT_BACK");
@@ -144,6 +149,10 @@
printf("\n AGC Adaptive Digital Saturation Margin in dB, default value 2dB");
printf("\n --aec_delay <delay>");
printf("\n AEC delay value in ms, default value 0ms");
+ printf("\n --fch <fileChannels>");
+ printf("\n number of channels in the input file");
+ printf("\n --mono <Mono Mode>");
+ printf("\n Mode to make data of all channels the same as first channel");
printf("\n");
}
@@ -189,10 +198,17 @@
printUsage();
return EXIT_FAILURE;
}
+
+ // Print the arguments passed
+ for (int i = 1; i < argc; i++) {
+ printf("%s ", argv[i]);
+ }
+
const char* inputFile = nullptr;
const char* outputFile = nullptr;
const char* farFile = nullptr;
int effectEn[PREPROC_NUM_EFFECTS] = {0};
+ struct preProcConfigParams_t preProcCfgParams {};
const option long_opts[] = {
{"help", no_argument, nullptr, ARG_HELP},
@@ -212,9 +228,10 @@
{"agc", no_argument, &effectEn[PREPROC_AGC], 1},
{"agc2", no_argument, &effectEn[PREPROC_AGC2], 1},
{"ns", no_argument, &effectEn[PREPROC_NS], 1},
+ {"fch", required_argument, nullptr, ARG_FILE_CHANNELS},
+ {"mono", no_argument, &preProcCfgParams.monoMode, 1},
{nullptr, 0, nullptr, 0},
};
- struct preProcConfigParams_t preProcCfgParams {};
while (true) {
const int opt = getopt_long(argc, (char* const*)argv, "i:o:", long_opts, nullptr);
@@ -279,6 +296,14 @@
preProcCfgParams.nsLevel = atoi(optarg);
break;
}
+ case ARG_FILE_CHANNELS: {
+ preProcCfgParams.fileChannels = atoi(optarg);
+ break;
+ }
+ case ARG_MONO_MODE: {
+ preProcCfgParams.monoMode = 1;
+ break;
+ }
default:
break;
}
@@ -402,16 +427,28 @@
// Process Call
const int frameLength = (int)(preProcCfgParams.samplingFreq * kTenMilliSecVal);
const int ioChannelCount = audio_channel_count_from_in_mask(preProcCfgParams.chMask);
+ const int fileChannelCount = preProcCfgParams.fileChannels;
const int ioFrameSize = ioChannelCount * sizeof(short);
+ const int inFrameSize = fileChannelCount * sizeof(short);
int frameCounter = 0;
while (true) {
std::vector<short> in(frameLength * ioChannelCount);
std::vector<short> out(frameLength * ioChannelCount);
std::vector<short> farIn(frameLength * ioChannelCount);
- size_t samplesRead = fread(in.data(), ioFrameSize, frameLength, inputFp.get());
+ size_t samplesRead = fread(in.data(), inFrameSize, frameLength, inputFp.get());
if (samplesRead == 0) {
break;
}
+ if (fileChannelCount != ioChannelCount) {
+ adjust_channels(in.data(), fileChannelCount, in.data(), ioChannelCount, sizeof(short),
+ frameLength * inFrameSize);
+ if (preProcCfgParams.monoMode == 1) {
+ for (int i = 0; i < frameLength; ++i) {
+ auto* fp = &in[i * ioChannelCount];
+ std::fill(fp + 1, fp + ioChannelCount, *fp); // replicate ch 0
+ }
+ }
+ }
audio_buffer_t inputBuffer, outputBuffer;
audio_buffer_t farInBuffer{};
inputBuffer.frameCount = samplesRead;
@@ -420,10 +457,21 @@
outputBuffer.s16 = out.data();
if (farFp != nullptr) {
- samplesRead = fread(farIn.data(), ioFrameSize, frameLength, farFp.get());
+ samplesRead = fread(farIn.data(), inFrameSize, frameLength, farFp.get());
if (samplesRead == 0) {
break;
}
+ if (fileChannelCount != ioChannelCount) {
+ adjust_channels(farIn.data(), fileChannelCount, farIn.data(), ioChannelCount,
+ sizeof(short), frameLength * inFrameSize);
+ if (preProcCfgParams.monoMode == 1) {
+ for (int i = 0; i < frameLength; ++i) {
+ auto* fp = &farIn[i * ioChannelCount];
+ std::fill(fp + 1, fp + ioChannelCount, *fp); // replicate ch 0
+ }
+ }
+ }
+
farInBuffer.frameCount = samplesRead;
farInBuffer.s16 = farIn.data();
}
@@ -458,8 +506,12 @@
}
}
if (outputFp != nullptr) {
+ if (fileChannelCount != ioChannelCount) {
+ adjust_channels(out.data(), ioChannelCount, out.data(), fileChannelCount,
+ sizeof(short), frameLength * ioFrameSize);
+ }
size_t samplesWritten =
- fwrite(out.data(), ioFrameSize, outputBuffer.frameCount, outputFp.get());
+ fwrite(out.data(), inFrameSize, outputBuffer.frameCount, outputFp.get());
if (samplesWritten != outputBuffer.frameCount) {
ALOGE("\nError: Output file writing failed");
break;
diff --git a/media/libeffects/preprocessing/tests/build_and_run_all_unit_tests.sh b/media/libeffects/preprocessing/tests/build_and_run_all_unit_tests.sh
new file mode 100755
index 0000000..942f2ec
--- /dev/null
+++ b/media/libeffects/preprocessing/tests/build_and_run_all_unit_tests.sh
@@ -0,0 +1,115 @@
+#!/bin/bash
+#
+# Run tests in this directory.
+#
+
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+ echo "Android build environment not set"
+ exit -1
+fi
+
+# ensure we have mm
+. $ANDROID_BUILD_TOP/build/envsetup.sh
+
+mm -j
+
+echo "waiting for device"
+
+adb root && adb wait-for-device remount
+
+# location of test files
+testdir="/data/local/tmp/AudioPreProcessingTest"
+
+echo "========================================"
+echo "testing PreProcessing modules"
+adb shell mkdir -p $testdir
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/libeffects/res/raw/sinesweepraw.raw $testdir
+adb push $OUT/testcases/snr/arm64/snr $testdir
+
+E_VAL=1
+if [ -z "$1" ]
+then
+ cmds=("adb push $OUT/testcases/AudioPreProcessingTest/arm64/AudioPreProcessingTest $testdir"
+ "adb push $OUT/testcases/AudioPreProcessingTest/arm/AudioPreProcessingTest $testdir"
+)
+elif [ "$1" == "32" ]
+then
+ cmds="adb push $OUT/testcases/AudioPreProcessingTest/arm/AudioPreProcessingTest $testdir"
+elif [ "$1" == "64" ]
+then
+ cmds="adb push $OUT/testcases/AudioPreProcessingTest/arm64/AudioPreProcessingTest $testdir"
+else
+ echo ""
+ echo "Invalid \"val\""
+ echo "Usage:"
+ echo " "$0" [val]"
+ echo " where, val can be either 32 or 64."
+ echo ""
+ echo " If val is not specified then both 32 bit and 64 bit binaries"
+ echo " are tested."
+ exit $E_VAL
+fi
+
+flags_arr=(
+ "--agc --mono"
+ "--ns --mono"
+ "--agc2 --mono"
+ "--aec --mono"
+)
+
+fs_arr=(
+ 8000
+ 16000
+ 24000
+ 32000
+ 48000
+)
+
+# run multichannel effects at different configs, saving only the mono channel
+error_count=0
+test_count=0
+for cmd in "${cmds[@]}"
+do
+ $cmd
+ for flags in "${flags_arr[@]}"
+ do
+ for fs in ${fs_arr[*]}
+ do
+ for chMask in {0..7}
+ do
+ adb shell $testdir/AudioPreProcessingTest $flags \
+ --i $testdir/sinesweepraw.raw --far $testdir/sinesweepraw.raw \
+ --output $testdir/sinesweep_$((chMask))_$((fs)).raw --ch_mask $chMask \
+ --fs $fs --fch 1
+
+ shell_ret=$?
+ if [ $shell_ret -ne 0 ]; then
+ echo "error shell_ret here is zero: $shell_ret"
+ ((++error_count))
+ fi
+
+
+ # single channel files should be identical to higher channel
+ # computation (first channel).
+ if [[ "$chMask" -gt 1 ]]
+ then
+ adb shell cmp $testdir/sinesweep_1_$((fs)).raw \
+ $testdir/sinesweep_$((chMask))_$((fs)).raw
+ fi
+
+ # cmp return EXIT_FAILURE on mismatch.
+ shell_ret=$?
+ if [ $shell_ret -ne 0 ]; then
+ echo "error: $shell_ret"
+ ((++error_count))
+ fi
+ ((++test_count))
+ done
+ done
+ done
+done
+
+adb shell rm -r $testdir
+echo "$test_count tests performed"
+echo "$error_count errors"
+exit $error_count
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 7c981b3..d77845f 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -188,11 +188,11 @@
// sanity check check struct version, uuid, name
if (plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V1 &&
plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V2) {
- ALOGE("don't understand extractor format %u, ignoring.", plugin->def.def_version);
+ ALOGW("don't understand extractor format %u, ignoring.", plugin->def.def_version);
return;
}
if (memcmp(&plugin->def.extractor_uuid, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0) {
- ALOGE("invalid UUID, ignoring");
+ ALOGW("invalid UUID, ignoring");
return;
}
if (plugin->def.extractor_name == NULL || strlen(plugin->def.extractor_name) == 0) {
@@ -244,13 +244,17 @@
void *libHandle = android_dlopen_ext(
libPath.string(),
RTLD_NOW | RTLD_LOCAL, dlextinfo);
- CHECK(libHandle != nullptr)
- << "couldn't dlopen(" << libPath.string() << ") " << strerror(errno);
+ if (libHandle == nullptr) {
+ ALOGI("dlopen(%s) reported error %s", libPath.string(), strerror(errno));
+ continue;
+ }
GetExtractorDef getDef =
(GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
- CHECK(getDef != nullptr)
- << libPath.string() << " does not contain sniffer";
+ if (getDef == nullptr) {
+ ALOGI("no sniffer found in %s", libPath.string());
+ continue;
+ }
ALOGV("registering sniffer for %s", libPath.string());
RegisterExtractor(
@@ -258,7 +262,7 @@
}
closedir(libDir);
} else {
- ALOGE("couldn't opendir(%s)", libDirPath);
+ ALOGI("plugin directory not present (%s)", libDirPath);
}
}
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index f63740e..51d9730 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -1675,7 +1675,7 @@
if (msg->findString("mime", &mime)) {
meta->setCString(kKeyMIMEType, mime.c_str());
} else {
- ALOGE("did not find mime type");
+ ALOGI("did not find mime type");
return BAD_VALUE;
}
@@ -1725,7 +1725,7 @@
meta->setInt32(kKeyWidth, width);
meta->setInt32(kKeyHeight, height);
} else {
- ALOGE("did not find width and/or height");
+ ALOGI("did not find width and/or height");
return BAD_VALUE;
}
@@ -1814,7 +1814,7 @@
int32_t numChannels, sampleRate;
if (!msg->findInt32("channel-count", &numChannels) ||
!msg->findInt32("sample-rate", &sampleRate)) {
- ALOGE("did not find channel-count and/or sample-rate");
+ ALOGI("did not find channel-count and/or sample-rate");
return BAD_VALUE;
}
meta->setInt32(kKeyChannelCount, numChannels);
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index f242b19..6bb7b37 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -1078,6 +1078,17 @@
return OK;
}
+status_t AMessage::removeEntryByName(const char *name) {
+ if (name == nullptr) {
+ return BAD_VALUE;
+ }
+ size_t index = findEntryByName(name);
+ if (index >= mNumItems) {
+ return BAD_INDEX;
+ }
+ return removeEntryAt(index);
+}
+
void AMessage::setItem(const char *name, const ItemData &item) {
if (item.used()) {
Item *it = allocateItem(name);
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
index 31e58ba..98d6147 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
@@ -261,6 +261,17 @@
*/
status_t removeEntryAt(size_t index);
+ /**
+ * Removes an entry based on name.
+ *
+ * \param name name of the entry
+ *
+ * \retval OK the entry was removed successfully
+ * \retval BAD_VALUE name is invalid (null)
+ * \retval BAD_INDEX name not found
+ */
+ status_t removeEntryByName(const char *name);
+
protected:
virtual ~AMessage();
diff --git a/media/libstagefright/foundation/tests/AMessage_test.cpp b/media/libstagefright/foundation/tests/AMessage_test.cpp
new file mode 100644
index 0000000..2b11326
--- /dev/null
+++ b/media/libstagefright/foundation/tests/AMessage_test.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2021 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 "AData_test"
+
+#include <gtest/gtest.h>
+#include <utils/RefBase.h>
+
+#include <media/stagefright/foundation/AMessage.h>
+
+using namespace android;
+
+class AMessageTest : public ::testing::Test {
+};
+
+
+TEST(AMessage_tests, item_manipulation) {
+ sp<AMessage> m1 = new AMessage();
+
+ m1->setInt32("value", 2);
+ m1->setInt32("bar", 3);
+
+ int32_t i32;
+ EXPECT_TRUE(m1->findInt32("value", &i32));
+ EXPECT_EQ(2, i32);
+
+ EXPECT_TRUE(m1->findInt32("bar", &i32));
+ EXPECT_EQ(3, i32);
+
+
+ m1->setInt64("big", INT64_MAX);
+ m1->setInt64("smaller", INT64_MAX - 2);
+ m1->setInt64("smallest", 257);
+
+ int64_t i64;
+ EXPECT_TRUE(m1->findInt64("big", &i64));
+ EXPECT_EQ(INT64_MAX, i64);
+
+ EXPECT_TRUE(m1->findInt64("smaller", &i64));
+ EXPECT_EQ(INT64_MAX - 2, i64);
+
+ m1->setSize("size1", 257);
+ m1->setSize("size2", 1023);
+
+ size_t sizing;
+ EXPECT_TRUE(m1->findSize("size2", &sizing));
+ EXPECT_EQ(1023, sizing);
+ EXPECT_TRUE(m1->findSize("size1", &sizing));
+ EXPECT_EQ(257, sizing);
+
+ m1->setDouble("precise", 10.5);
+ m1->setDouble("small", 0.125);
+
+ double d;
+ EXPECT_TRUE(m1->findDouble("precise", &d));
+ EXPECT_EQ(10.5, d);
+
+ EXPECT_TRUE(m1->findDouble("small", &d));
+ EXPECT_EQ(0.125, d);
+
+ // should be unchanged from the top of the test
+ EXPECT_TRUE(m1->findInt32("bar", &i32));
+ EXPECT_EQ(3, i32);
+
+ EXPECT_FALSE(m1->findInt32("nonesuch", &i32));
+ EXPECT_FALSE(m1->findInt64("nonesuch2", &i64));
+ // types disagree, not found
+ EXPECT_FALSE(m1->findInt32("big", &i32));
+ EXPECT_FALSE(m1->findInt32("precise", &i32));
+
+ // integral types should come back true
+ EXPECT_TRUE(m1->findAsInt64("big", &i64));
+ EXPECT_EQ(INT64_MAX, i64);
+ EXPECT_TRUE(m1->findAsInt64("bar", &i64));
+ EXPECT_EQ(3, i64);
+ EXPECT_FALSE(m1->findAsInt64("precise", &i64));
+
+ // recovers ints, size, and floating point values
+ float value;
+ EXPECT_TRUE(m1->findAsFloat("value", &value));
+ EXPECT_EQ(2, value);
+ EXPECT_TRUE(m1->findAsFloat("smallest", &value));
+ EXPECT_EQ(257, value);
+ EXPECT_TRUE(m1->findAsFloat("size2", &value));
+ EXPECT_EQ(1023, value);
+ EXPECT_TRUE(m1->findAsFloat("precise", &value));
+ EXPECT_EQ(10.5, value);
+ EXPECT_TRUE(m1->findAsFloat("small", &value));
+ EXPECT_EQ(0.125, value);
+
+
+ // need to handle still:
+ // strings
+ // Object
+ // Buffer
+ // Message (nested)
+ //
+
+ // removal
+ m1->setInt32("shortlived", 2);
+ m1->setInt32("alittlelonger", 2);
+ EXPECT_EQ(OK, m1->removeEntryByName("shortlived"));
+ EXPECT_EQ(BAD_VALUE, m1->removeEntryByName(nullptr));
+ EXPECT_EQ(BAD_INDEX, m1->removeEntryByName("themythicalnonesuch"));
+ EXPECT_FALSE(m1->findInt32("shortlived", &i32));
+ EXPECT_TRUE(m1->findInt32("alittlelonger", &i32));
+
+ EXPECT_NE(OK, m1->removeEntryByName("notpresent"));
+
+}
+
diff --git a/media/libstagefright/foundation/tests/Android.bp b/media/libstagefright/foundation/tests/Android.bp
index 715b57a..e50742e 100644
--- a/media/libstagefright/foundation/tests/Android.bp
+++ b/media/libstagefright/foundation/tests/Android.bp
@@ -30,6 +30,7 @@
srcs: [
"AData_test.cpp",
+ "AMessage_test.cpp",
"Base64_test.cpp",
"Flagged_test.cpp",
"TypeTraits_test.cpp",
diff --git a/media/ndk/TEST_MAPPING b/media/ndk/TEST_MAPPING
index 1a81538..e420812 100644
--- a/media/ndk/TEST_MAPPING
+++ b/media/ndk/TEST_MAPPING
@@ -1,6 +1,7 @@
// mappings for frameworks/av/media/ndk
{
"presubmit": [
- { "name": "AImageReaderWindowHandleTest" }
+ { "name": "AImageReaderWindowHandleTest" },
+ { "name": "libmediandk_test" }
]
}
diff --git a/media/ndk/tests/Android.bp b/media/ndk/tests/Android.bp
new file mode 100644
index 0000000..984b3ee
--- /dev/null
+++ b/media/ndk/tests/Android.bp
@@ -0,0 +1,41 @@
+// Copyright (C) 2016 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.
+
+// Headers module is in frameworks/av/Android.bp because modules are not allowed
+// to refer to headers in parent directories and the headers live in
+// frameworks/av/include.
+
+package {
+ default_applicable_licenses: ["frameworks_av_media_ndk_license"],
+}
+
+cc_test {
+ name: "libmediandk_test",
+ test_suites: ["device-tests"],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ shared_libs: [
+ "liblog",
+ "libmediandk",
+ "libutils",
+ ],
+
+ srcs: [
+ "NdkMediaFormat_test.cpp",
+ ],
+}
diff --git a/media/ndk/tests/NdkMediaFormat_test.cpp b/media/ndk/tests/NdkMediaFormat_test.cpp
new file mode 100644
index 0000000..668d0a4
--- /dev/null
+++ b/media/ndk/tests/NdkMediaFormat_test.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2021 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 "NdkMediaFormat_test"
+
+#include <gtest/gtest.h>
+#include <utils/RefBase.h>
+
+#include <media/NdkMediaFormat.h>
+
+namespace android {
+
+class NdkMediaFormatTest : public ::testing::Test {
+};
+
+
+TEST(NdkMediaFormat_tests, test_create) {
+
+ AMediaFormat *fmt1 = AMediaFormat_new();
+ AMediaFormat *fmt2 = AMediaFormat_new();
+
+ EXPECT_NE(fmt1, fmt2);
+ EXPECT_NE(fmt1, nullptr);
+ EXPECT_NE(fmt2, nullptr);
+
+ AMediaFormat_delete(fmt1);
+ AMediaFormat_delete(fmt2);
+}
+
+TEST(NdkMediaFormat_tests, test_int32) {
+ AMediaFormat *fmt1 = AMediaFormat_new();
+ int32_t i32;
+ int64_t i64;
+ AMediaFormat_setInt32(fmt1, "five", 5);
+
+ EXPECT_TRUE(AMediaFormat_getInt32(fmt1, "five", &i32));
+ EXPECT_FALSE(AMediaFormat_getInt64(fmt1, "five", &i64));
+ EXPECT_EQ(i32, 5);
+
+ AMediaFormat_delete(fmt1);
+}
+
+TEST(NdkMediaFormat_tests, test_int64) {
+ AMediaFormat *fmt1 = AMediaFormat_new();
+ int64_t i64;
+ AMediaFormat_setInt64(fmt1, "verylarge", INT64_MAX);
+
+ EXPECT_TRUE(AMediaFormat_getInt64(fmt1, "verylarge", &i64));
+ EXPECT_EQ(i64, INT64_MAX);
+
+ // return unchanged if not found
+ i64 = -1;
+ EXPECT_FALSE(AMediaFormat_getInt64(fmt1, "five", &i64));
+ EXPECT_EQ(i64, -1);
+
+ AMediaFormat_delete(fmt1);
+}
+
+TEST(NdkMediaFormat_tests, test_size) {
+ AMediaFormat *fmt1 = AMediaFormat_new();
+
+ size_t size = -15;
+ AMediaFormat_setSize(fmt1, "small", 1);
+ AMediaFormat_setSize(fmt1, "medium", 10);
+ AMediaFormat_setSize(fmt1, "large", 100);
+ EXPECT_TRUE(AMediaFormat_getSize(fmt1, "medium", &size));
+ EXPECT_EQ(size, 10);
+
+ AMediaFormat_delete(fmt1);
+}
+
+TEST(NdkMediaFormat_tests, test_float) {
+ AMediaFormat *fmt1 = AMediaFormat_new();
+ float f;
+ AMediaFormat_setFloat(fmt1, "boat", 1.5);
+ AMediaFormat_setFloat(fmt1, "ship", 0.5);
+ EXPECT_TRUE(AMediaFormat_getFloat(fmt1, "boat", &f));
+ EXPECT_EQ(f, 1.5);
+ AMediaFormat_delete(fmt1);
+}
+
+TEST(NdkMediaFormat_tests, test_double) {
+ AMediaFormat *fmt1 = AMediaFormat_new();
+ double d;
+ AMediaFormat_setDouble(fmt1, "trouble", 100.5);
+ AMediaFormat_setDouble(fmt1, "dip", 0.5);
+ EXPECT_TRUE(AMediaFormat_getDouble(fmt1, "trouble", &d));
+ EXPECT_EQ(d, 100.5);
+ AMediaFormat_delete(fmt1);
+}
+
+TEST(NdkMediaFormat_tests, test_string) {
+ AMediaFormat *fmt1 = AMediaFormat_new();
+
+ const char *content = "This is my test string";
+ const char *out = nullptr;
+ AMediaFormat_setString(fmt1, "stringtheory", content);
+ EXPECT_TRUE(AMediaFormat_getString(fmt1, "stringtheory", &out));
+ EXPECT_NE(out, nullptr);
+ EXPECT_EQ(strcmp(out,content), 0);
+
+ AMediaFormat_delete(fmt1);
+}
+
+
+TEST(NdkMediaFormat_tests, test_clear) {
+ AMediaFormat *fmt1 = AMediaFormat_new();
+
+ int32_t i32;
+ AMediaFormat_setInt32(fmt1, "five", 5);
+ size_t size = -15;
+ AMediaFormat_setSize(fmt1, "medium", 10);
+ float f;
+ AMediaFormat_setFloat(fmt1, "boat", 1.5);
+
+ AMediaFormat_clear(fmt1);
+ EXPECT_FALSE(AMediaFormat_getInt32(fmt1, "five", &i32));
+ EXPECT_FALSE(AMediaFormat_getSize(fmt1, "medium", &size));
+ EXPECT_FALSE(AMediaFormat_getFloat(fmt1, "boat", &f));
+
+ AMediaFormat_delete(fmt1);
+}
+
+TEST(NdkMediaFormat_tests, test_copy) {
+ AMediaFormat *fmt1 = AMediaFormat_new();
+ AMediaFormat *fmt2 = AMediaFormat_new();
+
+ double d;
+ int32_t i32;
+
+ // test copy functionality (NB: we cleared everything just above here)
+ AMediaFormat_setDouble(fmt1, "trouble", 100.5);
+ EXPECT_TRUE(AMediaFormat_getDouble(fmt1, "trouble", &d));
+ EXPECT_FALSE(AMediaFormat_getDouble(fmt2, "trouble", &d));
+
+ EXPECT_EQ(AMEDIA_OK, AMediaFormat_copy(fmt2, fmt1));
+
+ EXPECT_TRUE(AMediaFormat_getDouble(fmt2, "trouble", &d));
+ EXPECT_EQ(d, 100.5);
+
+ AMediaFormat *fmt3 = nullptr;
+ EXPECT_NE(AMEDIA_OK, AMediaFormat_copy(fmt3, fmt1));
+ EXPECT_NE(AMEDIA_OK, AMediaFormat_copy(fmt1, fmt3));
+
+ // we should lose an entry when we copy over it
+ AMediaFormat_setInt32(fmt2, "vanishing", 50);
+ EXPECT_FALSE(AMediaFormat_getInt32(fmt1, "vanishing", &i32));
+ EXPECT_TRUE(AMediaFormat_getInt32(fmt2, "vanishing", &i32));
+ EXPECT_EQ(AMEDIA_OK, AMediaFormat_copy(fmt2, fmt1));
+ EXPECT_FALSE(AMediaFormat_getInt32(fmt2, "vanishing", &i32));
+
+ AMediaFormat_delete(fmt1);
+ AMediaFormat_delete(fmt2);
+}
+
+TEST(NdkMediaFormat_tests, test_buffer) {
+ AMediaFormat *fmt1 = AMediaFormat_new();
+
+ typedef struct blockomem {
+ int leading;
+ int filled[100];
+ int trailing;
+ } block_t;
+ block_t buf = {};
+ buf.leading = 1;
+ buf.trailing = 2;
+ void *data;
+ size_t bsize;
+
+ AMediaFormat_setBuffer(fmt1, "mybuffer", &buf, sizeof(buf));
+ EXPECT_TRUE(AMediaFormat_getBuffer(fmt1, "mybuffer", &data, &bsize));
+ EXPECT_NE(&buf, data);
+ EXPECT_EQ(sizeof(buf), bsize);
+ block_t *bufp = (block_t*) data;
+ EXPECT_EQ(bufp->leading, buf.leading);
+ EXPECT_EQ(bufp->trailing, buf.trailing);
+ EXPECT_EQ(0, memcmp(&buf, data, bsize));
+
+ AMediaFormat_delete(fmt1);
+}
+
+} // namespace android
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index 8baf8dc..0b69bf6 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -39,7 +39,7 @@
using namespace aaudio;
#define MAX_STREAMS_PER_PROCESS 8
-#define AIDL_RETURN(x) *_aidl_return = (x); return Status::ok();
+#define AIDL_RETURN(x) { *_aidl_return = (x); return Status::ok(); }
#define VALUE_OR_RETURN_ILLEGAL_ARG_STATUS(x) \
({ auto _tmp = (x); \
@@ -116,12 +116,11 @@
// Enforce limit on client processes.
Identity callingIdentity = request.getIdentity();
+ pid_t pid = IPCThreadState::self()->getCallingPid();
callingIdentity.pid = VALUE_OR_RETURN_ILLEGAL_ARG_STATUS(
- legacy2aidl_pid_t_int32_t(IPCThreadState::self()->getCallingPid()));
+ legacy2aidl_pid_t_int32_t(pid));
callingIdentity.uid = VALUE_OR_RETURN_ILLEGAL_ARG_STATUS(
legacy2aidl_uid_t_int32_t(IPCThreadState::self()->getCallingUid()));
- pid_t pid = VALUE_OR_RETURN_ILLEGAL_ARG_STATUS(
- aidl2legacy_int32_t_pid_t(callingIdentity.pid));
if (callingIdentity.pid != mAudioClient.identity.pid) {
int32_t count = AAudioClientTracker::getInstance().getStreamCount(pid);
if (count >= MAX_STREAMS_PER_PROCESS) {