Turn off overrideToPortrait where not needed. am: 7b14d5e6c4
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/22118549
Change-Id: Ib180c20f7abe08e708fe8f8743a125b4c5675f69
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index ee609e1..37f6457 100644
--- a/Android.bp
+++ b/Android.bp
@@ -44,7 +44,7 @@
srcs: [
"aidl/android/media/InterpolatorConfig.aidl",
"aidl/android/media/InterpolatorType.aidl",
- "aidl/android/media/MicrophoneInfoData.aidl",
+ "aidl/android/media/MicrophoneInfoFw.aidl",
"aidl/android/media/VolumeShaperConfiguration.aidl",
"aidl/android/media/VolumeShaperConfigurationOptionFlag.aidl",
"aidl/android/media/VolumeShaperConfigurationType.aidl",
@@ -52,16 +52,22 @@
"aidl/android/media/VolumeShaperOperationFlag.aidl",
"aidl/android/media/VolumeShaperState.aidl",
],
+ imports: [
+ "android.media.audio.common.types-V2",
+ ],
backend: {
cpp: {
min_sdk_version: "29",
apex_available: [
"//apex_available:platform",
- "com.android.bluetooth",
+ "com.android.btservices",
"com.android.media",
"com.android.media.swcodec",
],
},
+ java: {
+ sdk_version: "module_current",
+ },
},
}
@@ -75,10 +81,10 @@
"av-types-aidl-cpp",
],
header_libs: [
- "libaudioclient_aidl_conversion_util",
+ "libaudio_aidl_conversion_common_util_cpp",
],
export_header_lib_headers: [
- "libaudioclient_aidl_conversion_util",
+ "libaudio_aidl_conversion_common_util_cpp",
],
host_supported: true,
vendor_available: true,
@@ -86,7 +92,7 @@
min_sdk_version: "29",
apex_available: [
"//apex_available:platform",
- "com.android.bluetooth",
+ "com.android.btservices",
"com.android.media",
"com.android.media.swcodec",
],
diff --git a/MainlineFiles.cfg b/MainlineFiles.cfg
index 490bbbf..bf39c1a 100644
--- a/MainlineFiles.cfg
+++ b/MainlineFiles.cfg
@@ -21,11 +21,20 @@
#
# matching is purely prefix
# so 'foo' will match 'foo', 'foo.c', 'foo/bar/baz'
-# if you want to exclude a directory, best to use a pattern like "foo/"
+# if you want to specify a directory, best to use a pattern like "foo/"
#
+apex/
media/codec2/components/
-media/codecs/
-media/extractors/
-media/libstagefright/mpeg2ts/
-media/libstagefright/flac/
+media/codec2/core/
+media/codec2/hidl/
+media/codec2/sfplugin/utils/
+media/codec2/vndk/
+media/libstagefright/data/media_codecs_sw.xml
+media/module/
+services/mediacodec/
+
+# source code used in both framework and mainline libraries
+media/libstagefright/HevcUtils.cpp
+media/libstagefright/MediaSource.cpp
+media/libstagefright/Utils.cpp
diff --git a/OWNERS b/OWNERS
index 40c65e7..3c7a3ab 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,7 +1,16 @@
-# Bug component: 1344
+## Media team top-level OWNERS, bug component: 1344
+## Only contact for camera changes as a fallback
elaurent@google.com
-etalvala@google.com
lajos@google.com
# go/android-fwk-media-solutions for info on areas of ownership.
include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
+
+## Camera team top-level OWNERS, bug component: 41727
+## Only contact for media changes as a fallback
+etalvala@google.com
+shuzhenwang@google.com
+
+# mainline related
+per-file MainlineFiles.cfg=essick@google.com
+per-file MainlineFiles.cfg=file:/media/janitors/reliability_mainline_OWNERS
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 716b550..1f7083b 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -11,3 +11,4 @@
clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
media/libmediatranscoding/
services/mediatranscoding/
+ media/libaudioclient/tests/
diff --git a/aidl/android/media/MicrophoneInfoData.aidl b/aidl/android/media/MicrophoneInfoData.aidl
deleted file mode 100644
index 747bfa5..0000000
--- a/aidl/android/media/MicrophoneInfoData.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2020 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.
- */
-
-package android.media;
-
-/**
- * {@hide}
- */
-parcelable MicrophoneInfoData {
- @utf8InCpp String deviceId;
- int portId;
- int type;
- @utf8InCpp String address;
- int deviceLocation;
- int deviceGroup;
- int indexInTheGroup;
- float[] geometricLocation;
- float[] orientation;
- float[] frequencies;
- float[] frequencyResponses;
- int[] channelMapping;
- float sensitivity;
- float maxSpl;
- float minSpl;
- int directionality;
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioPortConfig.aidl b/aidl/android/media/MicrophoneInfoFw.aidl
similarity index 69%
copy from media/libaudioclient/aidl/android/media/AudioPortConfig.aidl
copy to aidl/android/media/MicrophoneInfoFw.aidl
index 3a4ca31..bad0e0a 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortConfig.aidl
+++ b/aidl/android/media/MicrophoneInfoFw.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright 2020 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.
@@ -16,13 +16,14 @@
package android.media;
-import android.media.AudioPortConfigSys;
-import android.media.audio.common.AudioPortConfig;
+import android.media.audio.common.MicrophoneDynamicInfo;
+import android.media.audio.common.MicrophoneInfo;
/**
* {@hide}
*/
-parcelable AudioPortConfig {
- AudioPortConfig hal;
- AudioPortConfigSys sys;
+parcelable MicrophoneInfoFw {
+ MicrophoneInfo info;
+ MicrophoneDynamicInfo dynamic;
+ int portId;
}
diff --git a/apex/Android.bp b/apex/Android.bp
index 570ca01..b0d7c02 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -67,13 +67,15 @@
// Use a custom AndroidManifest.xml used for API targeting.
androidManifest: ":com.android.media-androidManifest",
- // IMPORTANT: q-launched-apex-module enables the build system to make
- // sure the package compatible to Android 10 in two ways:
+ // IMPORTANT: q-launched-dcla-enabled-apex-module enables the build system to make
+ // sure the package compatible to Android 10 in two ways(if flag APEX_BUILD_FOR_PRE_S_DEVICES=1
+ // is set):
// - build the APEX package compatible to Android 10
// so that the package can be installed.
// - build artifacts (lib/javalib/bin) against Android 10 SDK
// so that the artifacts can run.
- defaults: ["q-launched-apex-module"],
+ // If the flag is not set, the package is built to be compatible with Android 12.
+ defaults: ["q-launched-dcla-enabled-apex-module"],
// Indicates that pre-installed version of this apex can be compressed.
// Whether it actually will be compressed is controlled on per-device basis.
compressible: true,
@@ -191,13 +193,15 @@
// Use a custom AndroidManifest.xml used for API targeting.
androidManifest: ":com.android.media.swcodec-androidManifest",
- // IMPORTANT: q-launched-apex-module enables the build system to make
- // sure the package compatible to Android 10 in two ways:
+ // IMPORTANT: q-launched-dcla-enabled-apex-module enables the build system to make
+ // sure the package compatible to Android 10 in two ways(if flag APEX_BUILD_FOR_PRE_S_DEVICES=1
+ // is set):
// - build the APEX package compatible to Android 10
// so that the package can be installed.
// - build artifacts (lib/javalib/bin) against Android 10 SDK
// so that the artifacts can run.
- defaults: ["q-launched-apex-module"],
+ // If the flag is not set, the package is built to be compatible with Android 12.
+ defaults: ["q-launched-dcla-enabled-apex-module"],
// Indicates that pre-installed version of this apex can be compressed.
// Whether it actually will be compressed is controlled on per-device basis.
compressible: true,
diff --git a/apex/ld.config.txt b/apex/ld.config.txt
index 713f0b7..4dc5fb1 100644
--- a/apex/ld.config.txt
+++ b/apex/ld.config.txt
@@ -33,7 +33,7 @@
# TODO: replace the following when apex has a way to auto-generate this list
# namespace.default.link.platform.shared_libs = %LLNDK_LIBRARIES%
# namespace.default.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so:libbinder_ndk.so
+namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so:libbinder_ndk.so
###############################################################################
# "platform" namespace
@@ -138,7 +138,7 @@
# TODO: replace the following when apex has a way to auto-generate this list
# namespace.sphal.link.platform.shared_libs = %LLNDK_LIBRARIES%
# namespace.sphal.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so:libbinder_ndk.so
+namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so:libbinder_ndk.so
# Add a link for libz.so which is llndk on devices where VNDK is not enforced.
namespace.sphal.link.platform.shared_libs += libz.so
diff --git a/apex/manifest.json b/apex/manifest.json
index 1a26bff..5b235cd 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,6 +1,10 @@
{
"name": "com.android.media",
- "version": 330400000,
+
+ // Placeholder module version to be replaced during build.
+ // Do not change!
+ "version": 0,
+
"requireNativeLibs": [
"libandroid.so",
"libbinder_ndk.so",
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
index 9426e59..f2b8b36 100644
--- a/apex/manifest_codec.json
+++ b/apex/manifest_codec.json
@@ -1,6 +1,10 @@
{
"name": "com.android.media.swcodec",
- "version": 330400000,
+
+ // Placeholder module version to be replaced during build.
+ // Do not change!
+ "version": 0,
+
"requireNativeLibs": [
":sphal"
]
diff --git a/camera/OWNERS b/camera/OWNERS
index 385c163..b705548 100644
--- a/camera/OWNERS
+++ b/camera/OWNERS
@@ -1,7 +1,11 @@
# Bug component: 41727
etalvala@google.com
arakesh@google.com
+borgera@google.com
+bkukreja@google.com
epeev@google.com
jchowdhary@google.com
-shuzhenwang@google.com
+rdhanjal@google.com
ruchamk@google.com
+shuzhenwang@google.com
+
diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h
index 7be4bd3..239cb31 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -470,18 +470,6 @@
* <a href="http://developer.android.com/reference/android/media/CamcorderProfile.html">
* CamcorderProfiles</a>.</li>
*
- * <li>For efficient YUV processing with <a href=
- * "http://developer.android.com/reference/android/renderscript/package-summary.html">
- * RenderScript</a>:
- * Create a RenderScript
- * <a href="http://developer.android.com/reference/android/renderscript/Allocation.html">
- * Allocation</a> with a supported YUV
- * type, the IO_INPUT flag, and one of the YUV output sizes returned by
- * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS},
- * Then obtain the Surface with
- * <a href="http://developer.android.com/reference/android/renderscript/Allocation.html#getSurface()">
- * Allocation#getSurface}</a>.</li>
- *
* <li>For access to RAW, uncompressed YUV, or compressed JPEG data in the application: Create an
* {@link AImageReader} object using the {@link AImageReader_new} method with one of the supported
* output formats given by {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS}. Then obtain a
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
index 77c934a..bb4ef56 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
@@ -165,7 +165,10 @@
Mutex::Autolock _l(mLock);
if (mCameraService != nullptr) {
mCameraService->unlinkToDeath(mDeathNotifier);
- mCameraService->removeListener(mCameraServiceListener);
+ auto stat = mCameraService->removeListener(mCameraServiceListener);
+ if (!stat.isOk()) {
+ ALOGE("Failed to remove listener to camera service %s", stat.description().c_str());
+ }
}
mDeathNotifier.clear();
if (mCbLooper != nullptr) {
@@ -475,6 +478,10 @@
ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
return;
}
+ if (cb == nullptr) {
+ // Physical camera callback is null
+ return;
+ }
found = msg->findPointer(kContextKey, &context);
if (!found) {
ALOGE("%s: Cannot find callback context!", __FUNCTION__);
diff --git a/cmds/stagefright/Android.bp b/cmds/stagefright/Android.bp
index e1fe07e..445541e 100644
--- a/cmds/stagefright/Android.bp
+++ b/cmds/stagefright/Android.bp
@@ -211,46 +211,6 @@
}
cc_binary {
- name: "mediafilter",
-
- srcs: [
- "filters/argbtorgba.rscript",
- "filters/nightvision.rscript",
- "filters/saturation.rscript",
- "mediafilter.cpp",
- ],
-
- header_libs: [
- "libmediadrm_headers",
- "libmediametrics_headers",
- "libstagefright_headers",
- "rs-headers",
- ],
-
- shared_libs: [
- "libstagefright",
- "liblog",
- "libutils",
- "libbinder",
- "libstagefright_foundation",
- "libmedia_omx",
- "libui",
- "libgui",
- "libRScpp",
- ],
-
- static_libs: ["libstagefright_mediafilter"],
-
- cflags: [
- "-Wno-multichar",
- ],
-
- sanitize: {
- cfi: true,
- },
-}
-
-cc_binary {
name: "muxer",
srcs: ["muxer.cpp"],
diff --git a/cmds/stagefright/SineSource.cpp b/cmds/stagefright/SineSource.cpp
index 0ecc16c..0656030 100644
--- a/cmds/stagefright/SineSource.cpp
+++ b/cmds/stagefright/SineSource.cpp
@@ -63,12 +63,15 @@
MediaBufferBase **out, const ReadOptions * /* options */) {
*out = NULL;
- MediaBufferBase *buffer;
+ MediaBufferBase *buffer = nullptr;
status_t err = mGroup->acquire_buffer(&buffer);
if (err != OK) {
return err;
}
+ if (buffer == nullptr) {
+ return AMEDIA_ERROR_UNKNOWN;
+ }
size_t frameSize = mNumChannels * sizeof(int16_t);
size_t numFramesPerBuffer = buffer->size() / frameSize;
diff --git a/cmds/stagefright/filters/argbtorgba.rscript b/cmds/stagefright/filters/argbtorgba.rscript
deleted file mode 100644
index 229ff8c..0000000
--- a/cmds/stagefright/filters/argbtorgba.rscript
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2014 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 version(1)
-#pragma rs java_package_name(com.android.rs.cppbasic)
-#pragma rs_fp_relaxed
-
-void root(const uchar4 *v_in, uchar4 *v_out) {
- v_out->x = v_in->y;
- v_out->y = v_in->z;
- v_out->z = v_in->w;
- v_out->w = v_in->x;
-}
\ No newline at end of file
diff --git a/cmds/stagefright/filters/nightvision.rscript b/cmds/stagefright/filters/nightvision.rscript
deleted file mode 100644
index f61413c..0000000
--- a/cmds/stagefright/filters/nightvision.rscript
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2014 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 version(1)
-#pragma rs java_package_name(com.android.rs.cppbasic)
-#pragma rs_fp_relaxed
-
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-const static float3 gNightVisionMult = {0.5f, 1.f, 0.5f};
-
-// calculates luminance of pixel, then biases color balance toward green
-void root(const uchar4 *v_in, uchar4 *v_out) {
- v_out->x = v_in->x; // don't modify A
-
- // get RGB, scale 0-255 uchar to 0-1.0 float
- float3 rgb = {v_in->y * 0.003921569f, v_in->z * 0.003921569f,
- v_in->w * 0.003921569f};
-
- // apply filter
- float3 result = dot(rgb, gMonoMult) * gNightVisionMult;
-
- v_out->y = (uchar)clamp((result.r * 255.f + 0.5f), 0.f, 255.f);
- v_out->z = (uchar)clamp((result.g * 255.f + 0.5f), 0.f, 255.f);
- v_out->w = (uchar)clamp((result.b * 255.f + 0.5f), 0.f, 255.f);
-}
diff --git a/cmds/stagefright/filters/saturation.rscript b/cmds/stagefright/filters/saturation.rscript
deleted file mode 100644
index 1de9dd8..0000000
--- a/cmds/stagefright/filters/saturation.rscript
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2014 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 version(1)
-#pragma rs java_package_name(com.android.rs.cppbasic)
-#pragma rs_fp_relaxed
-
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-
-// global variables (parameters accessible to application code)
-float gSaturation = 1.0f;
-
-void root(const uchar4 *v_in, uchar4 *v_out) {
- v_out->x = v_in->x; // don't modify A
-
- // get RGB, scale 0-255 uchar to 0-1.0 float
- float3 rgb = {v_in->y * 0.003921569f, v_in->z * 0.003921569f,
- v_in->w * 0.003921569f};
-
- // apply saturation filter
- float3 result = dot(rgb, gMonoMult);
- result = mix(result, rgb, gSaturation);
-
- v_out->y = (uchar)clamp((result.r * 255.f + 0.5f), 0.f, 255.f);
- v_out->z = (uchar)clamp((result.g * 255.f + 0.5f), 0.f, 255.f);
- v_out->w = (uchar)clamp((result.b * 255.f + 0.5f), 0.f, 255.f);
-}
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
deleted file mode 100644
index 67c68e6..0000000
--- a/cmds/stagefright/mediafilter.cpp
+++ /dev/null
@@ -1,789 +0,0 @@
-/*
- * Copyright (C) 2014 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 "mediafilterTest"
-
-#include <inttypes.h>
-
-#include <binder/ProcessState.h>
-#include <filters/ColorConvert.h>
-#include <gui/ISurfaceComposer.h>
-#include <gui/SurfaceComposerClient.h>
-#include <gui/Surface.h>
-#include <media/IMediaHTTPService.h>
-#include <media/MediaCodecBuffer.h>
-#include <mediadrm/ICrypto.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaCodec.h>
-#include <media/stagefright/NuMediaExtractor.h>
-#include <media/stagefright/RenderScriptWrapper.h>
-#include <OMX_IVCommon.h>
-#include <ui/DisplayMode.h>
-
-#include "RenderScript.h"
-#include "ScriptC_argbtorgba.h"
-#include "ScriptC_nightvision.h"
-#include "ScriptC_saturation.h"
-
-// test parameters
-static const bool kTestFlush = true; // Note: true will drop 1 out of
-static const int kFlushAfterFrames = 25; // kFlushAfterFrames output frames
-static const int64_t kTimeout = 500ll;
-
-// built-in filter parameters
-static const int32_t kInvert = false; // ZeroFilter param
-static const float kBlurRadius = 15.0f; // IntrinsicBlurFilter param
-static const float kSaturation = 0.0f; // SaturationFilter param
-
-static void usage(const char *me) {
- fprintf(stderr, "usage: [flags] %s\n"
- "\t[-b] use IntrinsicBlurFilter\n"
- "\t[-c] use argb to rgba conversion RSFilter\n"
- "\t[-n] use night vision RSFilter\n"
- "\t[-r] use saturation RSFilter\n"
- "\t[-s] use SaturationFilter\n"
- "\t[-z] use ZeroFilter (copy filter)\n"
- "\t[-R] render output to surface (enables -S)\n"
- "\t[-S] allocate buffers from a surface\n"
- "\t[-T] use render timestamps (enables -R)\n",
- me);
- exit(1);
-}
-
-namespace android {
-
-struct SaturationRSFilter : RenderScriptWrapper::RSFilterCallback {
- void init(const RSC::sp<RSC::RS> &context) {
- mScript = new ScriptC_saturation(context);
- mScript->set_gSaturation(3.f);
- }
-
- virtual status_t processBuffers(
- RSC::Allocation *inBuffer, RSC::Allocation *outBuffer) {
- mScript->forEach_root(inBuffer, outBuffer);
-
- return OK;
- }
-
- status_t handleSetParameters(const sp<AMessage> &msg __unused) {
- return OK;
- }
-
-private:
- RSC::sp<ScriptC_saturation> mScript;
-};
-
-struct NightVisionRSFilter : RenderScriptWrapper::RSFilterCallback {
- void init(const RSC::sp<RSC::RS> &context) {
- mScript = new ScriptC_nightvision(context);
- }
-
- virtual status_t processBuffers(
- RSC::Allocation *inBuffer, RSC::Allocation *outBuffer) {
- mScript->forEach_root(inBuffer, outBuffer);
-
- return OK;
- }
-
- status_t handleSetParameters(const sp<AMessage> &msg __unused) {
- return OK;
- }
-
-private:
- RSC::sp<ScriptC_nightvision> mScript;
-};
-
-struct ARGBToRGBARSFilter : RenderScriptWrapper::RSFilterCallback {
- void init(const RSC::sp<RSC::RS> &context) {
- mScript = new ScriptC_argbtorgba(context);
- }
-
- virtual status_t processBuffers(
- RSC::Allocation *inBuffer, RSC::Allocation *outBuffer) {
- mScript->forEach_root(inBuffer, outBuffer);
-
- return OK;
- }
-
- status_t handleSetParameters(const sp<AMessage> &msg __unused) {
- return OK;
- }
-
-private:
- RSC::sp<ScriptC_argbtorgba> mScript;
-};
-
-struct CodecState {
- sp<MediaCodec> mCodec;
- Vector<sp<MediaCodecBuffer> > mInBuffers;
- Vector<sp<MediaCodecBuffer> > mOutBuffers;
- bool mSignalledInputEOS;
- bool mSawOutputEOS;
- int64_t mNumBuffersDecoded;
-};
-
-struct DecodedFrame {
- size_t index;
- size_t offset;
- size_t size;
- int64_t presentationTimeUs;
- uint32_t flags;
-};
-
-enum FilterType {
- FILTERTYPE_ZERO,
- FILTERTYPE_INTRINSIC_BLUR,
- FILTERTYPE_SATURATION,
- FILTERTYPE_RS_SATURATION,
- FILTERTYPE_RS_NIGHT_VISION,
- FILTERTYPE_RS_ARGB_TO_RGBA,
-};
-
-size_t inputFramesSinceFlush = 0;
-void tryCopyDecodedBuffer(
- List<DecodedFrame> *decodedFrameIndices,
- CodecState *filterState,
- CodecState *vidState) {
- if (decodedFrameIndices->empty()) {
- return;
- }
-
- size_t filterIndex;
- status_t err = filterState->mCodec->dequeueInputBuffer(
- &filterIndex, kTimeout);
- if (err != OK) {
- return;
- }
-
- ++inputFramesSinceFlush;
-
- DecodedFrame frame = *decodedFrameIndices->begin();
-
- // only consume a buffer if we are not going to flush, since we expect
- // the dequeue -> flush -> queue operation to cause an error and
- // not produce an output frame
- if (!kTestFlush || inputFramesSinceFlush < kFlushAfterFrames) {
- decodedFrameIndices->erase(decodedFrameIndices->begin());
- }
- size_t outIndex = frame.index;
-
- const sp<MediaCodecBuffer> &srcBuffer =
- vidState->mOutBuffers.itemAt(outIndex);
- const sp<MediaCodecBuffer> &destBuffer =
- filterState->mInBuffers.itemAt(filterIndex);
-
- sp<AMessage> srcFormat, destFormat;
- vidState->mCodec->getOutputFormat(&srcFormat);
- filterState->mCodec->getInputFormat(&destFormat);
-
- int32_t srcWidth, srcHeight, srcStride, srcSliceHeight;
- int32_t srcColorFormat, destColorFormat;
- int32_t destWidth, destHeight, destStride, destSliceHeight;
- CHECK(srcFormat->findInt32("stride", &srcStride)
- && srcFormat->findInt32("slice-height", &srcSliceHeight)
- && srcFormat->findInt32("width", &srcWidth)
- && srcFormat->findInt32("height", & srcHeight)
- && srcFormat->findInt32("color-format", &srcColorFormat));
- CHECK(destFormat->findInt32("stride", &destStride)
- && destFormat->findInt32("slice-height", &destSliceHeight)
- && destFormat->findInt32("width", &destWidth)
- && destFormat->findInt32("height", & destHeight)
- && destFormat->findInt32("color-format", &destColorFormat));
-
- CHECK(srcWidth <= destStride && srcHeight <= destSliceHeight);
-
- convertYUV420spToARGB(
- srcBuffer->data(),
- srcBuffer->data() + srcStride * srcSliceHeight,
- srcWidth,
- srcHeight,
- destBuffer->data());
-
- // copy timestamp
- int64_t timeUs;
- CHECK(srcBuffer->meta()->findInt64("timeUs", &timeUs));
- destBuffer->meta()->setInt64("timeUs", timeUs);
-
- if (kTestFlush && inputFramesSinceFlush >= kFlushAfterFrames) {
- inputFramesSinceFlush = 0;
-
- // check that queueing a buffer that was dequeued before flush
- // fails with expected error EACCES
- filterState->mCodec->flush();
-
- err = filterState->mCodec->queueInputBuffer(
- filterIndex, 0 /* offset */, destBuffer->size(),
- timeUs, frame.flags);
-
- if (err == OK) {
- ALOGE("FAIL: queue after flush returned OK");
- } else if (err != -EACCES) {
- ALOGE("queueInputBuffer after flush returned %d, "
- "expected -EACCES (-13)", err);
- }
- } else {
- err = filterState->mCodec->queueInputBuffer(
- filterIndex, 0 /* offset */, destBuffer->size(),
- timeUs, frame.flags);
- CHECK(err == OK);
-
- err = vidState->mCodec->releaseOutputBuffer(outIndex);
- CHECK(err == OK);
- }
-}
-
-size_t outputFramesSinceFlush = 0;
-void tryDrainOutputBuffer(
- CodecState *filterState,
- const sp<Surface> &surface, bool renderSurface,
- bool useTimestamp, int64_t *startTimeRender) {
- size_t index;
- size_t offset;
- size_t size;
- int64_t presentationTimeUs;
- uint32_t flags;
- status_t err = filterState->mCodec->dequeueOutputBuffer(
- &index, &offset, &size, &presentationTimeUs, &flags,
- kTimeout);
-
- if (err != OK) {
- return;
- }
-
- ++outputFramesSinceFlush;
-
- if (kTestFlush && outputFramesSinceFlush >= kFlushAfterFrames) {
- filterState->mCodec->flush();
- }
-
- if (surface == NULL || !renderSurface) {
- err = filterState->mCodec->releaseOutputBuffer(index);
- } else if (useTimestamp) {
- if (*startTimeRender == -1) {
- // begin rendering 2 vsyncs after first decode
- *startTimeRender = systemTime(SYSTEM_TIME_MONOTONIC)
- + 33000000 - (presentationTimeUs * 1000);
- }
- presentationTimeUs =
- (presentationTimeUs * 1000) + *startTimeRender;
- err = filterState->mCodec->renderOutputBufferAndRelease(
- index, presentationTimeUs);
- } else {
- err = filterState->mCodec->renderOutputBufferAndRelease(index);
- }
-
- if (kTestFlush && outputFramesSinceFlush >= kFlushAfterFrames) {
- outputFramesSinceFlush = 0;
-
- // releasing the buffer dequeued before flush should cause an error
- // if so, the frame will also be skipped in output stream
- if (err == OK) {
- ALOGE("FAIL: release after flush returned OK");
- } else if (err != -EACCES) {
- ALOGE("releaseOutputBuffer after flush returned %d, "
- "expected -EACCES (-13)", err);
- }
- } else {
- CHECK(err == OK);
- }
-
- if (flags & MediaCodec::BUFFER_FLAG_EOS) {
- ALOGV("reached EOS on output.");
- filterState->mSawOutputEOS = true;
- }
-}
-
-static int decode(
- const sp<android::ALooper> &looper,
- const char *path,
- const sp<Surface> &surface,
- bool renderSurface,
- bool useTimestamp,
- FilterType filterType) {
-
- static int64_t kTimeout = 500ll;
-
- sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
-
- if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
- fprintf(stderr, "unable to instantiate extractor.\n");
- return 1;
- }
-
- KeyedVector<size_t, CodecState> stateByTrack;
-
- CodecState *vidState = NULL;
- for (size_t i = 0; i < extractor->countTracks(); ++i) {
- sp<AMessage> format;
- status_t err = extractor->getTrackFormat(i, &format);
- CHECK(err == OK);
-
- AString mime;
- CHECK(format->findString("mime", &mime));
- bool isVideo = !strncasecmp(mime.c_str(), "video/", 6);
- if (!isVideo) {
- continue;
- }
-
- ALOGV("selecting track %zu", i);
-
- err = extractor->selectTrack(i);
- CHECK(err == OK);
-
- CodecState *state =
- &stateByTrack.editValueAt(stateByTrack.add(i, CodecState()));
-
- vidState = state;
-
- state->mNumBuffersDecoded = 0;
-
- state->mCodec = MediaCodec::CreateByType(
- looper, mime.c_str(), false /* encoder */);
-
- CHECK(state->mCodec != NULL);
-
- err = state->mCodec->configure(
- format, NULL /* surface */, NULL /* crypto */, 0 /* flags */);
-
- CHECK(err == OK);
-
- state->mSignalledInputEOS = false;
- state->mSawOutputEOS = false;
-
- break;
- }
- CHECK(!stateByTrack.isEmpty());
- CHECK(vidState != NULL);
- sp<AMessage> vidFormat;
- vidState->mCodec->getOutputFormat(&vidFormat);
-
- // set filter to use ARGB8888
- vidFormat->setInt32("color-format", OMX_COLOR_Format32bitARGB8888);
- // set app cache directory path
- vidFormat->setString("cacheDir", "/system/bin");
-
- // create RenderScript context for RSFilters
- RSC::sp<RSC::RS> context = new RSC::RS();
- context->init("/system/bin");
-
- sp<RenderScriptWrapper::RSFilterCallback> rsFilter;
-
- // create renderscript wrapper for RSFilters
- sp<RenderScriptWrapper> rsWrapper = new RenderScriptWrapper;
- rsWrapper->mContext = context.get();
-
- CodecState *filterState = new CodecState();
- filterState->mNumBuffersDecoded = 0;
-
- sp<AMessage> params = new AMessage();
-
- switch (filterType) {
- case FILTERTYPE_ZERO:
- {
- filterState->mCodec = MediaCodec::CreateByComponentName(
- looper, "android.filter.zerofilter");
- params->setInt32("invert", kInvert);
- break;
- }
- case FILTERTYPE_INTRINSIC_BLUR:
- {
- filterState->mCodec = MediaCodec::CreateByComponentName(
- looper, "android.filter.intrinsicblur");
- params->setFloat("blur-radius", kBlurRadius);
- break;
- }
- case FILTERTYPE_SATURATION:
- {
- filterState->mCodec = MediaCodec::CreateByComponentName(
- looper, "android.filter.saturation");
- params->setFloat("saturation", kSaturation);
- break;
- }
- case FILTERTYPE_RS_SATURATION:
- {
- SaturationRSFilter *satFilter = new SaturationRSFilter;
- satFilter->init(context);
- rsFilter = satFilter;
- rsWrapper->mCallback = rsFilter;
- vidFormat->setObject("rs-wrapper", rsWrapper);
-
- filterState->mCodec = MediaCodec::CreateByComponentName(
- looper, "android.filter.RenderScript");
- break;
- }
- case FILTERTYPE_RS_NIGHT_VISION:
- {
- NightVisionRSFilter *nightVisionFilter = new NightVisionRSFilter;
- nightVisionFilter->init(context);
- rsFilter = nightVisionFilter;
- rsWrapper->mCallback = rsFilter;
- vidFormat->setObject("rs-wrapper", rsWrapper);
-
- filterState->mCodec = MediaCodec::CreateByComponentName(
- looper, "android.filter.RenderScript");
- break;
- }
- case FILTERTYPE_RS_ARGB_TO_RGBA:
- {
- ARGBToRGBARSFilter *argbToRgbaFilter = new ARGBToRGBARSFilter;
- argbToRgbaFilter->init(context);
- rsFilter = argbToRgbaFilter;
- rsWrapper->mCallback = rsFilter;
- vidFormat->setObject("rs-wrapper", rsWrapper);
-
- filterState->mCodec = MediaCodec::CreateByComponentName(
- looper, "android.filter.RenderScript");
- break;
- }
- default:
- {
- LOG_ALWAYS_FATAL("mediacodec.cpp error: unrecognized FilterType");
- break;
- }
- }
- CHECK(filterState->mCodec != NULL);
-
- status_t err = filterState->mCodec->configure(
- vidFormat /* format */, surface, NULL /* crypto */, 0 /* flags */);
- CHECK(err == OK);
-
- filterState->mSignalledInputEOS = false;
- filterState->mSawOutputEOS = false;
-
- int64_t startTimeUs = android::ALooper::GetNowUs();
- int64_t startTimeRender = -1;
-
- for (size_t i = 0; i < stateByTrack.size(); ++i) {
- CodecState *state = &stateByTrack.editValueAt(i);
-
- sp<MediaCodec> codec = state->mCodec;
-
- CHECK_EQ((status_t)OK, codec->start());
-
- CHECK_EQ((status_t)OK, codec->getInputBuffers(&state->mInBuffers));
- CHECK_EQ((status_t)OK, codec->getOutputBuffers(&state->mOutBuffers));
-
- ALOGV("got %zu input and %zu output buffers",
- state->mInBuffers.size(), state->mOutBuffers.size());
- }
-
- CHECK_EQ((status_t)OK, filterState->mCodec->setParameters(params));
-
- if (kTestFlush) {
- status_t flushErr = filterState->mCodec->flush();
- if (flushErr == OK) {
- ALOGE("FAIL: Flush before start returned OK");
- } else {
- ALOGV("Flush before start returned status %d, usually ENOSYS (-38)",
- flushErr);
- }
- }
-
- CHECK_EQ((status_t)OK, filterState->mCodec->start());
- CHECK_EQ((status_t)OK, filterState->mCodec->getInputBuffers(
- &filterState->mInBuffers));
- CHECK_EQ((status_t)OK, filterState->mCodec->getOutputBuffers(
- &filterState->mOutBuffers));
-
- if (kTestFlush) {
- status_t flushErr = filterState->mCodec->flush();
- if (flushErr != OK) {
- ALOGE("FAIL: Flush after start returned %d, expect OK (0)",
- flushErr);
- } else {
- ALOGV("Flush immediately after start OK");
- }
- }
-
- List<DecodedFrame> decodedFrameIndices;
-
- // loop until decoder reaches EOS
- bool sawInputEOS = false;
- bool sawOutputEOSOnAllTracks = false;
- while (!sawOutputEOSOnAllTracks) {
- if (!sawInputEOS) {
- size_t trackIndex;
- status_t err = extractor->getSampleTrackIndex(&trackIndex);
-
- if (err != OK) {
- ALOGV("saw input eos");
- sawInputEOS = true;
- } else {
- CodecState *state = &stateByTrack.editValueFor(trackIndex);
-
- size_t index;
- err = state->mCodec->dequeueInputBuffer(&index, kTimeout);
-
- if (err == OK) {
- ALOGV("filling input buffer %zu", index);
-
- const sp<MediaCodecBuffer> &buffer = state->mInBuffers.itemAt(index);
- sp<ABuffer> abuffer = new ABuffer(buffer->base(), buffer->capacity());
-
- err = extractor->readSampleData(abuffer);
- CHECK(err == OK);
- buffer->setRange(abuffer->offset(), abuffer->size());
-
- int64_t timeUs;
- err = extractor->getSampleTime(&timeUs);
- CHECK(err == OK);
-
- uint32_t bufferFlags = 0;
-
- err = state->mCodec->queueInputBuffer(
- index, 0 /* offset */, buffer->size(),
- timeUs, bufferFlags);
-
- CHECK(err == OK);
-
- extractor->advance();
- } else {
- CHECK_EQ(err, -EAGAIN);
- }
- }
- } else {
- for (size_t i = 0; i < stateByTrack.size(); ++i) {
- CodecState *state = &stateByTrack.editValueAt(i);
-
- if (!state->mSignalledInputEOS) {
- size_t index;
- status_t err =
- state->mCodec->dequeueInputBuffer(&index, kTimeout);
-
- if (err == OK) {
- ALOGV("signalling input EOS on track %zu", i);
-
- err = state->mCodec->queueInputBuffer(
- index, 0 /* offset */, 0 /* size */,
- 0ll /* timeUs */, MediaCodec::BUFFER_FLAG_EOS);
-
- CHECK(err == OK);
-
- state->mSignalledInputEOS = true;
- } else {
- CHECK_EQ(err, -EAGAIN);
- }
- }
- }
- }
-
- sawOutputEOSOnAllTracks = true;
- for (size_t i = 0; i < stateByTrack.size(); ++i) {
- CodecState *state = &stateByTrack.editValueAt(i);
-
- if (state->mSawOutputEOS) {
- continue;
- } else {
- sawOutputEOSOnAllTracks = false;
- }
-
- DecodedFrame frame;
- status_t err = state->mCodec->dequeueOutputBuffer(
- &frame.index, &frame.offset, &frame.size,
- &frame.presentationTimeUs, &frame.flags, kTimeout);
-
- if (err == OK) {
- ALOGV("draining decoded buffer %zu, time = %lld us",
- frame.index, (long long)frame.presentationTimeUs);
-
- ++(state->mNumBuffersDecoded);
-
- decodedFrameIndices.push_back(frame);
-
- if (frame.flags & MediaCodec::BUFFER_FLAG_EOS) {
- ALOGV("reached EOS on decoder output.");
- state->mSawOutputEOS = true;
- }
-
- } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
- ALOGV("INFO_OUTPUT_BUFFERS_CHANGED");
- CHECK_EQ((status_t)OK, state->mCodec->getOutputBuffers(
- &state->mOutBuffers));
-
- ALOGV("got %zu output buffers", state->mOutBuffers.size());
- } else if (err == INFO_FORMAT_CHANGED) {
- sp<AMessage> format;
- CHECK_EQ((status_t)OK, state->mCodec->getOutputFormat(&format));
-
- ALOGV("INFO_FORMAT_CHANGED: %s",
- format->debugString().c_str());
- } else {
- CHECK_EQ(err, -EAGAIN);
- }
-
- tryCopyDecodedBuffer(&decodedFrameIndices, filterState, vidState);
-
- tryDrainOutputBuffer(
- filterState, surface, renderSurface,
- useTimestamp, &startTimeRender);
- }
- }
-
- // after EOS on decoder, let filter reach EOS
- while (!filterState->mSawOutputEOS) {
- tryCopyDecodedBuffer(&decodedFrameIndices, filterState, vidState);
-
- tryDrainOutputBuffer(
- filterState, surface, renderSurface,
- useTimestamp, &startTimeRender);
- }
-
- int64_t elapsedTimeUs = android::ALooper::GetNowUs() - startTimeUs;
-
- for (size_t i = 0; i < stateByTrack.size(); ++i) {
- CodecState *state = &stateByTrack.editValueAt(i);
-
- CHECK_EQ((status_t)OK, state->mCodec->release());
-
- printf("track %zu: %" PRId64 " frames decoded and filtered, "
- "%.2f fps.\n", i, state->mNumBuffersDecoded,
- state->mNumBuffersDecoded * 1E6 / elapsedTimeUs);
- }
-
- return 0;
-}
-
-} // namespace android
-
-int main(int argc, char **argv) {
- using namespace android;
-
- const char *me = argv[0];
-
- bool useSurface = false;
- bool renderSurface = false;
- bool useTimestamp = false;
- FilterType filterType = FILTERTYPE_ZERO;
-
- int res;
- while ((res = getopt(argc, argv, "bcnrszTRSh")) >= 0) {
- switch (res) {
- case 'b':
- {
- filterType = FILTERTYPE_INTRINSIC_BLUR;
- break;
- }
- case 'c':
- {
- filterType = FILTERTYPE_RS_ARGB_TO_RGBA;
- break;
- }
- case 'n':
- {
- filterType = FILTERTYPE_RS_NIGHT_VISION;
- break;
- }
- case 'r':
- {
- filterType = FILTERTYPE_RS_SATURATION;
- break;
- }
- case 's':
- {
- filterType = FILTERTYPE_SATURATION;
- break;
- }
- case 'z':
- {
- filterType = FILTERTYPE_ZERO;
- break;
- }
- case 'T':
- {
- useTimestamp = true;
- FALLTHROUGH_INTENDED;
- }
- case 'R':
- {
- renderSurface = true;
- FALLTHROUGH_INTENDED;
- }
- case 'S':
- {
- useSurface = true;
- break;
- }
- case '?':
- case 'h':
- default:
- {
- usage(me);
- break;
- }
- }
- }
-
- argc -= optind;
- argv += optind;
-
- if (argc != 1) {
- usage(me);
- }
-
- ProcessState::self()->startThreadPool();
-
- android::sp<android::ALooper> looper = new android::ALooper;
- looper->start();
-
- android::sp<SurfaceComposerClient> composerClient;
- android::sp<SurfaceControl> control;
- android::sp<Surface> surface;
-
- if (useSurface) {
- composerClient = new SurfaceComposerClient;
- CHECK_EQ((status_t)OK, composerClient->initCheck());
-
- const android::sp<IBinder> display = SurfaceComposerClient::getInternalDisplayToken();
- CHECK(display != nullptr);
-
- ui::DisplayMode mode;
- CHECK_EQ(SurfaceComposerClient::getActiveDisplayMode(display, &mode), NO_ERROR);
-
- const ui::Size& resolution = mode.resolution;
- const ssize_t displayWidth = resolution.getWidth();
- const ssize_t displayHeight = resolution.getHeight();
-
- ALOGV("display is %zd x %zd", displayWidth, displayHeight);
-
- control = composerClient->createSurface(
- String8("A Surface"), displayWidth, displayHeight,
- PIXEL_FORMAT_RGBA_8888, 0);
-
- CHECK(control != NULL);
- CHECK(control->isValid());
-
- SurfaceComposerClient::Transaction{}
- .setLayer(control, INT_MAX)
- .show(control)
- .apply();
-
- surface = control->getSurface();
- CHECK(surface != NULL);
- }
-
- decode(looper, argv[0], surface, renderSurface, useTimestamp, filterType);
-
- if (useSurface) {
- composerClient->dispose();
- }
-
- looper->stop();
-
- return 0;
-}
diff --git a/cmds/stagefright/muxer.cpp b/cmds/stagefright/muxer.cpp
index bc7e41e..185491f 100644
--- a/cmds/stagefright/muxer.cpp
+++ b/cmds/stagefright/muxer.cpp
@@ -78,10 +78,14 @@
int fd = open(outputFileName, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
if (fd < 0) {
- ALOGE("couldn't open file");
- return fd;
+ ALOGE("couldn't open output file %s", outputFileName);
+ return 1;
}
- sp<MediaMuxer> muxer = new MediaMuxer(fd, container);
+ sp<MediaMuxer> muxer = MediaMuxer::create(fd, container);
+ if (muxer == nullptr) {
+ fprintf(stderr, "unable to instantiate muxer for format %d\n", container);
+ return 1;
+ }
close(fd);
size_t trackCount = extractor->countTracks();
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 5743ad6..87e8832 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -89,6 +89,9 @@
if (err != OK) {
return err;
}
+ if (buffer == nullptr) {
+ return AMEDIA_ERROR_UNKNOWN;
+ }
char x = (char)((double)rand() / RAND_MAX * 255);
memset((*buffer)->data(), x, mSize);
diff --git a/drm/README.md b/drm/README.md
new file mode 100644
index 0000000..2681aac
--- /dev/null
+++ b/drm/README.md
@@ -0,0 +1,13 @@
+## AIDL error handling
+
+Starting in **Android U (14)**, `libmediadrm` (app-side) understands extra error
+details from **AIDL** DRM HALs passed through the binder exception message
+as a json string. The supported fields are:
+* `cdmError` (*int*)
+* `oemError` (*int*)
+* `context` (*int*)
+* `errorMessage` (*str*)
+
+The errors details will be reported to apps through the java interface
+`android.media.MediaDrmThrowable`. Please see the javadoc of `MediaDrmThrowable`
+for detailed definitions of each field above.
diff --git a/drm/TEST_MAPPING b/drm/TEST_MAPPING
index 3642898..b2d4d6e 100644
--- a/drm/TEST_MAPPING
+++ b/drm/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "presubmit-large": [
+ "presubmit": [
// The following tests validate codec and drm path.
{
"name": "GtsMediaTestCases",
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index df3a6a2..ab25c65 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -63,3 +63,39 @@
init_rc: ["drmserver.rc"],
}
+
+cc_fuzz {
+ name: "drmserver_fuzzer",
+
+ defaults: [
+ "service_fuzzer_defaults",
+ ],
+
+ srcs: [
+ "fuzzer/DrmFuzzer.cpp",
+ "DrmManagerService.cpp",
+ "DrmManager.cpp",
+ ],
+
+ static_libs: [
+ "libmediautils",
+ "liblog",
+ "libdl",
+ "libdrmframeworkcommon",
+ "libselinux",
+ "libstagefright_foundation",
+ ],
+
+ shared_libs: [
+ "libmediametrics",
+ ],
+
+ fuzz_config: {
+ libfuzzer_options: [
+ "max_len=50000",
+ ],
+ cc: [
+ "android-drm-team@google.com",
+ ],
+ },
+}
\ No newline at end of file
diff --git a/drm/drmserver/DrmManagerService.h b/drm/drmserver/DrmManagerService.h
index f9b8bef..56201d9 100644
--- a/drm/drmserver/DrmManagerService.h
+++ b/drm/drmserver/DrmManagerService.h
@@ -141,6 +141,8 @@
virtual status_t dump(int fd, const Vector<String16>& args);
+ friend class DrmManagerServiceFuzzer;
+
private:
sp<DrmManager> mDrmManager;
};
diff --git a/drm/drmserver/fuzzer/DrmFuzzer.cpp b/drm/drmserver/fuzzer/DrmFuzzer.cpp
new file mode 100644
index 0000000..4b23679
--- /dev/null
+++ b/drm/drmserver/fuzzer/DrmFuzzer.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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 <fuzzbinder/libbinder_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "DrmManagerService.h"
+
+namespace android {
+class DrmManagerServiceFuzzer {
+public:
+ DrmManagerServiceFuzzer() {}
+
+ void fuzz(const uint8_t* data, size_t size) {
+ auto drmService = new DrmManagerService();
+ fuzzService(drmService, FuzzedDataProvider(data, size));
+ }
+};
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ android::DrmManagerServiceFuzzer serviceFuzzer;
+ serviceFuzzer.fuzz(data, size);
+ return 0;
+}
\ No newline at end of file
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
index be2b546..6e55a16 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
@@ -48,7 +48,6 @@
srcs: ["src/FwdLockEngine.cpp"],
shared_libs: [
- "libandroidicu",
"libutils",
"liblog",
"libdl",
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 408d216..7d68c5b 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -35,6 +35,8 @@
"CryptoHalAidl.cpp",
"DrmUtils.cpp",
"DrmHalListener.cpp",
+ "DrmStatus.cpp",
+ "DrmMetricsLogger.cpp",
],
local_include_dirs: [
@@ -74,6 +76,7 @@
static_libs: [
"resourcemanager_aidl_interface-ndk",
"libaidlcommonsupport",
+ "libjsoncpp",
],
export_shared_lib_headers: [
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index f95d527..fc1780d 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -71,7 +71,7 @@
mCryptoHalHidl->notifyResolution(width, height);
}
-status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+DrmStatus CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
// This requires plugin to be created.
if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->setMediaDrmSession(sessionId);
return mCryptoHalHidl->setMediaDrmSession(sessionId);
diff --git a/drm/libmediadrm/CryptoHalAidl.cpp b/drm/libmediadrm/CryptoHalAidl.cpp
index 8b9d1de..c1fd797 100644
--- a/drm/libmediadrm/CryptoHalAidl.cpp
+++ b/drm/libmediadrm/CryptoHalAidl.cpp
@@ -41,7 +41,7 @@
using ::aidl::android::hardware::drm::DecryptArgs;
using ::android::sp;
-using ::android::DrmUtils::statusAidlToStatusT;
+using ::android::DrmUtils::statusAidlToDrmStatus;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_memory;
@@ -260,7 +260,7 @@
}
}
-status_t CryptoHalAidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+DrmStatus CryptoHalAidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
@@ -268,7 +268,7 @@
}
auto err = mPlugin->setMediaDrmSession(toStdVec(sessionId));
- return statusAidlToStatusT(err);
+ return statusAidlToDrmStatus(err);
}
ssize_t CryptoHalAidl::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
@@ -352,7 +352,7 @@
int32_t result = 0;
::ndk::ScopedAStatus statusAidl = mPlugin->decrypt(args, &result);
- err = statusAidlToStatusT(statusAidl);
+ err = statusAidlToDrmStatus(statusAidl);
std::string msgStr(statusAidl.getMessage());
if (errorDetailMsg != nullptr) {
*errorDetailMsg = toString8(msgStr);
diff --git a/drm/libmediadrm/CryptoHalHidl.cpp b/drm/libmediadrm/CryptoHalHidl.cpp
index 55364b5..458a1ae 100644
--- a/drm/libmediadrm/CryptoHalHidl.cpp
+++ b/drm/libmediadrm/CryptoHalHidl.cpp
@@ -386,7 +386,7 @@
ALOGE_IF(!hResult.isOk(), "notifyResolution txn failed %s", hResult.description().c_str());
}
-status_t CryptoHalHidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+DrmStatus CryptoHalHidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index c394d5a..754f066 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -20,6 +20,7 @@
#include <mediadrm/DrmHal.h>
#include <mediadrm/DrmHalAidl.h>
#include <mediadrm/DrmHalHidl.h>
+#include <mediadrm/DrmStatus.h>
#include <mediadrm/DrmUtils.h>
namespace android {
@@ -31,49 +32,49 @@
DrmHal::~DrmHal() {}
-status_t DrmHal::initCheck() const {
- if (mDrmHalAidl->initCheck() == OK || mDrmHalHidl->initCheck() == OK) return OK;
- if (mDrmHalAidl->initCheck() == NO_INIT || mDrmHalHidl->initCheck() == NO_INIT) return NO_INIT;
+DrmStatus DrmHal::initCheck() const {
+ if (mDrmHalAidl->initCheck() == OK || mDrmHalHidl->initCheck() == OK) return DrmStatus(OK);
+ if (mDrmHalAidl->initCheck() == NO_INIT || mDrmHalHidl->initCheck() == NO_INIT)
+ return DrmStatus(NO_INIT);
return mDrmHalHidl->initCheck();
}
-status_t DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
- DrmPlugin::SecurityLevel securityLevel, bool* result) {
- status_t statusResult;
- statusResult = mDrmHalAidl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
+DrmStatus DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel, bool* result) {
+ DrmStatus statusResult =
+ mDrmHalAidl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
if (*result) return statusResult;
return mDrmHalHidl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
}
-status_t DrmHal::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
- status_t statusResult;
- statusResult = mDrmHalAidl->createPlugin(uuid, appPackageName);
- if (statusResult != OK) return mDrmHalHidl->createPlugin(uuid, appPackageName);
- return statusResult;
+DrmStatus DrmHal::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+ return mDrmHalAidl->createPlugin(uuid, appPackageName) == OK
+ ? DrmStatus(OK)
+ : mDrmHalHidl->createPlugin(uuid, appPackageName);
}
-status_t DrmHal::destroyPlugin() {
- status_t statusResult = mDrmHalAidl->destroyPlugin();
- status_t statusResultHidl = mDrmHalHidl->destroyPlugin();
+DrmStatus DrmHal::destroyPlugin() {
+ DrmStatus statusResult = mDrmHalAidl->destroyPlugin();
+ DrmStatus statusResultHidl = mDrmHalHidl->destroyPlugin();
if (statusResult != OK) return statusResult;
return statusResultHidl;
}
-status_t DrmHal::openSession(DrmPlugin::SecurityLevel securityLevel, Vector<uint8_t>& sessionId) {
+DrmStatus DrmHal::openSession(DrmPlugin::SecurityLevel securityLevel, Vector<uint8_t>& sessionId) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->openSession(securityLevel, sessionId);
return mDrmHalHidl->openSession(securityLevel, sessionId);
}
-status_t DrmHal::closeSession(Vector<uint8_t> const& sessionId) {
+DrmStatus DrmHal::closeSession(Vector<uint8_t> const& sessionId) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->closeSession(sessionId);
return mDrmHalHidl->closeSession(sessionId);
}
-status_t DrmHal::getKeyRequest(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& initData,
- String8 const& mimeType, DrmPlugin::KeyType keyType,
- KeyedVector<String8, String8> const& optionalParameters,
- Vector<uint8_t>& request, String8& defaultUrl,
- DrmPlugin::KeyRequestType* keyRequestType) {
+DrmStatus DrmHal::getKeyRequest(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& initData,
+ String8 const& mimeType, DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->getKeyRequest(sessionId, initData, mimeType, keyType,
optionalParameters, request, defaultUrl, keyRequestType);
@@ -81,212 +82,212 @@
request, defaultUrl, keyRequestType);
}
-status_t DrmHal::provideKeyResponse(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& response, Vector<uint8_t>& keySetId) {
+DrmStatus DrmHal::provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response, Vector<uint8_t>& keySetId) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->provideKeyResponse(sessionId, response, keySetId);
return mDrmHalHidl->provideKeyResponse(sessionId, response, keySetId);
}
-status_t DrmHal::removeKeys(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHal::removeKeys(Vector<uint8_t> const& keySetId) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeKeys(keySetId);
return mDrmHalHidl->removeKeys(keySetId);
}
-status_t DrmHal::restoreKeys(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHal::restoreKeys(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keySetId) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->restoreKeys(sessionId, keySetId);
return mDrmHalHidl->restoreKeys(sessionId, keySetId);
}
-status_t DrmHal::queryKeyStatus(Vector<uint8_t> const& sessionId,
- KeyedVector<String8, String8>& infoMap) const {
+DrmStatus DrmHal::queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->queryKeyStatus(sessionId, infoMap);
return mDrmHalHidl->queryKeyStatus(sessionId, infoMap);
}
-status_t DrmHal::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
- Vector<uint8_t>& request, String8& defaultUrl) {
+DrmStatus DrmHal::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
return mDrmHalHidl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
}
-status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const& response,
- Vector<uint8_t>& certificate,
- Vector<uint8_t>& wrappedKey) {
+DrmStatus DrmHal::provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->provideProvisionResponse(response, certificate, wrappedKey);
return mDrmHalHidl->provideProvisionResponse(response, certificate, wrappedKey);
}
-status_t DrmHal::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+DrmStatus DrmHal::getSecureStops(List<Vector<uint8_t>>& secureStops) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStops(secureStops);
return mDrmHalHidl->getSecureStops(secureStops);
}
-status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+DrmStatus DrmHal::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStopIds(secureStopIds);
return mDrmHalHidl->getSecureStopIds(secureStopIds);
}
-status_t DrmHal::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+DrmStatus DrmHal::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStop(ssid, secureStop);
return mDrmHalHidl->getSecureStop(ssid, secureStop);
}
-status_t DrmHal::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+DrmStatus DrmHal::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->releaseSecureStops(ssRelease);
return mDrmHalHidl->releaseSecureStops(ssRelease);
}
-status_t DrmHal::removeSecureStop(Vector<uint8_t> const& ssid) {
+DrmStatus DrmHal::removeSecureStop(Vector<uint8_t> const& ssid) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeSecureStop(ssid);
return mDrmHalHidl->removeSecureStop(ssid);
}
-status_t DrmHal::removeAllSecureStops() {
+DrmStatus DrmHal::removeAllSecureStops() {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeAllSecureStops();
return mDrmHalHidl->removeAllSecureStops();
}
-status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
- DrmPlugin::HdcpLevel* maxLevel) const {
+DrmStatus DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+ DrmPlugin::HdcpLevel* maxLevel) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getHdcpLevels(connectedLevel, maxLevel);
return mDrmHalHidl->getHdcpLevels(connectedLevel, maxLevel);
}
-status_t DrmHal::getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const {
+DrmStatus DrmHal::getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->getNumberOfSessions(currentSessions, maxSessions);
return mDrmHalHidl->getNumberOfSessions(currentSessions, maxSessions);
}
-status_t DrmHal::getSecurityLevel(Vector<uint8_t> const& sessionId,
- DrmPlugin::SecurityLevel* level) const {
+DrmStatus DrmHal::getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecurityLevel(sessionId, level);
return mDrmHalHidl->getSecurityLevel(sessionId, level);
}
-status_t DrmHal::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+DrmStatus DrmHal::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getOfflineLicenseKeySetIds(keySetIds);
return mDrmHalHidl->getOfflineLicenseKeySetIds(keySetIds);
}
-status_t DrmHal::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHal::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeOfflineLicense(keySetId);
return mDrmHalHidl->removeOfflineLicense(keySetId);
}
-status_t DrmHal::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
- DrmPlugin::OfflineLicenseState* licenseState) const {
+DrmStatus DrmHal::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->getOfflineLicenseState(keySetId, licenseState);
return mDrmHalHidl->getOfflineLicenseState(keySetId, licenseState);
}
-status_t DrmHal::getPropertyString(String8 const& name, String8& value) const {
+DrmStatus DrmHal::getPropertyString(String8 const& name, String8& value) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getPropertyString(name, value);
return mDrmHalHidl->getPropertyString(name, value);
}
-status_t DrmHal::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+DrmStatus DrmHal::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getPropertyByteArray(name, value);
return mDrmHalHidl->getPropertyByteArray(name, value);
}
-status_t DrmHal::setPropertyString(String8 const& name, String8 const& value) const {
+DrmStatus DrmHal::setPropertyString(String8 const& name, String8 const& value) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPropertyString(name, value);
return mDrmHalHidl->setPropertyString(name, value);
}
-status_t DrmHal::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+DrmStatus DrmHal::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPropertyByteArray(name, value);
return mDrmHalHidl->setPropertyByteArray(name, value);
}
-status_t DrmHal::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+DrmStatus DrmHal::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getMetrics(consumer);
return mDrmHalHidl->getMetrics(consumer);
}
-status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+DrmStatus DrmHal::setCipherAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->setCipherAlgorithm(sessionId, algorithm);
return mDrmHalHidl->setCipherAlgorithm(sessionId, algorithm);
}
-status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+DrmStatus DrmHal::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setMacAlgorithm(sessionId, algorithm);
return mDrmHalHidl->setMacAlgorithm(sessionId, algorithm);
}
-status_t DrmHal::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output) {
+DrmStatus DrmHal::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->encrypt(sessionId, keyId, input, iv, output);
return mDrmHalHidl->encrypt(sessionId, keyId, input, iv, output);
}
-status_t DrmHal::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output) {
+DrmStatus DrmHal::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->decrypt(sessionId, keyId, input, iv, output);
return mDrmHalHidl->decrypt(sessionId, keyId, input, iv, output);
}
-status_t DrmHal::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+DrmStatus DrmHal::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->sign(sessionId, keyId, message, signature);
return mDrmHalHidl->sign(sessionId, keyId, message, signature);
}
-status_t DrmHal::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
- bool& match) {
+DrmStatus DrmHal::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->verify(sessionId, keyId, message, signature, match);
return mDrmHalHidl->verify(sessionId, keyId, message, signature, match);
}
-status_t DrmHal::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
- Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
- Vector<uint8_t>& signature) {
+DrmStatus DrmHal::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
return mDrmHalHidl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
}
-status_t DrmHal::setListener(const sp<IDrmClient>& listener) {
+DrmStatus DrmHal::setListener(const sp<IDrmClient>& listener) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setListener(listener);
return mDrmHalHidl->setListener(listener);
}
-status_t DrmHal::requiresSecureDecoder(const char* mime, bool* required) const {
+DrmStatus DrmHal::requiresSecureDecoder(const char* mime, bool* required) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->requiresSecureDecoder(mime, required);
return mDrmHalHidl->requiresSecureDecoder(mime, required);
}
-status_t DrmHal::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
- bool* required) const {
+DrmStatus DrmHal::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->requiresSecureDecoder(mime, securityLevel, required);
return mDrmHalHidl->requiresSecureDecoder(mime, securityLevel, required);
}
-status_t DrmHal::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+DrmStatus DrmHal::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPlaybackId(sessionId, playbackId);
return mDrmHalHidl->setPlaybackId(sessionId, playbackId);
}
-status_t DrmHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+DrmStatus DrmHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getLogMessages(logs);
return mDrmHalHidl->getLogMessages(logs);
}
-status_t DrmHal::getSupportedSchemes(std::vector<uint8_t> &schemes) const {
+DrmStatus DrmHal::getSupportedSchemes(std::vector<uint8_t>& schemes) const {
status_t statusResult;
statusResult = mDrmHalAidl->getSupportedSchemes(schemes);
if (statusResult == OK) return statusResult;
diff --git a/drm/libmediadrm/DrmHalAidl.cpp b/drm/libmediadrm/DrmHalAidl.cpp
index bdd83e9..5ec7337 100644
--- a/drm/libmediadrm/DrmHalAidl.cpp
+++ b/drm/libmediadrm/DrmHalAidl.cpp
@@ -29,9 +29,9 @@
#include <media/stagefright/foundation/hexdump.h>
#include <mediadrm/DrmHalAidl.h>
#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/DrmStatus.h>
#include <mediadrm/DrmUtils.h>
-using ::android::DrmUtils::statusAidlToStatusT;
using ::aidl::android::hardware::drm::CryptoSchemes;
using ::aidl::android::hardware::drm::DrmMetricNamedValue;
using ::aidl::android::hardware::drm::DrmMetricValue;
@@ -55,6 +55,7 @@
using ::aidl::android::hardware::drm::Status;
using ::aidl::android::hardware::drm::SupportedContentType;
using ::aidl::android::hardware::drm::Uuid;
+using ::android::DrmUtils::statusAidlToDrmStatus;
using DrmMetricGroupAidl = ::aidl::android::hardware::drm::DrmMetricGroup;
using DrmMetricGroupHidl = ::android::hardware::drm::V1_1::DrmMetricGroup;
using DrmMetricAidl = ::aidl::android::hardware::drm::DrmMetric;
@@ -392,23 +393,24 @@
// DrmHalAidl methods
DrmHalAidl::DrmHalAidl()
- : mListener(::ndk::SharedRefBase::make<DrmHalListener>(&mMetrics)),
+ : mMetrics(std::make_shared<MediaDrmMetrics>()),
+ mListener(::ndk::SharedRefBase::make<DrmHalListener>(mMetrics)),
mFactories(DrmUtils::makeDrmFactoriesAidl()),
mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {}
-status_t DrmHalAidl::initCheck() const {
- return mInitCheck;
+DrmStatus DrmHalAidl::initCheck() const {
+ return DrmStatus(mInitCheck);
}
DrmHalAidl::~DrmHalAidl() {}
-status_t DrmHalAidl::setListener(const sp<IDrmClient>& listener) {
+DrmStatus DrmHalAidl::setListener(const sp<IDrmClient>& listener) {
mListener->setListener(listener);
- return NO_ERROR;
+ return DrmStatus(NO_ERROR);
}
-status_t DrmHalAidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
- DrmPlugin::SecurityLevel level, bool* isSupported) {
+DrmStatus DrmHalAidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level, bool* isSupported) {
Mutex::Autolock autoLock(mLock);
*isSupported = false;
Uuid uuidAidl = DrmUtils::toAidlUuid(uuid);
@@ -438,9 +440,9 @@
// isCryptoSchemeSupported(uuid, mimeType)
*isSupported = contentTypes.count(mimeTypeStr);
}
- return OK;
+ return DrmStatus(OK);
} else if (mimeType == "") {
- return BAD_VALUE;
+ return DrmStatus(BAD_VALUE);
}
auto ct = contentTypes[mimeTypeStr];
@@ -452,17 +454,17 @@
break;
}
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalAidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+DrmStatus DrmHalAidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
Mutex::Autolock autoLock(mLock);
-
+ if (mInitCheck == ERROR_UNSUPPORTED) return mInitCheck;
Uuid uuidAidl = DrmUtils::toAidlUuid(uuid);
std::string appPackageNameAidl = toStdString(appPackageName);
std::shared_ptr<IDrmPluginAidl> pluginAidl;
- mMetrics.SetAppPackageName(appPackageName);
- mMetrics.SetAppUid(AIBinder_getCallingUid());
+ mMetrics->SetAppPackageName(appPackageName);
+ mMetrics->SetAppUid(AIBinder_getCallingUid());
for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
::ndk::ScopedAStatus status =
mFactories[i]->createDrmPlugin(uuidAidl, appPackageNameAidl, &pluginAidl);
@@ -497,10 +499,10 @@
}
}
- return mInitCheck;
+ return DrmStatus(mInitCheck);
}
-status_t DrmHalAidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
+DrmStatus DrmHalAidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -510,14 +512,14 @@
return ERROR_DRM_CANNOT_HANDLE;
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
bool retry = true;
do {
std::vector<uint8_t> aSessionId;
::ndk::ScopedAStatus status = mPlugin->openSession(aSecurityLevel, &aSessionId);
if (status.isOk()) sessionId = toVector(aSessionId);
- err = statusAidlToStatusT(status);
+ err = statusAidlToDrmStatus(status);
if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
mLock.unlock();
@@ -538,20 +540,20 @@
AIBinder_getCallingPid(), std::static_pointer_cast<IResourceManagerClient>(client),
sessionId);
mOpenSessions.push_back(client);
- mMetrics.SetSessionStart(sessionId);
+ mMetrics->SetSessionStart(sessionId);
}
- mMetrics.mOpenSessionCounter.Increment(err);
+ mMetrics->mOpenSessionCounter.Increment(err);
return err;
}
-status_t DrmHalAidl::closeSession(Vector<uint8_t> const& sessionId) {
+DrmStatus DrmHalAidl::closeSession(Vector<uint8_t> const& sessionId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
::ndk::ScopedAStatus status = mPlugin->closeSession(sessionIdAidl);
- status_t response = statusAidlToStatusT(status);
+ DrmStatus response = statusAidlToDrmStatus(status);
if (status.isOk()) {
DrmSessionManager::Instance()->removeSession(sessionId);
for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) {
@@ -561,22 +563,22 @@
}
}
- mMetrics.SetSessionEnd(sessionId);
+ mMetrics->SetSessionEnd(sessionId);
}
- mMetrics.mCloseSessionCounter.Increment(response);
+ mMetrics->mCloseSessionCounter.Increment(response);
return response;
}
-status_t DrmHalAidl::getKeyRequest(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& initData, String8 const& mimeType,
- DrmPlugin::KeyType keyType,
- KeyedVector<String8, String8> const& optionalParameters,
- Vector<uint8_t>& request, String8& defaultUrl,
- DrmPlugin::KeyRequestType* keyRequestType) {
+DrmStatus DrmHalAidl::getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
+ EventTimer<status_t> keyRequestTimer(&mMetrics->mGetKeyRequestTimeUs);
DrmSessionManager::Instance()->useSession(sessionId);
@@ -592,7 +594,7 @@
return BAD_VALUE;
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
std::vector<uint8_t> initDataAidl = toStdVec(initData);
@@ -607,21 +609,21 @@
*keyRequestType = toKeyRequestType(keyRequest.requestType);
}
- err = statusAidlToStatusT(status);
+ err = statusAidlToDrmStatus(status);
keyRequestTimer.SetAttribute(err);
return err;
}
-status_t DrmHalAidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& response,
- Vector<uint8_t>& keySetId) {
+DrmStatus DrmHalAidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response,
+ Vector<uint8_t>& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
+ EventTimer<status_t> keyResponseTimer(&mMetrics->mProvideKeyResponseTimeUs);
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
std::vector<uint8_t> responseAidl = toStdVec(response);
@@ -630,21 +632,21 @@
mPlugin->provideKeyResponse(sessionIdAidl, responseAidl, &keySetIdsAidl);
if (status.isOk()) keySetId = toVector(keySetIdsAidl.keySetId);
- err = statusAidlToStatusT(status);
+ err = statusAidlToDrmStatus(status);
keyResponseTimer.SetAttribute(err);
return err;
}
-status_t DrmHalAidl::removeKeys(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalAidl::removeKeys(Vector<uint8_t> const& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
::ndk::ScopedAStatus status = mPlugin->removeKeys(toStdVec(keySetId));
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::restoreKeys(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalAidl::restoreKeys(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -653,11 +655,11 @@
KeySetId keySetIdsAidl;
keySetIdsAidl.keySetId = toStdVec(keySetId);
::ndk::ScopedAStatus status = mPlugin->restoreKeys(toStdVec(sessionId), keySetIdsAidl);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
- KeyedVector<String8, String8>& infoMap) const {
+DrmStatus DrmHalAidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -668,15 +670,15 @@
infoMap = toKeyedVector(infoMapAidl);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
- Vector<uint8_t>& request, String8& defaultUrl) {
+DrmStatus DrmHalAidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
ProvisionRequest requestAidl;
::ndk::ScopedAStatus status = mPlugin->getProvisionRequest(
@@ -685,29 +687,29 @@
request = toVector(requestAidl.request);
defaultUrl = toString8(requestAidl.defaultUrl);
- err = statusAidlToStatusT(status);
- mMetrics.mGetProvisionRequestCounter.Increment(err);
+ err = statusAidlToDrmStatus(status);
+ mMetrics->mGetProvisionRequestCounter.Increment(err);
return err;
}
-status_t DrmHalAidl::provideProvisionResponse(Vector<uint8_t> const& response,
- Vector<uint8_t>& certificate,
- Vector<uint8_t>& wrappedKey) {
+DrmStatus DrmHalAidl::provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
ProvideProvisionResponseResult result;
::ndk::ScopedAStatus status = mPlugin->provideProvisionResponse(toStdVec(response), &result);
certificate = toVector(result.certificate);
wrappedKey = toVector(result.wrappedKey);
- err = statusAidlToStatusT(status);
- mMetrics.mProvideProvisionResponseCounter.Increment(err);
+ err = statusAidlToDrmStatus(status);
+ mMetrics->mProvideProvisionResponseCounter.Increment(err);
return err;
}
-status_t DrmHalAidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+DrmStatus DrmHalAidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -716,10 +718,10 @@
secureStops = toSecureStops(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+DrmStatus DrmHalAidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -728,10 +730,10 @@
secureStopIds = toSecureStopIds(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+DrmStatus DrmHalAidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -743,10 +745,10 @@
secureStop = toVector(result.opaqueData);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+DrmStatus DrmHalAidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -754,10 +756,10 @@
ssId.opaqueData = toStdVec(ssRelease);
::ndk::ScopedAStatus status = mPlugin->releaseSecureStops(ssId);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::removeSecureStop(Vector<uint8_t> const& ssid) {
+DrmStatus DrmHalAidl::removeSecureStop(Vector<uint8_t> const& ssid) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -765,19 +767,19 @@
SecureStopId ssidAidl;
ssidAidl.secureStopId = toStdVec(ssid);
::ndk::ScopedAStatus status = mPlugin->removeSecureStop(ssidAidl);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::removeAllSecureStops() {
+DrmStatus DrmHalAidl::removeAllSecureStops() {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
::ndk::ScopedAStatus status = mPlugin->releaseAllSecureStops();
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
- DrmPlugin::HdcpLevel* max) const {
+DrmStatus DrmHalAidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
+ DrmPlugin::HdcpLevel* max) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -794,10 +796,10 @@
*connected = toHdcpLevel(lvlsAidl.connectedLevel);
*max = toHdcpLevel(lvlsAidl.maxLevel);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
+DrmStatus DrmHalAidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -814,11 +816,11 @@
*open = result.currentSessions;
*max = result.maxSessions;
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
- DrmPlugin::SecurityLevel* level) const {
+DrmStatus DrmHalAidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -833,10 +835,10 @@
*level = toSecurityLevel(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+DrmStatus DrmHalAidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -845,21 +847,21 @@
keySetIds = toKeySetIds(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalAidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
KeySetId keySetIdAidl;
keySetIdAidl.keySetId = toStdVec(keySetId);
::ndk::ScopedAStatus status = mPlugin->removeOfflineLicense(keySetIdAidl);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
- DrmPlugin::OfflineLicenseState* licenseState) const {
+DrmStatus DrmHalAidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -873,15 +875,15 @@
*licenseState = toOfflineLicenseState(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getPropertyString(String8 const& name, String8& value) const {
+DrmStatus DrmHalAidl::getPropertyString(String8 const& name, String8& value) const {
Mutex::Autolock autoLock(mLock);
- return getPropertyStringInternal(name, value);
+ return DrmStatus(getPropertyStringInternal(name, value));
}
-status_t DrmHalAidl::getPropertyStringInternal(String8 const& name, String8& value) const {
+DrmStatus DrmHalAidl::getPropertyStringInternal(String8 const& name, String8& value) const {
// This function is internal to the class and should only be called while
// mLock is already held.
INIT_CHECK();
@@ -891,54 +893,55 @@
value = toString8(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+DrmStatus DrmHalAidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
Mutex::Autolock autoLock(mLock);
- return getPropertyByteArrayInternal(name, value);
+ return DrmStatus(getPropertyByteArrayInternal(name, value));
}
-status_t DrmHalAidl::getPropertyByteArrayInternal(String8 const& name,
- Vector<uint8_t>& value) const {
+DrmStatus DrmHalAidl::getPropertyByteArrayInternal(String8 const& name,
+ Vector<uint8_t>& value) const {
// This function is internal to the class and should only be called while
// mLock is already held.
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
std::vector<uint8_t> result;
::ndk::ScopedAStatus status = mPlugin->getPropertyByteArray(toStdString(name), &result);
value = toVector(result);
- err = statusAidlToStatusT(status);
+ err = statusAidlToDrmStatus(status);
if (name == kPropertyDeviceUniqueId) {
- mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
+ mMetrics->mGetDeviceUniqueIdCounter.Increment(err);
}
return err;
}
-status_t DrmHalAidl::setPropertyString(String8 const& name, String8 const& value) const {
+DrmStatus DrmHalAidl::setPropertyString(String8 const& name, String8 const& value) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
::ndk::ScopedAStatus status = mPlugin->setPropertyString(toStdString(name), toStdString(value));
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+DrmStatus DrmHalAidl::setPropertyByteArray(String8 const& name,
+ Vector<uint8_t> const& value) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
::ndk::ScopedAStatus status = mPlugin->setPropertyByteArray(toStdString(name), toStdVec(value));
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+DrmStatus DrmHalAidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
if (consumer == nullptr) {
- return UNEXPECTED_NULL;
+ return DrmStatus(UNEXPECTED_NULL);
}
- consumer->consumeFrameworkMetrics(mMetrics);
+ consumer->consumeFrameworkMetrics(*mMetrics.get());
// Append vendor metrics if they are supported.
@@ -957,7 +960,7 @@
vendor += description;
hidl_vec<DrmMetricGroupHidl> pluginMetrics;
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
std::vector<DrmMetricGroupAidl> result;
::ndk::ScopedAStatus status = mPlugin->getMetrics(&result);
@@ -967,13 +970,13 @@
consumer->consumeHidlMetrics(vendor, pluginMetrics);
}
- err = statusAidlToStatusT(status);
+ err = statusAidlToDrmStatus(status);
return err;
}
-status_t DrmHalAidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
- String8 const& algorithm) {
+DrmStatus DrmHalAidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+ String8 const& algorithm) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -981,10 +984,10 @@
::ndk::ScopedAStatus status =
mPlugin->setCipherAlgorithm(toStdVec(sessionId), toStdString(algorithm));
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+DrmStatus DrmHalAidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -992,12 +995,12 @@
::ndk::ScopedAStatus status =
mPlugin->setMacAlgorithm(toStdVec(sessionId), toStdString(algorithm));
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output) {
+DrmStatus DrmHalAidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1009,12 +1012,12 @@
output = toVector(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output) {
+DrmStatus DrmHalAidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1026,11 +1029,11 @@
output = toVector(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+DrmStatus DrmHalAidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1042,12 +1045,12 @@
signature = toVector(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
- bool& match) {
+DrmStatus DrmHalAidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1056,12 +1059,12 @@
::ndk::ScopedAStatus status = mPlugin->verify(toStdVec(sessionId), toStdVec(keyId),
toStdVec(message), toStdVec(signature), &match);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
- Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
- Vector<uint8_t>& signature) {
+DrmStatus DrmHalAidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1074,10 +1077,10 @@
signature = toVector(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::requiresSecureDecoder(const char* mime, bool* required) const {
+DrmStatus DrmHalAidl::requiresSecureDecoder(const char* mime, bool* required) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1086,14 +1089,15 @@
mPlugin->requiresSecureDecoder(mimeAidl, SecurityLevel::DEFAULT, required);
if (!status.isOk()) {
DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %d", status.getServiceSpecificError());
- return DEAD_OBJECT;
+ return DrmStatus(DEAD_OBJECT);
}
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalAidl::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
- bool* required) const {
+DrmStatus DrmHalAidl::requiresSecureDecoder(const char* mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1101,7 +1105,7 @@
std::string mimeAidl(mime);
::ndk::ScopedAStatus status = mPlugin->requiresSecureDecoder(mimeAidl, aLevel, required);
- status_t err = statusAidlToStatusT(status);
+ DrmStatus err = statusAidlToDrmStatus(status);
if (!status.isOk()) {
DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %d", status.getServiceSpecificError());
}
@@ -1109,17 +1113,17 @@
return err;
}
-status_t DrmHalAidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+DrmStatus DrmHalAidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
std::string playbackIdAidl(playbackId);
::ndk::ScopedAStatus status = mPlugin->setPlaybackId(toStdVec(sessionId), playbackIdAidl);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+DrmStatus DrmHalAidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
Mutex::Autolock autoLock(mLock);
- return DrmUtils::GetLogMessagesAidl<IDrmPluginAidl>(mPlugin, logs);
+ return DrmStatus(DrmUtils::GetLogMessagesAidl<IDrmPluginAidl>(mPlugin, logs));
}
void DrmHalAidl::closeOpenSessions() {
@@ -1143,7 +1147,7 @@
getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
metricsString = toBase64StringNoPad(metricsVector.array(), metricsVector.size());
status_t res = android::reportDrmPluginMetrics(metricsString, vendor, description,
- mMetrics.GetAppUid());
+ mMetrics->GetAppUid());
if (res != OK) {
ALOGE("Metrics were retrieved but could not be reported: %d", res);
}
@@ -1153,7 +1157,7 @@
std::string DrmHalAidl::reportFrameworkMetrics(const std::string& pluginMetrics) const {
mediametrics_handle_t item(mediametrics_create("mediadrm"));
- mediametrics_setUid(item, mMetrics.GetAppUid());
+ mediametrics_setUid(item, mMetrics->GetAppUid());
String8 vendor;
String8 description;
status_t result = getPropertyStringInternal(String8("vendor"), vendor);
@@ -1170,7 +1174,7 @@
}
std::string serializedMetrics;
- result = mMetrics.GetSerializedMetrics(&serializedMetrics);
+ result = mMetrics->GetSerializedMetrics(&serializedMetrics);
if (result != OK) {
ALOGE("Failed to serialize framework metrics: %d", result);
}
@@ -1189,7 +1193,7 @@
return serializedMetrics;
}
-status_t DrmHalAidl::getSupportedSchemes(std::vector<uint8_t> &schemes) const {
+DrmStatus DrmHalAidl::getSupportedSchemes(std::vector<uint8_t>& schemes) const {
Mutex::Autolock autoLock(mLock);
if (mFactories.empty()) return UNKNOWN_ERROR;
@@ -1205,14 +1209,14 @@
}
}
- return OK;
+ return DrmStatus(OK);
}
void DrmHalAidl::cleanup() {
closeOpenSessions();
Mutex::Autolock autoLock(mLock);
- reportFrameworkMetrics(reportPluginMetrics());
+ if (mInitCheck == OK) reportFrameworkMetrics(reportPluginMetrics());
setListener(NULL);
mInitCheck = NO_INIT;
@@ -1225,9 +1229,9 @@
mPlugin.reset();
}
-status_t DrmHalAidl::destroyPlugin() {
+DrmStatus DrmHalAidl::destroyPlugin() {
cleanup();
- return OK;
+ return DrmStatus(OK);
}
::ndk::ScopedAStatus DrmHalAidl::onEvent(EventTypeAidl eventTypeAidl,
diff --git a/drm/libmediadrm/DrmHalHidl.cpp b/drm/libmediadrm/DrmHalHidl.cpp
index ea99483..6106aa7 100644
--- a/drm/libmediadrm/DrmHalHidl.cpp
+++ b/drm/libmediadrm/DrmHalHidl.cpp
@@ -35,6 +35,7 @@
#include <mediadrm/DrmHalHidl.h>
#include <mediadrm/DrmSessionClientInterface.h>
#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/DrmStatus.h>
#include <mediadrm/DrmUtils.h>
#include <mediadrm/IDrmMetricsConsumer.h>
#include <utils/Log.h>
@@ -368,14 +369,14 @@
return plugin;
}
-status_t DrmHalHidl::initCheck() const {
- return mInitCheck;
+DrmStatus DrmHalHidl::initCheck() const {
+ return DrmStatus(mInitCheck);
}
-status_t DrmHalHidl::setListener(const sp<IDrmClient>& listener) {
+DrmStatus DrmHalHidl::setListener(const sp<IDrmClient>& listener) {
Mutex::Autolock lock(mEventLock);
mListener = listener;
- return NO_ERROR;
+ return DrmStatus(NO_ERROR);
}
Return<void> DrmHalHidl::sendEvent(EventType hEventType, const hidl_vec<uint8_t>& sessionId,
@@ -502,10 +503,10 @@
return Void();
}
-status_t DrmHalHidl::matchMimeTypeAndSecurityLevel(const sp<IDrmFactory>& factory,
- const uint8_t uuid[16], const String8& mimeType,
- DrmPlugin::SecurityLevel level,
- bool* isSupported) {
+DrmStatus DrmHalHidl::matchMimeTypeAndSecurityLevel(const sp<IDrmFactory>& factory,
+ const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level,
+ bool* isSupported) {
*isSupported = false;
// handle default value cases
@@ -513,35 +514,35 @@
if (mimeType == "") {
// isCryptoSchemeSupported(uuid)
*isSupported = true;
- return OK;
+ return DrmStatus(OK);
}
// isCryptoSchemeSupported(uuid, mimeType)
auto hResult = factory->isContentTypeSupported(mimeType.string());
if (!hResult.isOk()) {
- return DEAD_OBJECT;
+ return DrmStatus(DEAD_OBJECT);
}
*isSupported = hResult;
- return OK;
+ return DrmStatus(OK);
} else if (mimeType == "") {
- return BAD_VALUE;
+ return DrmStatus(BAD_VALUE);
}
sp<drm::V1_2::IDrmFactory> factoryV1_2 = drm::V1_2::IDrmFactory::castFrom(factory);
if (factoryV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
+ return DrmStatus(ERROR_UNSUPPORTED);
} else {
auto hResult = factoryV1_2->isCryptoSchemeSupported_1_2(uuid, mimeType.string(),
toHidlSecurityLevel(level));
if (!hResult.isOk()) {
- return DEAD_OBJECT;
+ return DrmStatus(DEAD_OBJECT);
}
*isSupported = hResult;
- return OK;
+ return DrmStatus(OK);
}
}
-status_t DrmHalHidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
- DrmPlugin::SecurityLevel level, bool* isSupported) {
+DrmStatus DrmHalHidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level, bool* isSupported) {
Mutex::Autolock autoLock(mLock);
*isSupported = false;
for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
@@ -550,12 +551,13 @@
return matchMimeTypeAndSecurityLevel(mFactories[i], uuid, mimeType, level, isSupported);
}
}
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalHidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+DrmStatus DrmHalHidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
Mutex::Autolock autoLock(mLock);
+ if (mInitCheck == ERROR_UNSUPPORTED) return mInitCheck;
for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
auto hResult = mFactories[i]->isCryptoSchemeSupported(uuid);
if (hResult.isOk() && hResult) {
@@ -590,15 +592,15 @@
}
}
- return mInitCheck;
+ return DrmStatus(mInitCheck);
}
-status_t DrmHalHidl::destroyPlugin() {
+DrmStatus DrmHalHidl::destroyPlugin() {
cleanup();
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalHidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
+DrmStatus DrmHalHidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -613,7 +615,7 @@
}
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
bool retry = true;
do {
hidl_vec<uint8_t> hSessionId;
@@ -666,7 +668,7 @@
return err;
}
-status_t DrmHalHidl::closeSession(Vector<uint8_t> const& sessionId) {
+DrmStatus DrmHalHidl::closeSession(Vector<uint8_t> const& sessionId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -681,13 +683,13 @@
}
}
}
- status_t response = toStatusT(status);
+ DrmStatus response = toStatusT(status);
mMetrics.SetSessionEnd(sessionId);
mMetrics.mCloseSessionCounter.Increment(response);
return response;
}
mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
- return DEAD_OBJECT;
+ return DrmStatus(DEAD_OBJECT);
}
static DrmPlugin::KeyRequestType toKeyRequestType(KeyRequestType keyRequestType) {
@@ -721,12 +723,12 @@
}
}
-status_t DrmHalHidl::getKeyRequest(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& initData, String8 const& mimeType,
- DrmPlugin::KeyType keyType,
- KeyedVector<String8, String8> const& optionalParameters,
- Vector<uint8_t>& request, String8& defaultUrl,
- DrmPlugin::KeyRequestType* keyRequestType) {
+DrmStatus DrmHalHidl::getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
@@ -747,7 +749,7 @@
::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult;
if (mPluginV1_2 != NULL) {
@@ -796,16 +798,16 @@
return err;
}
-status_t DrmHalHidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& response,
- Vector<uint8_t>& keySetId) {
+DrmStatus DrmHalHidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response,
+ Vector<uint8_t>& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult =
mPlugin->provideKeyResponse(toHidlVec(sessionId), toHidlVec(response),
@@ -820,27 +822,27 @@
return err;
}
-status_t DrmHalHidl::removeKeys(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalHidl::removeKeys(Vector<uint8_t> const& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
Return<Status> status = mPlugin->removeKeys(toHidlVec(keySetId));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::restoreKeys(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalHidl::restoreKeys(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
Return<Status> status = mPlugin->restoreKeys(toHidlVec(sessionId), toHidlVec(keySetId));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
- KeyedVector<String8, String8>& infoMap) const {
+DrmStatus DrmHalHidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -848,7 +850,7 @@
::KeyedVector hInfoMap;
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->queryKeyStatus(
toHidlVec(sessionId), [&](Status status, const hidl_vec<KeyValue>& map) {
@@ -858,15 +860,15 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? DrmStatus(err) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
- Vector<uint8_t>& request, String8& defaultUrl) {
+DrmStatus DrmHalHidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult;
if (mPluginV1_2 != NULL) {
@@ -897,13 +899,13 @@
return err;
}
-status_t DrmHalHidl::provideProvisionResponse(Vector<uint8_t> const& response,
- Vector<uint8_t>& certificate,
- Vector<uint8_t>& wrappedKey) {
+DrmStatus DrmHalHidl::provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->provideProvisionResponse(
toHidlVec(response), [&](Status status, const hidl_vec<uint8_t>& hCertificate,
@@ -920,11 +922,11 @@
return err;
}
-status_t DrmHalHidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+DrmStatus DrmHalHidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult =
mPlugin->getSecureStops([&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
@@ -934,10 +936,10 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+DrmStatus DrmHalHidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
@@ -948,7 +950,7 @@
return ERROR_DRM_CANNOT_HANDLE;
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPluginV1_1->getSecureStopIds(
[&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
@@ -958,14 +960,14 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+DrmStatus DrmHalHidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->getSecureStop(
toHidlVec(ssid), [&](Status status, const SecureStop& hSecureStop) {
@@ -975,10 +977,10 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+DrmStatus DrmHalHidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -990,10 +992,10 @@
} else {
status = mPlugin->releaseSecureStop(toHidlVec(ssRelease));
}
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::removeSecureStop(Vector<uint8_t> const& ssid) {
+DrmStatus DrmHalHidl::removeSecureStop(Vector<uint8_t> const& ssid) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
@@ -1005,10 +1007,10 @@
}
Return<Status> status = mPluginV1_1->removeSecureStop(toHidlVec(ssid));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::removeAllSecureStops() {
+DrmStatus DrmHalHidl::removeAllSecureStops() {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1018,18 +1020,18 @@
} else {
status = mPlugin->releaseAllSecureStops();
}
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
- DrmPlugin::HdcpLevel* max) const {
+DrmStatus DrmHalHidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
+ DrmPlugin::HdcpLevel* max) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
if (connected == NULL || max == NULL) {
return BAD_VALUE;
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
*connected = DrmPlugin::kHdcpLevelUnknown;
*max = DrmPlugin::kHdcpLevelUnknown;
@@ -1055,26 +1057,26 @@
err = toStatusT(status);
});
} else {
- return ERROR_DRM_CANNOT_HANDLE;
+ return DrmStatus(ERROR_DRM_CANNOT_HANDLE);
}
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
+DrmStatus DrmHalHidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
if (open == NULL || max == NULL) {
return BAD_VALUE;
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
*open = 0;
*max = 0;
if (mPluginV1_1 == NULL) {
- return ERROR_DRM_CANNOT_HANDLE;
+ return DrmStatus(ERROR_DRM_CANNOT_HANDLE);
}
Return<void> hResult =
@@ -1086,21 +1088,21 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
- DrmPlugin::SecurityLevel* level) const {
+DrmStatus DrmHalHidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
if (level == NULL) {
- return BAD_VALUE;
+ return DrmStatus(BAD_VALUE);
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
if (mPluginV1_1 == NULL) {
- return ERROR_DRM_CANNOT_HANDLE;
+ return DrmStatus(ERROR_DRM_CANNOT_HANDLE);
}
*level = DrmPlugin::kSecurityLevelUnknown;
@@ -1113,21 +1115,21 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+DrmStatus DrmHalHidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
- return mInitCheck;
+ return DrmStatus(mInitCheck);
}
if (mPluginV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
+ return DrmStatus(ERROR_UNSUPPORTED);
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPluginV1_2->getOfflineLicenseKeySetIds(
[&](Status status, const hidl_vec<KeySetId>& hKeySetIds) {
@@ -1137,38 +1139,38 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalHidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
- return mInitCheck;
+ return DrmStatus(mInitCheck);
}
if (mPluginV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
+ return DrmStatus(ERROR_UNSUPPORTED);
}
Return<Status> status = mPluginV1_2->removeOfflineLicense(toHidlVec(keySetId));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
- DrmPlugin::OfflineLicenseState* licenseState) const {
+DrmStatus DrmHalHidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
- return mInitCheck;
+ return DrmStatus(mInitCheck);
}
if (mPluginV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
+ return DrmStatus(ERROR_UNSUPPORTED);
}
*licenseState = DrmPlugin::kOfflineLicenseStateUnknown;
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPluginV1_2->getOfflineLicenseState(
toHidlVec(keySetId), [&](Status status, OfflineLicenseState hLicenseState) {
@@ -1178,20 +1180,20 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getPropertyString(String8 const& name, String8& value) const {
+DrmStatus DrmHalHidl::getPropertyString(String8 const& name, String8& value) const {
Mutex::Autolock autoLock(mLock);
return getPropertyStringInternal(name, value);
}
-status_t DrmHalHidl::getPropertyStringInternal(String8 const& name, String8& value) const {
+DrmStatus DrmHalHidl::getPropertyStringInternal(String8 const& name, String8& value) const {
// This function is internal to the class and should only be called while
// mLock is already held.
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->getPropertyString(
toHidlString(name), [&](Status status, const hidl_string& hValue) {
@@ -1201,21 +1203,21 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+DrmStatus DrmHalHidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
Mutex::Autolock autoLock(mLock);
return getPropertyByteArrayInternal(name, value);
}
-status_t DrmHalHidl::getPropertyByteArrayInternal(String8 const& name,
- Vector<uint8_t>& value) const {
+DrmStatus DrmHalHidl::getPropertyByteArrayInternal(String8 const& name,
+ Vector<uint8_t>& value) const {
// This function is internal to the class and should only be called while
// mLock is already held.
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->getPropertyByteArray(
toHidlString(name), [&](Status status, const hidl_vec<uint8_t>& hValue) {
@@ -1232,25 +1234,26 @@
return err;
}
-status_t DrmHalHidl::setPropertyString(String8 const& name, String8 const& value) const {
+DrmStatus DrmHalHidl::setPropertyString(String8 const& name, String8 const& value) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
Return<Status> status = mPlugin->setPropertyString(toHidlString(name), toHidlString(value));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+DrmStatus DrmHalHidl::setPropertyByteArray(String8 const& name,
+ Vector<uint8_t> const& value) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
Return<Status> status = mPlugin->setPropertyByteArray(toHidlString(name), toHidlVec(value));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+DrmStatus DrmHalHidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
if (consumer == nullptr) {
- return UNEXPECTED_NULL;
+ return DrmStatus(UNEXPECTED_NULL);
}
consumer->consumeFrameworkMetrics(mMetrics);
@@ -1271,7 +1274,7 @@
vendor += description;
hidl_vec<DrmMetricGroup> pluginMetrics;
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> status =
mPluginV1_1->getMetrics([&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
@@ -1282,14 +1285,14 @@
}
err = toStatusT(status);
});
- return status.isOk() ? err : DEAD_OBJECT;
+ return status.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalHidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
- String8 const& algorithm) {
+DrmStatus DrmHalHidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+ String8 const& algorithm) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1297,28 +1300,28 @@
Return<Status> status =
mPlugin->setCipherAlgorithm(toHidlVec(sessionId), toHidlString(algorithm));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+DrmStatus DrmHalHidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
Return<Status> status = mPlugin->setMacAlgorithm(toHidlVec(sessionId), toHidlString(algorithm));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output) {
+DrmStatus DrmHalHidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult =
mPlugin->encrypt(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(input),
@@ -1329,18 +1332,18 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output) {
+DrmStatus DrmHalHidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult =
mPlugin->decrypt(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(input),
@@ -1351,17 +1354,17 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+DrmStatus DrmHalHidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->sign(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(message),
[&](Status status, const hidl_vec<uint8_t>& hSignature) {
@@ -1371,18 +1374,18 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
- bool& match) {
+DrmStatus DrmHalHidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult =
mPlugin->verify(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(message),
@@ -1395,18 +1398,18 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
- Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
- Vector<uint8_t>& signature) {
+DrmStatus DrmHalHidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->signRSA(
toHidlVec(sessionId), toHidlString(algorithm), toHidlVec(message),
@@ -1417,7 +1420,7 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
std::string DrmHalHidl::reportFrameworkMetrics(const std::string& pluginMetrics) const {
@@ -1476,55 +1479,56 @@
return metricsString;
}
-status_t DrmHalHidl::requiresSecureDecoder(const char* mime, bool* required) const {
+DrmStatus DrmHalHidl::requiresSecureDecoder(const char* mime, bool* required) const {
Mutex::Autolock autoLock(mLock);
if (mPluginV1_4 == NULL) {
- return false;
+ return DrmStatus(false);
}
auto hResult = mPluginV1_4->requiresSecureDecoderDefault(hidl_string(mime));
if (!hResult.isOk()) {
DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
- return DEAD_OBJECT;
+ return DrmStatus(DEAD_OBJECT);
}
if (required) {
*required = hResult;
}
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalHidl::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
- bool* required) const {
+DrmStatus DrmHalHidl::requiresSecureDecoder(const char* mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const {
Mutex::Autolock autoLock(mLock);
if (mPluginV1_4 == NULL) {
- return false;
+ return DrmStatus(false);
}
auto hLevel = toHidlSecurityLevel(securityLevel);
auto hResult = mPluginV1_4->requiresSecureDecoder(hidl_string(mime), hLevel);
if (!hResult.isOk()) {
DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
- return DEAD_OBJECT;
+ return DrmStatus(DEAD_OBJECT);
}
if (required) {
*required = hResult;
}
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalHidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+DrmStatus DrmHalHidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
Mutex::Autolock autoLock(mLock);
if (mPluginV1_4 == NULL) {
- return ERROR_UNSUPPORTED;
+ return DrmStatus(ERROR_UNSUPPORTED);
}
auto err = mPluginV1_4->setPlaybackId(toHidlVec(sessionId), hidl_string(playbackId));
- return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
+ return err.isOk() ? DrmStatus(toStatusT(err)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+DrmStatus DrmHalHidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
Mutex::Autolock autoLock(mLock);
- return DrmUtils::GetLogMessages<drm::V1_4::IDrmPlugin>(mPlugin, logs);
+ return DrmStatus(DrmUtils::GetLogMessages<drm::V1_4::IDrmPlugin>(mPlugin, logs));
}
-status_t DrmHalHidl::getSupportedSchemes(std::vector<uint8_t> &schemes) const {
+DrmStatus DrmHalHidl::getSupportedSchemes(std::vector<uint8_t>& schemes) const {
Mutex::Autolock autoLock(mLock);
for (auto &factory : mFactories) {
sp<drm::V1_3::IDrmFactory> factoryV1_3 = drm::V1_3::IDrmFactory::castFrom(factory);
@@ -1540,7 +1544,7 @@
});
}
- return OK;
+ return DrmStatus(OK);
}
} // namespace android
diff --git a/drm/libmediadrm/DrmHalListener.cpp b/drm/libmediadrm/DrmHalListener.cpp
index cfcf475..4e868ac 100644
--- a/drm/libmediadrm/DrmHalListener.cpp
+++ b/drm/libmediadrm/DrmHalListener.cpp
@@ -37,12 +37,12 @@
return vec;
}
-DrmHalListener::DrmHalListener(MediaDrmMetrics* metrics)
+DrmHalListener::DrmHalListener(const std::shared_ptr<MediaDrmMetrics>& metrics)
: mMetrics(metrics) {}
DrmHalListener::~DrmHalListener() {}
-void DrmHalListener::setListener(sp<IDrmClient> listener) {
+void DrmHalListener::setListener(const sp<IDrmClient>& listener) {
Mutex::Autolock lock(mEventLock);
mListener = listener;
}
diff --git a/drm/libmediadrm/DrmMetricsLogger.cpp b/drm/libmediadrm/DrmMetricsLogger.cpp
new file mode 100644
index 0000000..bc004c8
--- /dev/null
+++ b/drm/libmediadrm/DrmMetricsLogger.cpp
@@ -0,0 +1,641 @@
+/*
+ * Copyright (C) 2022 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 "DrmMetricsLogger"
+
+#include <media/MediaMetrics.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/base64.h>
+#include <mediadrm/DrmHal.h>
+#include <mediadrm/DrmMetricsLogger.h>
+#include <mediadrm/DrmUtils.h>
+
+namespace android {
+
+namespace {
+
+std::vector<uint8_t> toStdVec(Vector<uint8_t> const& sessionId) {
+ auto sessionKey = sessionId.array();
+ std::vector<uint8_t> vec(sessionKey, sessionKey + sessionId.size());
+ return vec;
+}
+
+} // namespace
+
+DrmMetricsLogger::DrmMetricsLogger(IDrmFrontend frontend)
+ : mImpl(sp<DrmHal>::make()), mUuid(), mObjNonce(), mFrontend(frontend) {}
+
+DrmMetricsLogger::~DrmMetricsLogger() {}
+
+int MediaErrorToJavaError(status_t err) {
+#define STATUS_CASE(status) \
+ case status: \
+ return J##status
+
+ switch (err) {
+ STATUS_CASE(ERROR_DRM_UNKNOWN);
+ STATUS_CASE(ERROR_DRM_NO_LICENSE);
+ STATUS_CASE(ERROR_DRM_LICENSE_EXPIRED);
+ STATUS_CASE(ERROR_DRM_RESOURCE_BUSY);
+ STATUS_CASE(ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION);
+ STATUS_CASE(ERROR_DRM_SESSION_NOT_OPENED);
+ STATUS_CASE(ERROR_DRM_CANNOT_HANDLE);
+ STATUS_CASE(ERROR_DRM_INSUFFICIENT_SECURITY);
+ STATUS_CASE(ERROR_DRM_FRAME_TOO_LARGE);
+ STATUS_CASE(ERROR_DRM_SESSION_LOST_STATE);
+ STATUS_CASE(ERROR_DRM_CERTIFICATE_MALFORMED);
+ STATUS_CASE(ERROR_DRM_CERTIFICATE_MISSING);
+ STATUS_CASE(ERROR_DRM_CRYPTO_LIBRARY);
+ STATUS_CASE(ERROR_DRM_GENERIC_OEM);
+ STATUS_CASE(ERROR_DRM_GENERIC_PLUGIN);
+ STATUS_CASE(ERROR_DRM_INIT_DATA);
+ STATUS_CASE(ERROR_DRM_KEY_NOT_LOADED);
+ STATUS_CASE(ERROR_DRM_LICENSE_PARSE);
+ STATUS_CASE(ERROR_DRM_LICENSE_POLICY);
+ STATUS_CASE(ERROR_DRM_LICENSE_RELEASE);
+ STATUS_CASE(ERROR_DRM_LICENSE_REQUEST_REJECTED);
+ STATUS_CASE(ERROR_DRM_LICENSE_RESTORE);
+ STATUS_CASE(ERROR_DRM_LICENSE_STATE);
+ STATUS_CASE(ERROR_DRM_MEDIA_FRAMEWORK);
+ STATUS_CASE(ERROR_DRM_PROVISIONING_CERTIFICATE);
+ STATUS_CASE(ERROR_DRM_PROVISIONING_CONFIG);
+ STATUS_CASE(ERROR_DRM_PROVISIONING_PARSE);
+ STATUS_CASE(ERROR_DRM_PROVISIONING_REQUEST_REJECTED);
+ STATUS_CASE(ERROR_DRM_PROVISIONING_RETRY);
+ STATUS_CASE(ERROR_DRM_RESOURCE_CONTENTION);
+ STATUS_CASE(ERROR_DRM_SECURE_STOP_RELEASE);
+ STATUS_CASE(ERROR_DRM_STORAGE_READ);
+ STATUS_CASE(ERROR_DRM_STORAGE_WRITE);
+ STATUS_CASE(ERROR_DRM_ZERO_SUBSAMPLES);
+#undef STATUS_CASE
+ }
+ return static_cast<int>(err);
+}
+
+int DrmPluginSecurityLevelToJavaSecurityLevel(DrmPlugin::SecurityLevel securityLevel) {
+#define STATUS_CASE(status) \
+ case DrmPlugin::k##status: \
+ return J##status
+
+ switch (securityLevel) {
+ STATUS_CASE(SecurityLevelUnknown);
+ STATUS_CASE(SecurityLevelSwSecureCrypto);
+ STATUS_CASE(SecurityLevelSwSecureDecode);
+ STATUS_CASE(SecurityLevelHwSecureCrypto);
+ STATUS_CASE(SecurityLevelHwSecureDecode);
+ STATUS_CASE(SecurityLevelHwSecureAll);
+ STATUS_CASE(SecurityLevelMax);
+#undef STATUS_CASE
+ }
+ return static_cast<int>(securityLevel);
+}
+
+
+DrmStatus DrmMetricsLogger::initCheck() const {
+ DrmStatus status = mImpl->initCheck();
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::isCryptoSchemeSupported(const uint8_t uuid[IDRM_UUID_SIZE],
+ const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool* result) {
+ DrmStatus status = mImpl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::createPlugin(const uint8_t uuid[IDRM_UUID_SIZE],
+ const String8& appPackageName) {
+ std::memcpy(mUuid.data(), uuid, IDRM_UUID_SIZE);
+ mUuid[0] = betoh64(mUuid[0]);
+ mUuid[1] = betoh64(mUuid[1]);
+ if (kUuidSchemeMap.count(mUuid)) {
+ mScheme = kUuidSchemeMap.at(mUuid);
+ } else {
+ mScheme = "Other";
+ }
+ if (generateNonce(&mObjNonce, kNonceSize, __func__) != OK) {
+ return ERROR_DRM_RESOURCE_BUSY;
+ }
+ DrmStatus status = mImpl->createPlugin(uuid, appPackageName);
+ if (status == OK) {
+ String8 version8;
+ if (getPropertyString(String8("version"), version8) == OK) {
+ mVersion = version8.string();
+ }
+ reportMediaDrmCreated();
+ } else {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::destroyPlugin() {
+ DrmStatus status = mImpl->destroyPlugin();
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::openSession(DrmPlugin::SecurityLevel securityLevel,
+ Vector<uint8_t>& sessionId) {
+ SessionContext ctx{};
+ if (generateNonce(&ctx.mNonce, kNonceSize, __func__) != OK) {
+ return ERROR_DRM_RESOURCE_BUSY;
+ }
+ DrmStatus status = mImpl->openSession(securityLevel, sessionId);
+ if (status == OK) {
+ std::vector<uint8_t> sessionKey = toStdVec(sessionId);
+ ctx.mTargetSecurityLevel = securityLevel;
+ if (getSecurityLevel(sessionId, &ctx.mActualSecurityLevel) != OK) {
+ ctx.mActualSecurityLevel = DrmPlugin::kSecurityLevelUnknown;
+ }
+ if (!mVersion.empty()) {
+ ctx.mVersion = mVersion;
+ }
+ {
+ const std::lock_guard<std::mutex> lock(mSessionMapMutex);
+ mSessionMap.insert({sessionKey, ctx});
+ }
+ reportMediaDrmSessionOpened(sessionKey);
+ } else {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::closeSession(Vector<uint8_t> const& sessionId) {
+ std::vector<uint8_t> sid = toStdVec(sessionId);
+ {
+ const std::lock_guard<std::mutex> lock(mSessionMapMutex);
+ mSessionMap.erase(sid);
+ }
+ DrmStatus status = mImpl->closeSession(sessionId);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, sid);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType) {
+ DrmStatus status =
+ mImpl->getKeyRequest(sessionId, initData, mimeType, keyType, optionalParameters,
+ request, defaultUrl, keyRequestType);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response,
+ Vector<uint8_t>& keySetId) {
+ DrmStatus status = mImpl->provideKeyResponse(sessionId, response, keySetId);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::removeKeys(Vector<uint8_t> const& keySetId) {
+ DrmStatus status = mImpl->removeKeys(keySetId);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::restoreKeys(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& keySetId) {
+ DrmStatus status = mImpl->restoreKeys(sessionId, keySetId);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
+ DrmStatus status = mImpl->queryKeyStatus(sessionId, infoMap);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getProvisionRequest(String8 const& certType,
+ String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl) {
+ DrmStatus status = mImpl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey) {
+ DrmStatus status = mImpl->provideProvisionResponse(response, certificate, wrappedKey);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+ DrmStatus status = mImpl->getSecureStops(secureStops);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+ DrmStatus status = mImpl->getSecureStopIds(secureStopIds);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getSecureStop(Vector<uint8_t> const& ssid,
+ Vector<uint8_t>& secureStop) {
+ DrmStatus status = mImpl->getSecureStop(ssid, secureStop);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+ DrmStatus status = mImpl->releaseSecureStops(ssRelease);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::removeSecureStop(Vector<uint8_t> const& ssid) {
+ DrmStatus status = mImpl->removeSecureStop(ssid);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::removeAllSecureStops() {
+ DrmStatus status = mImpl->removeAllSecureStops();
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+ DrmPlugin::HdcpLevel* maxLevel) const {
+ DrmStatus status = mImpl->getHdcpLevels(connectedLevel, maxLevel);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getNumberOfSessions(uint32_t* currentSessions,
+ uint32_t* maxSessions) const {
+ DrmStatus status = mImpl->getNumberOfSessions(currentSessions, maxSessions);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const {
+ DrmStatus status = mImpl->getSecurityLevel(sessionId, level);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+ DrmStatus status = mImpl->getOfflineLicenseKeySetIds(keySetIds);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+ DrmStatus status = mImpl->removeOfflineLicense(keySetId);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getOfflineLicenseState(
+ Vector<uint8_t> const& keySetId, DrmPlugin::OfflineLicenseState* licenseState) const {
+ DrmStatus status = mImpl->getOfflineLicenseState(keySetId, licenseState);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getPropertyString(String8 const& name, String8& value) const {
+ DrmStatus status = mImpl->getPropertyString(name, value);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getPropertyByteArray(String8 const& name,
+ Vector<uint8_t>& value) const {
+ DrmStatus status = mImpl->getPropertyByteArray(name, value);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::setPropertyString(String8 const& name, String8 const& value) const {
+ DrmStatus status = mImpl->setPropertyString(name, value);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::setPropertyByteArray(String8 const& name,
+ Vector<uint8_t> const& value) const {
+ DrmStatus status = mImpl->setPropertyByteArray(name, value);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+ DrmStatus status = mImpl->getMetrics(consumer);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+ String8 const& algorithm) {
+ DrmStatus status = mImpl->setCipherAlgorithm(sessionId, algorithm);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::setMacAlgorithm(Vector<uint8_t> const& sessionId,
+ String8 const& algorithm) {
+ DrmStatus status = mImpl->setMacAlgorithm(sessionId, algorithm);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ DrmStatus status = mImpl->encrypt(sessionId, keyId, input, iv, output);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ DrmStatus status = mImpl->decrypt(sessionId, keyId, input, iv, output);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+ DrmStatus status = mImpl->sign(sessionId, keyId, message, signature);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match) {
+ DrmStatus status = mImpl->verify(sessionId, keyId, message, signature, match);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message,
+ Vector<uint8_t> const& wrappedKey, Vector<uint8_t>& signature) {
+ DrmStatus status = mImpl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::setListener(const sp<IDrmClient>& listener) {
+ DrmStatus status = mImpl->setListener(listener);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::requiresSecureDecoder(const char* mime, bool* required) const {
+ DrmStatus status = mImpl->requiresSecureDecoder(mime, required);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::requiresSecureDecoder(const char* mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const {
+ DrmStatus status = mImpl->requiresSecureDecoder(mime, securityLevel, required);
+ if (status != OK) {
+ reportMediaDrmErrored(status, "requiresSecureDecoderLevel");
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::setPlaybackId(Vector<uint8_t> const& sessionId,
+ const char* playbackId) {
+ DrmStatus status = mImpl->setPlaybackId(sessionId, playbackId);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+ DrmStatus status = mImpl->getLogMessages(logs);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+DrmStatus DrmMetricsLogger::getSupportedSchemes(std::vector<uint8_t>& schemes) const {
+ DrmStatus status = mImpl->getSupportedSchemes(schemes);
+ if (status != OK) {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
+}
+
+void DrmMetricsLogger::reportMediaDrmCreated() const {
+ mediametrics_handle_t handle(mediametrics_create("mediadrm.created"));
+ mediametrics_setCString(handle, "scheme", mScheme.c_str());
+ mediametrics_setInt64(handle, "uuid_msb", mUuid[0]);
+ mediametrics_setInt64(handle, "uuid_lsb", mUuid[1]);
+ mediametrics_setInt32(handle, "frontend", mFrontend);
+ mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
+ mediametrics_setCString(handle, "version", mVersion.c_str());
+ mediametrics_selfRecord(handle);
+ mediametrics_delete(handle);
+}
+
+void DrmMetricsLogger::reportMediaDrmSessionOpened(const std::vector<uint8_t>& sessionId) const {
+ mediametrics_handle_t handle(mediametrics_create("mediadrm.session_opened"));
+ mediametrics_setCString(handle, "scheme", mScheme.c_str());
+ mediametrics_setInt64(handle, "uuid_msb", mUuid[0]);
+ mediametrics_setInt64(handle, "uuid_lsb", mUuid[1]);
+ mediametrics_setInt32(handle, "frontend", mFrontend);
+ mediametrics_setCString(handle, "version", mVersion.c_str());
+ mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
+ const std::lock_guard<std::mutex> lock(mSessionMapMutex);
+ auto it = mSessionMap.find(sessionId);
+ if (it != mSessionMap.end()) {
+ mediametrics_setCString(handle, "session_nonce", it->second.mNonce.c_str());
+ mediametrics_setInt32(handle, "requested_security_level",
+ DrmPluginSecurityLevelToJavaSecurityLevel(it->second.mTargetSecurityLevel));
+ mediametrics_setInt32(handle, "opened_security_level",
+ DrmPluginSecurityLevelToJavaSecurityLevel(it->second.mActualSecurityLevel));
+ }
+ mediametrics_selfRecord(handle);
+ mediametrics_delete(handle);
+}
+
+void DrmMetricsLogger::reportMediaDrmErrored(const DrmStatus& error_code, const char* api,
+ const std::vector<uint8_t>& sessionId) const {
+ mediametrics_handle_t handle(mediametrics_create("mediadrm.errored"));
+ mediametrics_setCString(handle, "scheme", mScheme.c_str());
+ mediametrics_setInt64(handle, "uuid_msb", mUuid[0]);
+ mediametrics_setInt64(handle, "uuid_lsb", mUuid[1]);
+ mediametrics_setInt32(handle, "frontend", mFrontend);
+ mediametrics_setCString(handle, "version", mVersion.c_str());
+ mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
+ if (!sessionId.empty()) {
+ const std::lock_guard<std::mutex> lock(mSessionMapMutex);
+ auto it = mSessionMap.find(sessionId);
+ if (it != mSessionMap.end()) {
+ mediametrics_setCString(handle, "session_nonce", it->second.mNonce.c_str());
+ mediametrics_setInt32(handle, "security_level",
+ DrmPluginSecurityLevelToJavaSecurityLevel(it->second.mActualSecurityLevel));
+ }
+ }
+ mediametrics_setCString(handle, "api", api);
+ mediametrics_setInt32(handle, "error_code", MediaErrorToJavaError(error_code));
+ mediametrics_setInt32(handle, "cdm_err", error_code.getCdmErr());
+ mediametrics_setInt32(handle, "oem_err", error_code.getOemErr());
+ mediametrics_setInt32(handle, "error_context", error_code.getContext());
+ mediametrics_selfRecord(handle);
+ mediametrics_delete(handle);
+}
+
+DrmStatus DrmMetricsLogger::generateNonce(std::string* out, size_t size, const char* api) {
+ std::vector<uint8_t> buf(size);
+ ssize_t bytes = getrandom(buf.data(), size, GRND_NONBLOCK);
+ if (bytes < size) {
+ ALOGE("getrandom failed: %d", errno);
+ reportMediaDrmErrored(ERROR_DRM_RESOURCE_BUSY, api);
+ return ERROR_DRM_RESOURCE_BUSY;
+ }
+ android::AString tmp;
+ encodeBase64(buf.data(), size, &tmp);
+ out->assign(tmp.c_str());
+ return OK;
+}
+
+const std::map<std::array<int64_t, 2>, std::string> DrmMetricsLogger::kUuidSchemeMap {
+ {{(int64_t)0x6DD8B3C345F44A68, (int64_t)0xBF3A64168D01A4A6}, "ABV DRM (MoDRM)"},
+ {{(int64_t)0xF239E769EFA34850, (int64_t)0x9C16A903C6932EFB},
+ "Adobe Primetime DRM version 4"},
+ {{(int64_t)0x616C746963617374, (int64_t)0x2D50726F74656374}, "Alticast"},
+ {{(int64_t)0x94CE86FB07FF4F43, (int64_t)0xADB893D2FA968CA2}, "Apple FairPlay"},
+ {{(int64_t)0x279FE473512C48FE, (int64_t)0xADE8D176FEE6B40F}, "Arris Titanium"},
+ {{(int64_t)0x3D5E6D359B9A41E8, (int64_t)0xB843DD3C6E72C42C}, "ChinaDRM"},
+ {{(int64_t)0x3EA8778F77424BF9, (int64_t)0xB18BE834B2ACBD47}, "Clear Key AES-128"},
+ {{(int64_t)0xBE58615B19C44684, (int64_t)0x88B3C8C57E99E957}, "Clear Key SAMPLE-AES"},
+ {{(int64_t)0xE2719D58A985B3C9, (int64_t)0x781AB030AF78D30E}, "Clear Key DASH-IF"},
+ {{(int64_t)0x644FE7B5260F4FAD, (int64_t)0x949A0762FFB054B4}, "CMLA (OMA DRM)"},
+ {{(int64_t)0x37C332587B994C7E, (int64_t)0xB15D19AF74482154}, "Commscope Titanium V3"},
+ {{(int64_t)0x45D481CB8FE049C0, (int64_t)0xADA9AB2D2455B2F2}, "CoreCrypt"},
+ {{(int64_t)0xDCF4E3E362F15818, (int64_t)0x7BA60A6FE33FF3DD}, "DigiCAP SmartXess"},
+ {{(int64_t)0x35BF197B530E42D7, (int64_t)0x8B651B4BF415070F}, "DivX DRM Series 5"},
+ {{(int64_t)0x80A6BE7E14484C37, (int64_t)0x9E70D5AEBE04C8D2}, "Irdeto Content Protection"},
+ {{(int64_t)0x5E629AF538DA4063, (int64_t)0x897797FFBD9902D4},
+ "Marlin Adaptive Streaming Simple Profile V1.0"},
+ {{(int64_t)0x9A04F07998404286, (int64_t)0xAB92E65BE0885F95}, "Microsoft PlayReady"},
+ {{(int64_t)0x6A99532D869F5922, (int64_t)0x9A91113AB7B1E2F3}, "MobiTV DRM"},
+ {{(int64_t)0xADB41C242DBF4A6D, (int64_t)0x958B4457C0D27B95}, "Nagra MediaAccess PRM 3.0"},
+ {{(int64_t)0x1F83E1E86EE94F0D, (int64_t)0xBA2F5EC4E3ED1A66}, "SecureMedia"},
+ {{(int64_t)0x992C46E6C4374899, (int64_t)0xB6A050FA91AD0E39}, "SecureMedia SteelKnot"},
+ {{(int64_t)0xA68129D3575B4F1A, (int64_t)0x9CBA3223846CF7C3},
+ "Synamedia/Cisco/NDS VideoGuard DRM"},
+ {{(int64_t)0xAA11967FCC014A4A, (int64_t)0x8E99C5D3DDDFEA2D}, "Unitend DRM (UDRM)"},
+ {{(int64_t)0x9A27DD82FDE24725, (int64_t)0x8CBC4234AA06EC09}, "Verimatrix VCAS"},
+ {{(int64_t)0xB4413586C58CFFB0, (int64_t)0x94A5D4896C1AF6C3}, "Viaccess-Orca DRM (VODRM)"},
+ {{(int64_t)0x793B79569F944946, (int64_t)0xA94223E7EF7E44B4}, "VisionCrypt"},
+ {{(int64_t)0x1077EFECC0B24D02, (int64_t)0xACE33C1E52E2FB4B}, "W3C Common PSSH box"},
+ {{(int64_t)0xEDEF8BA979D64ACE, (int64_t)0xA3C827DCD51D21ED}, "Widevine Content Protection"},
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/drm/libmediadrm/DrmSessionManager.cpp b/drm/libmediadrm/DrmSessionManager.cpp
index e31395d..301538f 100644
--- a/drm/libmediadrm/DrmSessionManager.cpp
+++ b/drm/libmediadrm/DrmSessionManager.cpp
@@ -34,6 +34,7 @@
namespace android {
using aidl::android::media::MediaResourceParcel;
+using aidl::android::media::ClientInfoParcel;
namespace {
void ResourceManagerServiceDied(void* cookie) {
@@ -137,7 +138,10 @@
static int64_t clientId = 0;
mSessionMap[toStdVec(sessionId)] = (SessionInfo){pid, uid, clientId};
- mService->addResource(pid, uid, clientId++, drm, toResourceVec(sessionId, INT64_MAX));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(pid),
+ .uid = static_cast<int32_t>(uid),
+ .id = clientId++};
+ mService->addResource(clientInfo, drm, toResourceVec(sessionId, INT64_MAX));
}
void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
@@ -150,7 +154,10 @@
}
auto info = it->second;
- mService->addResource(info.pid, info.uid, info.clientId, NULL, toResourceVec(sessionId, -1));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(info.pid),
+ .uid = static_cast<int32_t>(info.uid),
+ .id = info.clientId};
+ mService->addResource(clientInfo, NULL, toResourceVec(sessionId, -1));
}
void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) {
@@ -164,7 +171,10 @@
auto info = it->second;
// removeClient instead of removeSession because each client has only one session
- mService->removeClient(info.pid, info.clientId);
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(info.pid),
+ .uid = static_cast<int32_t>(info.uid),
+ .id = info.clientId};
+ mService->removeClient(clientInfo);
mSessionMap.erase(it);
}
@@ -182,9 +192,13 @@
// cannot update mSessionMap because we do not know which sessionId is reclaimed;
// we rely on IResourceManagerClient to removeSession in reclaimResource
- Vector<uint8_t> dummy;
+ Vector<uint8_t> placeHolder;
bool success;
- ScopedAStatus status = service->reclaimResource(callingPid, toResourceVec(dummy, INT64_MAX), &success);
+ uid_t uid = AIBinder_getCallingUid();
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(callingPid),
+ .uid = static_cast<int32_t>(uid)};
+ ScopedAStatus status = service->reclaimResource(
+ clientInfo, toResourceVec(placeHolder, INT64_MAX), &success);
return status.isOk() && success;
}
diff --git a/drm/libmediadrm/DrmStatus.cpp b/drm/libmediadrm/DrmStatus.cpp
new file mode 100644
index 0000000..f622160
--- /dev/null
+++ b/drm/libmediadrm/DrmStatus.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 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 <mediadrm/DrmStatus.h>
+#include <json/json.h>
+
+namespace android {
+
+DrmStatus::DrmStatus(status_t err, const char *msg) : mStatus(err) {
+ Json::Value errorDetails;
+ Json::Reader reader;
+ if (!reader.parse(msg, errorDetails)) {
+ mErrMsg = msg;
+ return;
+ }
+
+ auto val = errorDetails["cdmError"];
+ if (val.isInt()) {
+ mCdmErr = val.asInt();
+ }
+ val = errorDetails["oemError"];
+ if (val.isInt()) {
+ mOemErr = val.asInt();
+ }
+ val = errorDetails["context"];
+ if (val.isInt()) {
+ mCtx = val.asInt();
+ }
+ val = errorDetails["errorMessage"];
+ if (val.isString()) {
+ mErrMsg = val.asString();
+ } else {
+ mErrMsg = msg;
+ }
+}
+
+} // namespace android
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index be0cd4b..a99b1d1 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -32,6 +32,7 @@
#include <android/hardware/drm/1.4/IDrmFactory.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl/HidlSupport.h>
+#include <json/json.h>
#include <cutils/properties.h>
#include <utils/Errors.h>
@@ -58,11 +59,11 @@
namespace {
-template <typename Hal>
-Hal* MakeObject(status_t* pstatus) {
+template <typename Hal, typename... Ts>
+Hal* MakeObject(status_t* pstatus, Ts... args) {
status_t err = OK;
status_t& status = pstatus ? *pstatus : err;
- auto obj = new Hal();
+ auto obj = new Hal(args...);
status = obj->initCheck();
if (status != OK && status != NO_INIT) {
return NULL;
@@ -191,8 +192,8 @@
return factories;
}
-sp<IDrm> MakeDrm(status_t* pstatus) {
- return MakeObject<DrmHal>(pstatus);
+sp<IDrm> MakeDrm(IDrmFrontend frontend, status_t* pstatus) {
+ return MakeObject<DrmMetricsLogger>(pstatus, frontend);
}
sp<ICrypto> MakeCrypto(status_t* pstatus) {
@@ -362,18 +363,23 @@
}
} // namespace
-std::string GetExceptionMessage(status_t err, const char* msg,
+std::string GetExceptionMessage(const DrmStatus &err, const char* defaultMsg,
const Vector<::V1_4::LogMessage>& logs) {
std::string ruler("==============================");
std::string header("Beginning of DRM Plugin Log");
std::string footer("End of DRM Plugin Log");
+ std::string msg(err.getErrorMessage());
String8 msg8;
- if (msg) {
- msg8 += msg;
+ if (!msg.empty()) {
+ msg8 += msg.c_str();
+ msg8 += ": ";
+ } else if (defaultMsg) {
+ msg8 += defaultMsg;
msg8 += ": ";
}
- auto errStr = StrCryptoError(err);
- msg8 += errStr.c_str();
+ msg8 += StrCryptoError(err).c_str();
+ msg8 += String8::format("\ncdm err: %d, oem err: %d, ctx: %d",
+ err.getCdmErr(), err.getOemErr(), err.getContext());
msg8 += String8::format("\n%s %s %s", ruler.c_str(), header.c_str(), ruler.c_str());
for (auto log : logs) {
@@ -410,6 +416,141 @@
return logs;
}
+DrmStatus statusAidlToDrmStatus(::ndk::ScopedAStatus& statusAidl) {
+ if (statusAidl.isOk()) return OK;
+ if (statusAidl.getExceptionCode() != EX_SERVICE_SPECIFIC) return DEAD_OBJECT;
+ auto astatus = static_cast<StatusAidl>(statusAidl.getServiceSpecificError());
+ status_t status{};
+ switch (astatus) {
+ case StatusAidl::OK:
+ status = OK;
+ break;
+ case StatusAidl::BAD_VALUE:
+ status = BAD_VALUE;
+ break;
+ case StatusAidl::ERROR_DRM_CANNOT_HANDLE:
+ status = ERROR_DRM_CANNOT_HANDLE;
+ break;
+ case StatusAidl::ERROR_DRM_DECRYPT:
+ status = ERROR_DRM_DECRYPT;
+ break;
+ case StatusAidl::ERROR_DRM_DEVICE_REVOKED:
+ status = ERROR_DRM_DEVICE_REVOKED;
+ break;
+ case StatusAidl::ERROR_DRM_FRAME_TOO_LARGE:
+ status = ERROR_DRM_FRAME_TOO_LARGE;
+ break;
+ case StatusAidl::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+ status = ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+ break;
+ case StatusAidl::ERROR_DRM_INSUFFICIENT_SECURITY:
+ status = ERROR_DRM_INSUFFICIENT_SECURITY;
+ break;
+ case StatusAidl::ERROR_DRM_INVALID_STATE:
+ status = ERROR_DRM_INVALID_STATE;
+ break;
+ case StatusAidl::ERROR_DRM_LICENSE_EXPIRED:
+ status = ERROR_DRM_LICENSE_EXPIRED;
+ break;
+ case StatusAidl::ERROR_DRM_NO_LICENSE:
+ status = ERROR_DRM_NO_LICENSE;
+ break;
+ case StatusAidl::ERROR_DRM_NOT_PROVISIONED:
+ status = ERROR_DRM_NOT_PROVISIONED;
+ break;
+ case StatusAidl::ERROR_DRM_RESOURCE_BUSY:
+ status = ERROR_DRM_RESOURCE_BUSY;
+ break;
+ case StatusAidl::ERROR_DRM_RESOURCE_CONTENTION:
+ status = ERROR_DRM_RESOURCE_CONTENTION;
+ break;
+ case StatusAidl::ERROR_DRM_SESSION_LOST_STATE:
+ status = ERROR_DRM_SESSION_LOST_STATE;
+ break;
+ case StatusAidl::ERROR_DRM_SESSION_NOT_OPENED:
+ status = ERROR_DRM_SESSION_NOT_OPENED;
+ break;
+
+ // New in S / drm@1.4:
+ case StatusAidl::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
+ status = ERROR_DRM_ZERO_SUBSAMPLES;
+ break;
+ case StatusAidl::CRYPTO_LIBRARY_ERROR:
+ status = ERROR_DRM_CRYPTO_LIBRARY;
+ break;
+ case StatusAidl::GENERAL_OEM_ERROR:
+ status = ERROR_DRM_GENERIC_OEM;
+ break;
+ case StatusAidl::GENERAL_PLUGIN_ERROR:
+ status = ERROR_DRM_GENERIC_PLUGIN;
+ break;
+ case StatusAidl::INIT_DATA_INVALID:
+ status = ERROR_DRM_INIT_DATA;
+ break;
+ case StatusAidl::KEY_NOT_LOADED:
+ status = ERROR_DRM_KEY_NOT_LOADED;
+ break;
+ case StatusAidl::LICENSE_PARSE_ERROR:
+ status = ERROR_DRM_LICENSE_PARSE;
+ break;
+ case StatusAidl::LICENSE_POLICY_ERROR:
+ status = ERROR_DRM_LICENSE_POLICY;
+ break;
+ case StatusAidl::LICENSE_RELEASE_ERROR:
+ status = ERROR_DRM_LICENSE_RELEASE;
+ break;
+ case StatusAidl::LICENSE_REQUEST_REJECTED:
+ status = ERROR_DRM_LICENSE_REQUEST_REJECTED;
+ break;
+ case StatusAidl::LICENSE_RESTORE_ERROR:
+ status = ERROR_DRM_LICENSE_RESTORE;
+ break;
+ case StatusAidl::LICENSE_STATE_ERROR:
+ status = ERROR_DRM_LICENSE_STATE;
+ break;
+ case StatusAidl::MALFORMED_CERTIFICATE:
+ status = ERROR_DRM_CERTIFICATE_MALFORMED;
+ break;
+ case StatusAidl::MEDIA_FRAMEWORK_ERROR:
+ status = ERROR_DRM_MEDIA_FRAMEWORK;
+ break;
+ case StatusAidl::MISSING_CERTIFICATE:
+ status = ERROR_DRM_CERTIFICATE_MISSING;
+ break;
+ case StatusAidl::PROVISIONING_CERTIFICATE_ERROR:
+ status = ERROR_DRM_PROVISIONING_CERTIFICATE;
+ break;
+ case StatusAidl::PROVISIONING_CONFIGURATION_ERROR:
+ status = ERROR_DRM_PROVISIONING_CONFIG;
+ break;
+ case StatusAidl::PROVISIONING_PARSE_ERROR:
+ status = ERROR_DRM_PROVISIONING_PARSE;
+ break;
+ case StatusAidl::PROVISIONING_REQUEST_REJECTED:
+ status = ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
+ break;
+ case StatusAidl::RETRYABLE_PROVISIONING_ERROR:
+ status = ERROR_DRM_PROVISIONING_RETRY;
+ break;
+ case StatusAidl::SECURE_STOP_RELEASE_ERROR:
+ status = ERROR_DRM_SECURE_STOP_RELEASE;
+ break;
+ case StatusAidl::STORAGE_READ_FAILURE:
+ status = ERROR_DRM_STORAGE_READ;
+ break;
+ case StatusAidl::STORAGE_WRITE_FAILURE:
+ status = ERROR_DRM_STORAGE_WRITE;
+ break;
+
+ case StatusAidl::ERROR_DRM_UNKNOWN:
+ default:
+ status = ERROR_DRM_UNKNOWN;
+ break;
+ }
+
+ return DrmStatus(status, statusAidl.getMessage());
+}
+
LogBuffer gLogBuf;
} // namespace DrmUtils
} // namespace android
diff --git a/drm/libmediadrm/fuzzer/Android.bp b/drm/libmediadrm/fuzzer/Android.bp
index a85e3cf..deda9ef 100644
--- a/drm/libmediadrm/fuzzer/Android.bp
+++ b/drm/libmediadrm/fuzzer/Android.bp
@@ -37,6 +37,7 @@
"liblog",
"resourcemanager_aidl_interface-ndk",
"libaidlcommonsupport",
+ "libjsoncpp",
],
header_libs: [
"libmedia_headers",
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHal.h b/drm/libmediadrm/include/mediadrm/CryptoHal.h
index 32a6741..60cbbf8 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHal.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHal.h
@@ -38,7 +38,7 @@
virtual bool requiresSecureDecoderComponent(
const char *mime) const;
virtual void notifyResolution(uint32_t width, uint32_t height);
- virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
+ virtual DrmStatus setMediaDrmSession(const Vector<uint8_t> &sessionId);
virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
const drm::V1_0::SharedBuffer &source, size_t offset,
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h b/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
index 50878a6..eec4585 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
@@ -49,7 +49,7 @@
virtual status_t destroyPlugin();
virtual bool requiresSecureDecoderComponent(const char* mime) const;
virtual void notifyResolution(uint32_t width, uint32_t height);
- virtual status_t setMediaDrmSession(const Vector<uint8_t>& sessionId);
+ virtual DrmStatus setMediaDrmSession(const Vector<uint8_t>& sessionId);
virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode,
const CryptoPlugin::Pattern& pattern, const ::SharedBuffer& source,
size_t offset, const CryptoPlugin::SubSample* subSamples,
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h b/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
index 6db1e89..0150d7c 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
@@ -57,7 +57,7 @@
virtual void notifyResolution(uint32_t width, uint32_t height);
- virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
+ virtual DrmStatus setMediaDrmSession(const Vector<uint8_t> &sessionId);
virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
diff --git a/drm/libmediadrm/include/mediadrm/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
index eab597b..16e5fe1 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHal.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -15,6 +15,7 @@
*/
#include <mediadrm/IDrm.h>
+#include <mediadrm/DrmStatus.h>
#ifndef DRM_HAL_H_
#define DRM_HAL_H_
@@ -24,100 +25,99 @@
struct DrmHal : public IDrm {
DrmHal();
virtual ~DrmHal();
- virtual status_t initCheck() const;
- virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
- const String8 &mimeType,
- DrmPlugin::SecurityLevel securityLevel,
- bool *result);
- virtual status_t createPlugin(const uint8_t uuid[16],
- const String8 &appPackageName);
- virtual status_t destroyPlugin();
- virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
+ virtual DrmStatus initCheck() const;
+ virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel, bool* result);
+ virtual DrmStatus createPlugin(const uint8_t uuid[16],
+ const String8 &appPackageName);
+ virtual DrmStatus destroyPlugin();
+ virtual DrmStatus openSession(DrmPlugin::SecurityLevel securityLevel,
Vector<uint8_t> &sessionId);
- virtual status_t closeSession(Vector<uint8_t> const &sessionId);
- virtual status_t
+ virtual DrmStatus closeSession(Vector<uint8_t> const &sessionId);
+ virtual DrmStatus
getKeyRequest(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &initData,
String8 const &mimeType, DrmPlugin::KeyType keyType,
KeyedVector<String8, String8> const &optionalParameters,
Vector<uint8_t> &request, String8 &defaultUrl,
DrmPlugin::KeyRequestType *keyRequestType);
- virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &response,
- Vector<uint8_t> &keySetId);
- virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
- virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keySetId);
- virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
- KeyedVector<String8, String8> &infoMap) const;
- virtual status_t getProvisionRequest(String8 const &certType,
- String8 const &certAuthority,
- Vector<uint8_t> &request,
- String8 &defaultUrl);
- virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
- Vector<uint8_t> &certificate,
- Vector<uint8_t> &wrappedKey);
- virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
- virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
- virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
- virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
- virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
- virtual status_t removeAllSecureStops();
- virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
+ virtual DrmStatus provideKeyResponse(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &response,
+ Vector<uint8_t> &keySetId);
+ virtual DrmStatus removeKeys(Vector<uint8_t> const &keySetId);
+ virtual DrmStatus restoreKeys(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keySetId);
+ virtual DrmStatus queryKeyStatus(Vector<uint8_t> const &sessionId,
+ KeyedVector<String8, String8> &infoMap) const;
+ virtual DrmStatus getProvisionRequest(String8 const &certType,
+ String8 const &certAuthority,
+ Vector<uint8_t> &request,
+ String8 &defaultUrl);
+ virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const &response,
+ Vector<uint8_t> &certificate,
+ Vector<uint8_t> &wrappedKey);
+ virtual DrmStatus getSecureStops(List<Vector<uint8_t>> &secureStops);
+ virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
+ virtual DrmStatus getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
+ virtual DrmStatus releaseSecureStops(Vector<uint8_t> const &ssRelease);
+ virtual DrmStatus removeSecureStop(Vector<uint8_t> const &ssid);
+ virtual DrmStatus removeAllSecureStops();
+ virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
DrmPlugin::HdcpLevel *maxLevel) const;
- virtual status_t getNumberOfSessions(uint32_t *currentSessions,
+ virtual DrmStatus getNumberOfSessions(uint32_t *currentSessions,
uint32_t *maxSessions) const;
- virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
+ virtual DrmStatus getSecurityLevel(Vector<uint8_t> const &sessionId,
DrmPlugin::SecurityLevel *level) const;
- virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
- virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId);
- virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
+ virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
+ virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const &keySetId);
+ virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const &keySetId,
DrmPlugin::OfflineLicenseState *licenseState) const;
- virtual status_t getPropertyString(String8 const &name, String8 &value) const;
- virtual status_t getPropertyByteArray(String8 const &name,
- Vector<uint8_t> &value) const;
- virtual status_t setPropertyString(String8 const &name,
- String8 const &value ) const;
- virtual status_t setPropertyByteArray(String8 const &name,
- Vector<uint8_t> const &value) const;
- virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer);
- virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm);
- virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm);
- virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+ virtual DrmStatus getPropertyString(String8 const &name, String8 &value) const;
+ virtual DrmStatus getPropertyByteArray(String8 const &name,
+ Vector<uint8_t> &value) const;
+ virtual DrmStatus setPropertyString(String8 const &name,
+ String8 const &value ) const;
+ virtual DrmStatus setPropertyByteArray(String8 const &name,
+ Vector<uint8_t> const &value) const;
+ virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer> &consumer);
+ virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
+ virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
+ virtual DrmStatus encrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+ virtual DrmStatus decrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+ virtual DrmStatus sign(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> &signature);
+ virtual DrmStatus verify(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output);
- virtual status_t decrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output);
- virtual status_t sign(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> &signature);
- virtual status_t verify(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> const &signature,
- bool &match);
- virtual status_t signRSA(Vector<uint8_t> const &sessionId,
- String8 const &algorithm,
Vector<uint8_t> const &message,
- Vector<uint8_t> const &wrappedKey,
- Vector<uint8_t> &signature);
- virtual status_t setListener(const sp<IDrmClient>& listener);
- virtual status_t requiresSecureDecoder(const char *mime, bool *required) const;
- virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
- bool *required) const;
- virtual status_t setPlaybackId(
+ Vector<uint8_t> const &signature,
+ bool &match);
+ virtual DrmStatus signRSA(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> const &wrappedKey,
+ Vector<uint8_t> &signature);
+ virtual DrmStatus setListener(const sp<IDrmClient>& listener);
+ virtual DrmStatus requiresSecureDecoder(const char *mime, bool *required) const;
+ virtual DrmStatus requiresSecureDecoder(const char *mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool *required) const;
+ virtual DrmStatus setPlaybackId(
Vector<uint8_t> const &sessionId,
const char *playbackId);
- virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
- virtual status_t getSupportedSchemes(std::vector<uint8_t> &schemes) const;
+ virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
+ virtual DrmStatus getSupportedSchemes(std::vector<uint8_t> &schemes) const;
private:
sp<IDrm> mDrmHalHidl;
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalAidl.h b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
index 0f51ce9..a81b312 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
@@ -25,6 +25,7 @@
#include <mediadrm/DrmMetrics.h>
#include <mediadrm/DrmSessionManager.h>
#include <mediadrm/DrmHalListener.h>
+#include <mediadrm/DrmStatus.h>
#include <mediadrm/IDrm.h>
using IDrmPluginAidl = ::aidl::android::hardware::drm::IDrmPlugin;
@@ -38,74 +39,78 @@
struct DrmSessionClient;
DrmHalAidl();
virtual ~DrmHalAidl();
- virtual status_t initCheck() const;
- virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
- DrmPlugin::SecurityLevel securityLevel, bool* result);
- virtual status_t createPlugin(const uint8_t uuid[16], const String8& appPackageName);
- virtual status_t destroyPlugin();
- virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
- Vector<uint8_t>& sessionId);
- virtual status_t closeSession(Vector<uint8_t> const& sessionId);
- virtual status_t getKeyRequest(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& initData, String8 const& mimeType,
- DrmPlugin::KeyType keyType,
- KeyedVector<String8, String8> const& optionalParameters,
- Vector<uint8_t>& request, String8& defaultUrl,
- DrmPlugin::KeyRequestType* keyRequestType);
- virtual status_t provideKeyResponse(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& response, Vector<uint8_t>& keySetId);
- virtual status_t removeKeys(Vector<uint8_t> const& keySetId);
- virtual status_t restoreKeys(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keySetId);
- virtual status_t queryKeyStatus(Vector<uint8_t> const& sessionId,
- KeyedVector<String8, String8>& infoMap) const;
- virtual status_t getProvisionRequest(String8 const& certType, String8 const& certAuthority,
- Vector<uint8_t>& request, String8& defaultUrl);
- virtual status_t provideProvisionResponse(Vector<uint8_t> const& response,
- Vector<uint8_t>& certificate,
- Vector<uint8_t>& wrappedKey);
- virtual status_t getSecureStops(List<Vector<uint8_t>>& secureStops);
- virtual status_t getSecureStopIds(List<Vector<uint8_t>>& secureStopIds);
- virtual status_t getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop);
- virtual status_t releaseSecureStops(Vector<uint8_t> const& ssRelease);
- virtual status_t removeSecureStop(Vector<uint8_t> const& ssid);
- virtual status_t removeAllSecureStops();
- virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
- DrmPlugin::HdcpLevel* maxLevel) const;
- virtual status_t getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const;
- virtual status_t getSecurityLevel(Vector<uint8_t> const& sessionId,
- DrmPlugin::SecurityLevel* level) const;
- virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const;
- virtual status_t removeOfflineLicense(Vector<uint8_t> const& keySetId);
- virtual status_t getOfflineLicenseState(Vector<uint8_t> const& keySetId,
- DrmPlugin::OfflineLicenseState* licenseState) const;
- virtual status_t getPropertyString(String8 const& name, String8& value) const;
- virtual status_t getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const;
- virtual status_t setPropertyString(String8 const& name, String8 const& value) const;
- virtual status_t setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const;
- virtual status_t getMetrics(const sp<IDrmMetricsConsumer>& consumer);
- virtual status_t setCipherAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
- virtual status_t setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
- virtual status_t encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output);
- virtual status_t decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output);
- virtual status_t sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t>& signature);
- virtual status_t verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
- bool& match);
- virtual status_t signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
- Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
- Vector<uint8_t>& signature);
- virtual status_t setListener(const sp<IDrmClient>& listener);
- virtual status_t requiresSecureDecoder(const char* mime, bool* required) const;
- virtual status_t requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
- bool* required) const;
- virtual status_t setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId);
- virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const;
- virtual status_t getSupportedSchemes(std::vector<uint8_t> &schemes) const;
+ virtual DrmStatus initCheck() const;
+ virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel, bool* result);
+ virtual DrmStatus createPlugin(const uint8_t uuid[16], const String8& appPackageName);
+ virtual DrmStatus destroyPlugin();
+ virtual DrmStatus openSession(DrmPlugin::SecurityLevel securityLevel,
+ Vector<uint8_t>& sessionId);
+ virtual DrmStatus closeSession(Vector<uint8_t> const& sessionId);
+ virtual DrmStatus getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType);
+ virtual DrmStatus provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response,
+ Vector<uint8_t>& keySetId);
+ virtual DrmStatus removeKeys(Vector<uint8_t> const& keySetId);
+ virtual DrmStatus restoreKeys(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& keySetId);
+ virtual DrmStatus queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const;
+ virtual DrmStatus getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl);
+ virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey);
+ virtual DrmStatus getSecureStops(List<Vector<uint8_t>>& secureStops);
+ virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>>& secureStopIds);
+ virtual DrmStatus getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop);
+ virtual DrmStatus releaseSecureStops(Vector<uint8_t> const& ssRelease);
+ virtual DrmStatus removeSecureStop(Vector<uint8_t> const& ssid);
+ virtual DrmStatus removeAllSecureStops();
+ virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+ DrmPlugin::HdcpLevel* maxLevel) const;
+ virtual DrmStatus getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const;
+ virtual DrmStatus getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const;
+ virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const;
+ virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const& keySetId);
+ virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const;
+ virtual DrmStatus getPropertyString(String8 const& name, String8& value) const;
+ virtual DrmStatus getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const;
+ virtual DrmStatus setPropertyString(String8 const& name, String8 const& value) const;
+ virtual DrmStatus setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const;
+ virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer>& consumer);
+ virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+ String8 const& algorithm);
+ virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
+ virtual DrmStatus encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output);
+ virtual DrmStatus decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output);
+ virtual DrmStatus sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature);
+ virtual DrmStatus verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match);
+ virtual DrmStatus signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature);
+ virtual DrmStatus setListener(const sp<IDrmClient>& listener);
+ virtual DrmStatus requiresSecureDecoder(const char* mime, bool* required) const;
+ virtual DrmStatus requiresSecureDecoder(const char* mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const;
+ virtual DrmStatus setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId);
+ virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const;
+ virtual DrmStatus getSupportedSchemes(std::vector<uint8_t>& schemes) const;
::ndk::ScopedAStatus onEvent(EventTypeAidl in_eventType,
const std::vector<uint8_t>& in_sessionId,
@@ -118,7 +123,7 @@
::ndk::ScopedAStatus onSessionLostState(const std::vector<uint8_t>& in_sessionId);
private:
static Mutex mLock;
- mutable MediaDrmMetrics mMetrics;
+ std::shared_ptr<MediaDrmMetrics> mMetrics;
std::shared_ptr<DrmHalListener> mListener;
const std::vector<std::shared_ptr<IDrmFactoryAidl>> mFactories;
std::shared_ptr<IDrmPluginAidl> mPlugin;
@@ -128,8 +133,8 @@
void closeOpenSessions();
std::string reportPluginMetrics() const;
std::string reportFrameworkMetrics(const std::string& pluginMetrics) const;
- status_t getPropertyStringInternal(String8 const& name, String8& value) const;
- status_t getPropertyByteArrayInternal(String8 const& name, Vector<uint8_t>& value) const;
+ DrmStatus getPropertyStringInternal(String8 const& name, String8& value) const;
+ DrmStatus getPropertyByteArrayInternal(String8 const& name, Vector<uint8_t>& value) const;
DISALLOW_EVIL_CONSTRUCTORS(DrmHalAidl);
};
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalHidl.h b/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
index 11f0608..73a9e1d 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
@@ -26,6 +26,7 @@
#include <media/drm/DrmAPI.h>
#include <mediadrm/DrmMetrics.h>
#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/DrmStatus.h>
#include <mediadrm/IDrm.h>
#include <mediadrm/IDrmClient.h>
#include <mediadrm/IDrmMetricsConsumer.h>
@@ -63,24 +64,22 @@
DrmHalHidl();
virtual ~DrmHalHidl();
- virtual status_t initCheck() const;
+ virtual DrmStatus initCheck() const;
- virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
- const String8& mimeType,
- DrmPlugin::SecurityLevel level,
- bool *isSupported);
+ virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level, bool* isSupported);
- virtual status_t createPlugin(const uint8_t uuid[16],
- const String8 &appPackageName);
+ virtual DrmStatus createPlugin(const uint8_t uuid[16],
+ const String8 &appPackageName);
- virtual status_t destroyPlugin();
+ virtual DrmStatus destroyPlugin();
- virtual status_t openSession(DrmPlugin::SecurityLevel level,
+ virtual DrmStatus openSession(DrmPlugin::SecurityLevel level,
Vector<uint8_t> &sessionId);
- virtual status_t closeSession(Vector<uint8_t> const &sessionId);
+ virtual DrmStatus closeSession(Vector<uint8_t> const &sessionId);
- virtual status_t
+ virtual DrmStatus
getKeyRequest(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &initData,
String8 const &mimeType, DrmPlugin::KeyType keyType,
@@ -88,103 +87,104 @@
Vector<uint8_t> &request, String8 &defaultUrl,
DrmPlugin::KeyRequestType *keyRequestType);
- virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &response,
- Vector<uint8_t> &keySetId);
+ virtual DrmStatus provideKeyResponse(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &response,
+ Vector<uint8_t> &keySetId);
- virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
+ virtual DrmStatus removeKeys(Vector<uint8_t> const &keySetId);
- virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keySetId);
+ virtual DrmStatus restoreKeys(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keySetId);
- virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
- KeyedVector<String8, String8> &infoMap) const;
+ virtual DrmStatus queryKeyStatus(Vector<uint8_t> const &sessionId,
+ KeyedVector<String8, String8> &infoMap) const;
- virtual status_t getProvisionRequest(String8 const &certType,
- String8 const &certAuthority,
- Vector<uint8_t> &request,
- String8 &defaultUrl);
+ virtual DrmStatus getProvisionRequest(String8 const &certType,
+ String8 const &certAuthority,
+ Vector<uint8_t> &request,
+ String8 &defaultUrl);
- virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
- Vector<uint8_t> &certificate,
- Vector<uint8_t> &wrappedKey);
+ virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const &response,
+ Vector<uint8_t> &certificate,
+ Vector<uint8_t> &wrappedKey);
- virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
- virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
- virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
+ virtual DrmStatus getSecureStops(List<Vector<uint8_t>> &secureStops);
+ virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
+ virtual DrmStatus getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
- virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
- virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
- virtual status_t removeAllSecureStops();
+ virtual DrmStatus releaseSecureStops(Vector<uint8_t> const &ssRelease);
+ virtual DrmStatus removeSecureStop(Vector<uint8_t> const &ssid);
+ virtual DrmStatus removeAllSecureStops();
- virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
+ virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
DrmPlugin::HdcpLevel *maxLevel) const;
- virtual status_t getNumberOfSessions(uint32_t *currentSessions,
+ virtual DrmStatus getNumberOfSessions(uint32_t *currentSessions,
uint32_t *maxSessions) const;
- virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
+ virtual DrmStatus getSecurityLevel(Vector<uint8_t> const &sessionId,
DrmPlugin::SecurityLevel *level) const;
- virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
- virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId);
- virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
+ virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
+ virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const &keySetId);
+ virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const &keySetId,
DrmPlugin::OfflineLicenseState *licenseState) const;
- virtual status_t getPropertyString(String8 const &name, String8 &value ) const;
- virtual status_t getPropertyByteArray(String8 const &name,
- Vector<uint8_t> &value ) const;
- virtual status_t setPropertyString(String8 const &name, String8 const &value ) const;
- virtual status_t setPropertyByteArray(String8 const &name,
- Vector<uint8_t> const &value ) const;
- virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer);
+ virtual DrmStatus getPropertyString(String8 const &name, String8 &value ) const;
+ virtual DrmStatus getPropertyByteArray(String8 const &name,
+ Vector<uint8_t> &value ) const;
+ virtual DrmStatus setPropertyString(String8 const &name, String8 const &value ) const;
+ virtual DrmStatus setPropertyByteArray(String8 const &name,
+ Vector<uint8_t> const &value ) const;
+ virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer> &consumer);
- virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm);
+ virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
- virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm);
+ virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
- virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+ virtual DrmStatus encrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+
+ virtual DrmStatus decrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+
+ virtual DrmStatus sign(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> &signature);
+
+ virtual DrmStatus verify(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output);
-
- virtual status_t decrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output);
-
- virtual status_t sign(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> &signature);
-
- virtual status_t verify(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> const &signature,
- bool &match);
-
- virtual status_t signRSA(Vector<uint8_t> const &sessionId,
- String8 const &algorithm,
Vector<uint8_t> const &message,
- Vector<uint8_t> const &wrappedKey,
- Vector<uint8_t> &signature);
+ Vector<uint8_t> const &signature,
+ bool &match);
- virtual status_t setListener(const sp<IDrmClient>& listener);
+ virtual DrmStatus signRSA(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> const &wrappedKey,
+ Vector<uint8_t> &signature);
- virtual status_t requiresSecureDecoder(const char *mime, bool *required) const;
+ virtual DrmStatus setListener(const sp<IDrmClient>& listener);
- virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
- bool *required) const;
+ virtual DrmStatus requiresSecureDecoder(const char *mime, bool *required) const;
- virtual status_t setPlaybackId(
+ virtual DrmStatus requiresSecureDecoder(const char *mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool *required) const;
+
+ virtual DrmStatus setPlaybackId(
Vector<uint8_t> const &sessionId,
const char *playbackId);
- virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
- virtual status_t getSupportedSchemes(std::vector<uint8_t> &schemes) const;
+ virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
+ virtual DrmStatus getSupportedSchemes(std::vector<uint8_t> &schemes) const;
// Methods of IDrmPluginListener
Return<void> sendEvent(EventType eventType,
@@ -238,10 +238,10 @@
std::string reportPluginMetrics() const;
std::string reportFrameworkMetrics(const std::string& pluginMetrics) const;
- status_t getPropertyStringInternal(String8 const &name, String8 &value) const;
- status_t getPropertyByteArrayInternal(String8 const &name,
+ DrmStatus getPropertyStringInternal(String8 const &name, String8 &value) const;
+ DrmStatus getPropertyByteArrayInternal(String8 const &name,
Vector<uint8_t> &value) const;
- status_t matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
+ DrmStatus matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
const uint8_t uuid[16],
const String8 &mimeType,
DrmPlugin::SecurityLevel level,
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalListener.h b/drm/libmediadrm/include/mediadrm/DrmHalListener.h
index 22361ad..0eed929 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHalListener.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHalListener.h
@@ -27,7 +27,7 @@
namespace android {
struct DrmHalListener : public BnDrmPluginListener {
- explicit DrmHalListener(MediaDrmMetrics* mMetrics);
+ explicit DrmHalListener(const std::shared_ptr<MediaDrmMetrics>& in_metrics);
~DrmHalListener();
::ndk::ScopedAStatus onEvent(EventTypeAidl in_eventType,
const std::vector<uint8_t>& in_sessionId,
@@ -38,9 +38,9 @@
const std::vector<KeyStatusAidl>& in_keyStatusList,
bool in_hasNewUsableKey);
::ndk::ScopedAStatus onSessionLostState(const std::vector<uint8_t>& in_sessionId);
- void setListener(sp<IDrmClient> listener);
+ void setListener(const sp<IDrmClient>& listener);
private:
- mutable MediaDrmMetrics* mMetrics;
+ std::shared_ptr<MediaDrmMetrics> mMetrics;
sp<IDrmClient> mListener;
mutable Mutex mEventLock;
mutable Mutex mNotifyLock;
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
new file mode 100644
index 0000000..7666f04
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2022 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 <mediadrm/DrmStatus.h>
+#include <mediadrm/IDrm.h>
+#include <sys/random.h>
+#include <map>
+#include <mutex>
+
+#ifndef DRM_METRICS_LOGGER_H
+#define DRM_METRICS_LOGGER_H
+
+namespace android {
+
+enum {
+ JERROR_DRM_UNKNOWN = 0,
+ JERROR_DRM_NO_LICENSE = 1,
+ JERROR_DRM_LICENSE_EXPIRED = 2,
+ JERROR_DRM_RESOURCE_BUSY = 3,
+ JERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = 4,
+ JERROR_DRM_SESSION_NOT_OPENED = 5,
+ JERROR_DRM_CANNOT_HANDLE = 6,
+ JERROR_DRM_INSUFFICIENT_SECURITY = 7,
+ JERROR_DRM_FRAME_TOO_LARGE = 8,
+ JERROR_DRM_SESSION_LOST_STATE = 9,
+ JERROR_DRM_CERTIFICATE_MALFORMED = 10,
+ JERROR_DRM_CERTIFICATE_MISSING = 11,
+ JERROR_DRM_CRYPTO_LIBRARY = 12,
+ JERROR_DRM_GENERIC_OEM = 13,
+ JERROR_DRM_GENERIC_PLUGIN = 14,
+ JERROR_DRM_INIT_DATA = 15,
+ JERROR_DRM_KEY_NOT_LOADED = 16,
+ JERROR_DRM_LICENSE_PARSE = 17,
+ JERROR_DRM_LICENSE_POLICY = 18,
+ JERROR_DRM_LICENSE_RELEASE = 19,
+ JERROR_DRM_LICENSE_REQUEST_REJECTED = 20,
+ JERROR_DRM_LICENSE_RESTORE = 21,
+ JERROR_DRM_LICENSE_STATE = 22,
+ JERROR_DRM_MEDIA_FRAMEWORK = 23,
+ JERROR_DRM_PROVISIONING_CERTIFICATE = 24,
+ JERROR_DRM_PROVISIONING_CONFIG = 25,
+ JERROR_DRM_PROVISIONING_PARSE = 26,
+ JERROR_DRM_PROVISIONING_REQUEST_REJECTED = 27,
+ JERROR_DRM_PROVISIONING_RETRY = 28,
+ JERROR_DRM_RESOURCE_CONTENTION = 29,
+ JERROR_DRM_SECURE_STOP_RELEASE = 30,
+ JERROR_DRM_STORAGE_READ = 31,
+ JERROR_DRM_STORAGE_WRITE = 32,
+ JERROR_DRM_ZERO_SUBSAMPLES = 33,
+};
+
+enum {
+ JSecurityLevelUnknown = 0,
+ JSecurityLevelSwSecureCrypto = 1,
+ JSecurityLevelSwSecureDecode = 2,
+ JSecurityLevelHwSecureCrypto = 3,
+ JSecurityLevelHwSecureDecode = 4,
+ JSecurityLevelHwSecureAll = 5,
+ JSecurityLevelMax = 6,
+};
+
+struct SessionContext {
+ std::string mNonce;
+ DrmPlugin::SecurityLevel mTargetSecurityLevel;
+ DrmPlugin::SecurityLevel mActualSecurityLevel;
+ std::string mVersion;
+};
+
+class DrmMetricsLogger : public IDrm {
+ public:
+ DrmMetricsLogger(IDrmFrontend);
+
+ virtual ~DrmMetricsLogger();
+
+ virtual DrmStatus initCheck() const;
+
+ virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[IDRM_UUID_SIZE],
+ const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool* result);
+
+ virtual DrmStatus createPlugin(const uint8_t uuid[IDRM_UUID_SIZE],
+ const String8& appPackageName);
+
+ virtual DrmStatus destroyPlugin();
+
+ virtual DrmStatus openSession(DrmPlugin::SecurityLevel securityLevel,
+ Vector<uint8_t>& sessionId);
+
+ virtual DrmStatus closeSession(Vector<uint8_t> const& sessionId);
+
+ virtual DrmStatus getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType);
+
+ virtual DrmStatus provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response,
+ Vector<uint8_t>& keySetId);
+
+ virtual DrmStatus removeKeys(Vector<uint8_t> const& keySetId);
+
+ virtual DrmStatus restoreKeys(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& keySetId);
+
+ virtual DrmStatus queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const;
+
+ virtual DrmStatus getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl);
+
+ virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey);
+
+ virtual DrmStatus getSecureStops(List<Vector<uint8_t>>& secureStops);
+ virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>>& secureStopIds);
+ virtual DrmStatus getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop);
+
+ virtual DrmStatus releaseSecureStops(Vector<uint8_t> const& ssRelease);
+ virtual DrmStatus removeSecureStop(Vector<uint8_t> const& ssid);
+ virtual DrmStatus removeAllSecureStops();
+
+ virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+ DrmPlugin::HdcpLevel* maxLevel) const;
+ virtual DrmStatus getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const;
+ virtual DrmStatus getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const;
+
+ virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const;
+ virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const& keySetId);
+ virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const;
+
+ virtual DrmStatus getPropertyString(String8 const& name, String8& value) const;
+ virtual DrmStatus getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const;
+ virtual DrmStatus setPropertyString(String8 const& name, String8 const& value) const;
+ virtual DrmStatus setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const;
+
+ virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer>& consumer);
+
+ virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+ String8 const& algorithm);
+
+ virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
+
+ virtual DrmStatus encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output);
+
+ virtual DrmStatus decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output);
+
+ virtual DrmStatus sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature);
+
+ virtual DrmStatus verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match);
+
+ virtual DrmStatus signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature);
+
+ virtual DrmStatus setListener(const sp<IDrmClient>& listener);
+
+ virtual DrmStatus requiresSecureDecoder(const char* mime, bool* required) const;
+
+ virtual DrmStatus requiresSecureDecoder(const char* mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const;
+
+ virtual DrmStatus setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId);
+
+ virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const;
+
+ virtual DrmStatus getSupportedSchemes(std::vector<uint8_t>& schemes) const;
+
+ void reportMediaDrmCreated() const;
+
+ void reportMediaDrmSessionOpened(const std::vector<uint8_t>& sessionId) const;
+
+ void reportMediaDrmErrored(
+ const DrmStatus& error_code, const char* api,
+ const std::vector<uint8_t>& sessionId = std::vector<uint8_t>()) const;
+
+ DrmStatus generateNonce(std::string* out, size_t size, const char* api);
+
+ private:
+ static const size_t kNonceSize = 16;
+ static const std::map<std::array<int64_t, 2>, std::string> kUuidSchemeMap;
+ sp<IDrm> mImpl;
+ std::array<int64_t, 2> mUuid;
+ std::string mObjNonce;
+ std::string mScheme;
+ std::string mVersion;
+ std::map<std::vector<uint8_t>, SessionContext> mSessionMap;
+ mutable std::mutex mSessionMapMutex;
+ IDrmFrontend mFrontend;
+ DISALLOW_EVIL_CONSTRUCTORS(DrmMetricsLogger);
+};
+
+} // namespace android
+
+#endif // DRM_METRICS_LOGGER_H
\ No newline at end of file
diff --git a/drm/libmediadrm/include/mediadrm/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
index ee2be6a..ff5f63b 100644
--- a/drm/libmediadrm/include/mediadrm/IDrm.h
+++ b/drm/libmediadrm/include/mediadrm/IDrm.h
@@ -16,6 +16,7 @@
#include <media/stagefright/foundation/ABase.h>
#include <media/drm/DrmAPI.h>
+#include <mediadrm/DrmStatus.h>
#include <mediadrm/IDrmClient.h>
#include <mediadrm/IDrmMetricsConsumer.h>
@@ -23,6 +24,8 @@
#define ANDROID_IDRM_H_
+#define IDRM_UUID_SIZE (16)
+
namespace android {
namespace hardware {
namespace drm {
@@ -32,6 +35,13 @@
} // namespace drm
} // namespace hardware
+enum IDrmFrontend : int32_t {
+ IDRM_UNKNOWN = 0,
+ IDRM_JNI = 1,
+ IDRM_NDK = 2,
+ IDRM_NUPLAYER = 3,
+};
+
namespace drm = ::android::hardware::drm;
struct AString;
@@ -40,24 +50,23 @@
virtual ~IDrm() {}
- virtual status_t initCheck() const = 0;
+ virtual DrmStatus initCheck() const = 0;
- virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
- const String8 &mimeType,
- DrmPlugin::SecurityLevel securityLevel,
- bool *result) = 0;
+ virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool* result) = 0;
- virtual status_t createPlugin(const uint8_t uuid[16],
- const String8 &appPackageName) = 0;
+ virtual DrmStatus createPlugin(const uint8_t uuid[16],
+ const String8 &appPackageName) = 0;
- virtual status_t destroyPlugin() = 0;
+ virtual DrmStatus destroyPlugin() = 0;
- virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
+ virtual DrmStatus openSession(DrmPlugin::SecurityLevel securityLevel,
Vector<uint8_t> &sessionId) = 0;
- virtual status_t closeSession(Vector<uint8_t> const &sessionId) = 0;
+ virtual DrmStatus closeSession(Vector<uint8_t> const &sessionId) = 0;
- virtual status_t
+ virtual DrmStatus
getKeyRequest(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &initData,
String8 const &mimeType, DrmPlugin::KeyType keyType,
@@ -65,107 +74,108 @@
Vector<uint8_t> &request, String8 &defaultUrl,
DrmPlugin::KeyRequestType *keyRequestType) = 0;
- virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &response,
- Vector<uint8_t> &keySetId) = 0;
+ virtual DrmStatus provideKeyResponse(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &response,
+ Vector<uint8_t> &keySetId) = 0;
- virtual status_t removeKeys(Vector<uint8_t> const &keySetId) = 0;
+ virtual DrmStatus removeKeys(Vector<uint8_t> const &keySetId) = 0;
- virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keySetId) = 0;
+ virtual DrmStatus restoreKeys(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keySetId) = 0;
- virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
- KeyedVector<String8, String8> &infoMap) const = 0;
+ virtual DrmStatus queryKeyStatus(Vector<uint8_t> const &sessionId,
+ KeyedVector<String8, String8> &infoMap) const = 0;
- virtual status_t getProvisionRequest(String8 const &certType,
- String8 const &certAuthority,
- Vector<uint8_t> &request,
- String8 &defaulUrl) = 0;
+ virtual DrmStatus getProvisionRequest(String8 const &certType,
+ String8 const &certAuthority,
+ Vector<uint8_t> &request,
+ String8 &defaultUrl) = 0;
- virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
- Vector<uint8_t> &certificate,
- Vector<uint8_t> &wrappedKey) = 0;
+ virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const &response,
+ Vector<uint8_t> &certificate,
+ Vector<uint8_t> &wrappedKey) = 0;
- virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops) = 0;
- virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) = 0;
- virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0;
+ virtual DrmStatus getSecureStops(List<Vector<uint8_t>> &secureStops) = 0;
+ virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) = 0;
+ virtual DrmStatus getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0;
- virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
- virtual status_t removeSecureStop(Vector<uint8_t> const &ssid) = 0;
- virtual status_t removeAllSecureStops() = 0;
+ virtual DrmStatus releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
+ virtual DrmStatus removeSecureStop(Vector<uint8_t> const &ssid) = 0;
+ virtual DrmStatus removeAllSecureStops() = 0;
- virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
+ virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
DrmPlugin::HdcpLevel *maxLevel)
const = 0;
- virtual status_t getNumberOfSessions(uint32_t *currentSessions,
+ virtual DrmStatus getNumberOfSessions(uint32_t *currentSessions,
uint32_t *maxSessions) const = 0;
- virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
+ virtual DrmStatus getSecurityLevel(Vector<uint8_t> const &sessionId,
DrmPlugin::SecurityLevel *level) const = 0;
- virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const = 0;
- virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId) = 0;
- virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
+ virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const = 0;
+ virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const &keySetId) = 0;
+ virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const &keySetId,
DrmPlugin::OfflineLicenseState *licenseState) const = 0;
- virtual status_t getPropertyString(String8 const &name, String8 &value) const = 0;
- virtual status_t getPropertyByteArray(String8 const &name,
- Vector<uint8_t> &value) const = 0;
- virtual status_t setPropertyString(String8 const &name,
- String8 const &value ) const = 0;
- virtual status_t setPropertyByteArray(String8 const &name,
- Vector<uint8_t> const &value) const = 0;
+ virtual DrmStatus getPropertyString(String8 const &name, String8 &value) const = 0;
+ virtual DrmStatus getPropertyByteArray(String8 const &name,
+ Vector<uint8_t> &value) const = 0;
+ virtual DrmStatus setPropertyString(String8 const &name,
+ String8 const &value ) const = 0;
+ virtual DrmStatus setPropertyByteArray(String8 const &name,
+ Vector<uint8_t> const &value) const = 0;
- virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer) = 0;
+ virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer> &consumer) = 0;
- virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm) = 0;
+ virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm) = 0;
- virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm) = 0;
+ virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm) = 0;
- virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+ virtual DrmStatus encrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output) = 0;
+
+ virtual DrmStatus decrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output) = 0;
+
+ virtual DrmStatus sign(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> &signature) = 0;
+
+ virtual DrmStatus verify(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output) = 0;
-
- virtual status_t decrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output) = 0;
-
- virtual status_t sign(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> &signature) = 0;
-
- virtual status_t verify(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> const &signature,
- bool &match) = 0;
-
- virtual status_t signRSA(Vector<uint8_t> const &sessionId,
- String8 const &algorithm,
Vector<uint8_t> const &message,
- Vector<uint8_t> const &wrappedKey,
- Vector<uint8_t> &signature) = 0;
+ Vector<uint8_t> const &signature,
+ bool &match) = 0;
- virtual status_t setListener(const sp<IDrmClient>& listener) = 0;
+ virtual DrmStatus signRSA(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> const &wrappedKey,
+ Vector<uint8_t> &signature) = 0;
- virtual status_t requiresSecureDecoder(const char *mime, bool *required) const = 0;
+ virtual DrmStatus setListener(const sp<IDrmClient>& listener) = 0;
- virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
- bool *required) const = 0;
+ virtual DrmStatus requiresSecureDecoder(const char *mime, bool *required) const = 0;
- virtual status_t setPlaybackId(
+ virtual DrmStatus requiresSecureDecoder(const char *mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool *required) const = 0;
+
+ virtual DrmStatus setPlaybackId(
Vector<uint8_t> const &sessionId,
const char *playbackId) = 0;
- virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const = 0;
+ virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const = 0;
- virtual status_t getSupportedSchemes(std::vector<uint8_t> &schemes) const = 0;
+ virtual DrmStatus getSupportedSchemes(std::vector<uint8_t> &schemes) const = 0;
protected:
IDrm() {}
diff --git a/drm/libmediadrm/interface/mediadrm/DrmStatus.h b/drm/libmediadrm/interface/mediadrm/DrmStatus.h
new file mode 100644
index 0000000..15826ca
--- /dev/null
+++ b/drm/libmediadrm/interface/mediadrm/DrmStatus.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DRM_STATUS_
+#define DRM_STATUS_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/Errors.h>
+
+#include <stdint.h>
+#include <string>
+
+namespace android {
+
+struct DrmStatus {
+ public:
+ DrmStatus(status_t status, int32_t cdmErr = 0, int32_t oemErr = 0,
+ int32_t ctx = 0, std::string errMsg = "")
+ : mStatus(status), mCdmErr(cdmErr), mOemErr(oemErr),
+ mCtx(ctx), mErrMsg(errMsg) {}
+ DrmStatus(status_t err, const char *msg);
+ operator status_t() const { return mStatus; }
+ int32_t getCdmErr() const { return mCdmErr; }
+ int32_t getOemErr() const { return mOemErr; }
+ int32_t getContext() const { return mCtx; }
+ std::string getErrorMessage() const { return mErrMsg; }
+ bool operator==(status_t other) const { return mStatus == other; }
+ bool operator!=(status_t other) const { return mStatus != other; }
+
+ private:
+ status_t mStatus{};
+ int32_t mCdmErr{}, mOemErr{}, mCtx{};
+ std::string mErrMsg;
+};
+
+} // namespace android
+
+#endif // DRM_STATUS_
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
index 980ce55..ba20b95 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -22,6 +22,8 @@
#include <android/hardware/drm/1.4/IDrmPlugin.h>
#include <android/hardware/drm/1.4/types.h>
#include <media/stagefright/MediaErrors.h>
+#include <mediadrm/DrmMetricsLogger.h>
+#include <mediadrm/DrmStatus.h>
#include <utils/Errors.h> // for status_t
#include <utils/Log.h>
#include <utils/String8.h>
@@ -35,6 +37,7 @@
#include <ctime>
#include <deque>
#include <endian.h>
+#include <inttypes.h>
#include <iterator>
#include <mutex>
#include <string>
@@ -103,9 +106,9 @@
void LogToBuffer(android_LogPriority level, const uint8_t uuid[16], const char *fmt, Args... args) {
uint64_t uuid2[2] = {};
std::memcpy(uuid2, uuid, sizeof(uuid2));
- std::string uuidFmt("uuid=[%lx %lx] ");
+ std::string uuidFmt("uuid=[%" PRIx64 " %" PRIx64 "] ");
uuidFmt += fmt;
- LogToBuffer(level, uuidFmt.c_str(), htobe64(uuid2[0]), htobe64(uuid2[1]), args...);
+ LogToBuffer(level, uuidFmt.c_str(), betoh64(uuid2[0]), betoh64(uuid2[1]), args...);
}
#ifndef LOG2BE
@@ -118,7 +121,7 @@
bool UseDrmService();
-sp<IDrm> MakeDrm(status_t *pstatus = nullptr);
+sp<IDrm> MakeDrm(IDrmFrontend frontend = IDRM_JNI, status_t* pstatus = nullptr);
sp<ICrypto> MakeCrypto(status_t *pstatus = nullptr);
@@ -198,98 +201,7 @@
return toStatusT_1_4(err);
}
-inline status_t statusAidlToStatusT(::ndk::ScopedAStatus &statusAidl) {
- if (statusAidl.isOk()) return OK;
- if (statusAidl.getExceptionCode() != EX_SERVICE_SPECIFIC) return DEAD_OBJECT;
- auto status = static_cast<StatusAidl>(statusAidl.getServiceSpecificError());
- switch (status) {
- case StatusAidl::OK:
- return OK;
- case StatusAidl::BAD_VALUE:
- return BAD_VALUE;
- case StatusAidl::ERROR_DRM_CANNOT_HANDLE:
- return ERROR_DRM_CANNOT_HANDLE;
- case StatusAidl::ERROR_DRM_DECRYPT:
- return ERROR_DRM_DECRYPT;
- case StatusAidl::ERROR_DRM_DEVICE_REVOKED:
- return ERROR_DRM_DEVICE_REVOKED;
- case StatusAidl::ERROR_DRM_FRAME_TOO_LARGE:
- return ERROR_DRM_FRAME_TOO_LARGE;
- case StatusAidl::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
- return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
- case StatusAidl::ERROR_DRM_INSUFFICIENT_SECURITY:
- return ERROR_DRM_INSUFFICIENT_SECURITY;
- case StatusAidl::ERROR_DRM_INVALID_STATE:
- return ERROR_DRM_INVALID_STATE;
- case StatusAidl::ERROR_DRM_LICENSE_EXPIRED:
- return ERROR_DRM_LICENSE_EXPIRED;
- case StatusAidl::ERROR_DRM_NO_LICENSE:
- return ERROR_DRM_NO_LICENSE;
- case StatusAidl::ERROR_DRM_NOT_PROVISIONED:
- return ERROR_DRM_NOT_PROVISIONED;
- case StatusAidl::ERROR_DRM_RESOURCE_BUSY:
- return ERROR_DRM_RESOURCE_BUSY;
- case StatusAidl::ERROR_DRM_RESOURCE_CONTENTION:
- return ERROR_DRM_RESOURCE_CONTENTION;
- case StatusAidl::ERROR_DRM_SESSION_LOST_STATE:
- return ERROR_DRM_SESSION_LOST_STATE;
- case StatusAidl::ERROR_DRM_SESSION_NOT_OPENED:
- return ERROR_DRM_SESSION_NOT_OPENED;
-
- // New in S / drm@1.4:
- case StatusAidl::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
- return ERROR_DRM_ZERO_SUBSAMPLES;
- case StatusAidl::CRYPTO_LIBRARY_ERROR:
- return ERROR_DRM_CRYPTO_LIBRARY;
- case StatusAidl::GENERAL_OEM_ERROR:
- return ERROR_DRM_GENERIC_OEM;
- case StatusAidl::GENERAL_PLUGIN_ERROR:
- return ERROR_DRM_GENERIC_PLUGIN;
- case StatusAidl::INIT_DATA_INVALID:
- return ERROR_DRM_INIT_DATA;
- case StatusAidl::KEY_NOT_LOADED:
- return ERROR_DRM_KEY_NOT_LOADED;
- case StatusAidl::LICENSE_PARSE_ERROR:
- return ERROR_DRM_LICENSE_PARSE;
- case StatusAidl::LICENSE_POLICY_ERROR:
- return ERROR_DRM_LICENSE_POLICY;
- case StatusAidl::LICENSE_RELEASE_ERROR:
- return ERROR_DRM_LICENSE_RELEASE;
- case StatusAidl::LICENSE_REQUEST_REJECTED:
- return ERROR_DRM_LICENSE_REQUEST_REJECTED;
- case StatusAidl::LICENSE_RESTORE_ERROR:
- return ERROR_DRM_LICENSE_RESTORE;
- case StatusAidl::LICENSE_STATE_ERROR:
- return ERROR_DRM_LICENSE_STATE;
- case StatusAidl::MALFORMED_CERTIFICATE:
- return ERROR_DRM_CERTIFICATE_MALFORMED;
- case StatusAidl::MEDIA_FRAMEWORK_ERROR:
- return ERROR_DRM_MEDIA_FRAMEWORK;
- case StatusAidl::MISSING_CERTIFICATE:
- return ERROR_DRM_CERTIFICATE_MISSING;
- case StatusAidl::PROVISIONING_CERTIFICATE_ERROR:
- return ERROR_DRM_PROVISIONING_CERTIFICATE;
- case StatusAidl::PROVISIONING_CONFIGURATION_ERROR:
- return ERROR_DRM_PROVISIONING_CONFIG;
- case StatusAidl::PROVISIONING_PARSE_ERROR:
- return ERROR_DRM_PROVISIONING_PARSE;
- case StatusAidl::PROVISIONING_REQUEST_REJECTED:
- return ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
- case StatusAidl::RETRYABLE_PROVISIONING_ERROR:
- return ERROR_DRM_PROVISIONING_RETRY;
- case StatusAidl::SECURE_STOP_RELEASE_ERROR:
- return ERROR_DRM_SECURE_STOP_RELEASE;
- case StatusAidl::STORAGE_READ_FAILURE:
- return ERROR_DRM_STORAGE_READ;
- case StatusAidl::STORAGE_WRITE_FAILURE:
- return ERROR_DRM_STORAGE_WRITE;
-
- case StatusAidl::ERROR_DRM_UNKNOWN:
- default:
- return ERROR_DRM_UNKNOWN;
- }
- return ERROR_DRM_UNKNOWN;
-}
+DrmStatus statusAidlToDrmStatus(::ndk::ScopedAStatus& statusAidl);
template<typename T, typename U>
status_t GetLogMessagesAidl(const std::shared_ptr<U> &obj, Vector<::V1_4::LogMessage> &logs) {
@@ -373,14 +285,16 @@
return OK;
}
-std::string GetExceptionMessage(status_t err, const char *msg,
+std::string GetExceptionMessage(const DrmStatus & err, const char *defaultMsg,
const Vector<::V1_4::LogMessage> &logs);
template<typename T>
-std::string GetExceptionMessage(status_t err, const char *msg, const sp<T> &iface) {
+std::string GetExceptionMessage(const DrmStatus &err, const char *defaultMsg, const sp<T> &iface) {
Vector<::V1_4::LogMessage> logs;
- iface->getLogMessages(logs);
- return GetExceptionMessage(err, msg, logs);
+ if (iface != NULL) {
+ iface->getLogMessages(logs);
+ }
+ return GetExceptionMessage(err, defaultMsg, logs);
}
} // namespace DrmUtils
diff --git a/drm/libmediadrm/interface/mediadrm/ICrypto.h b/drm/libmediadrm/interface/mediadrm/ICrypto.h
index 2c4df60..4087186 100644
--- a/drm/libmediadrm/interface/mediadrm/ICrypto.h
+++ b/drm/libmediadrm/interface/mediadrm/ICrypto.h
@@ -17,6 +17,7 @@
#include <cutils/native_handle.h>
#include <media/hardware/CryptoAPI.h>
#include <media/stagefright/foundation/ABase.h>
+#include <mediadrm/DrmStatus.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
@@ -65,7 +66,7 @@
virtual void notifyResolution(uint32_t width, uint32_t height) = 0;
- virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
+ virtual DrmStatus setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
enum DestinationType {
kDestinationTypeSharedMemory, // non-secure
diff --git a/drm/mediadrm/plugins/clearkey/aidl/Android.bp b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
index 2d1f741..eaf5051 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
@@ -37,6 +37,7 @@
static_libs: [
"android.hardware.common-V2-ndk",
"libclearkeybase",
+ "libjsoncpp",
],
local_include_dirs: ["include"],
@@ -69,3 +70,56 @@
"android.hardware.drm-service.clearkey",
],
}
+
+cc_defaults {
+ name: "fuzz_aidl_clearkey_service_defaults",
+
+ srcs: [
+ "CreatePluginFactories.cpp",
+ "CryptoPlugin.cpp",
+ "DrmFactory.cpp",
+ "DrmPlugin.cpp",
+ ],
+
+ relative_install_path: "hw",
+
+ cflags: ["-Wall", "-Werror", "-Wthread-safety"],
+
+ include_dirs: ["frameworks/av/include"],
+
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcrypto",
+ "liblog",
+ "libprotobuf-cpp-lite",
+ "libutils",
+ "android.hardware.drm-V1-ndk",
+ ],
+
+ static_libs: [
+ "android.hardware.common-V2-ndk",
+ "libclearkeybase_fuzz",
+ "libjsoncpp",
+ ],
+
+ local_include_dirs: ["include"],
+
+ sanitize: {
+ integer_overflow: true,
+ },
+}
+
+cc_fuzz {
+ name: "android.hardware.drm-service.clearkey.aidl_fuzzer",
+ defaults: [
+ "fuzz_aidl_clearkey_service_defaults",
+ "service_fuzzer_defaults",
+ ],
+ srcs: ["fuzzer.cpp"],
+ fuzz_config: {
+ cc: [
+ "hamzeh@google.com",
+ ],
+ },
+}
diff --git a/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp
index afc9b6a..a63471f 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp
@@ -137,6 +137,8 @@
*_aidl_return = static_cast<ssize_t>(offset);
return toNdkScopedAStatus(Status::OK);
} else if (in_args.mode == Mode::AES_CTR) {
+ if (!mSession) return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE,
+ "session not found");
size_t bytesDecrypted{};
std::vector<int32_t> clearDataLengths;
std::vector<int32_t> encryptedDataLengths;
@@ -149,6 +151,7 @@
detailedError = "invalid decrypt parameter size";
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
}
+
auto res =
mSession->decrypt(in_args.keyId.data(), in_args.iv.data(),
srcPtr, static_cast<uint8_t*>(destPtr),
diff --git a/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
index ea51e9d..e8dec80 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "clearkey-DrmPlugin"
#include <aidl/android/hardware/drm/DrmMetric.h>
+#include <android-base/parseint.h>
#include <utils/Log.h>
#include <inttypes.h>
@@ -83,12 +84,14 @@
void DrmPlugin::initProperties() {
mStringProperties.clear();
mStringProperties[kVendorKey] = kAidlVendorValue;
- mStringProperties[kVersionKey] = kAidlVersionValue;
+ mStringProperties[kVersionKey] = kVersionValue;
mStringProperties[kPluginDescriptionKey] = kAidlPluginDescriptionValue;
mStringProperties[kAlgorithmsKey] = kAidlAlgorithmsValue;
mStringProperties[kListenerTestSupportKey] = kAidlListenerTestSupportValue;
mStringProperties[kDrmErrorTestKey] = kAidlDrmErrorTestValue;
mStringProperties[kAidlVersionKey] = kAidlVersionValue;
+ mStringProperties[kOemErrorKey] = "0";
+ mStringProperties[kErrorContextKey] = "0";
std::vector<uint8_t> valueVector;
valueVector.clear();
@@ -102,6 +105,26 @@
mByteArrayProperties[kMetricsKey] = valueVector;
}
+int32_t DrmPlugin::getIntProperty(const std::string& prop, int32_t defaultVal) const {
+ if (!mStringProperties.count(prop)) {
+ return defaultVal;
+ }
+ int32_t out = defaultVal;
+ if (!::android::base::ParseInt(mStringProperties.at(prop), &out)) {
+ return defaultVal;
+ }
+ return out;
+}
+
+int32_t DrmPlugin::getOemError() const {
+ return getIntProperty(kOemErrorKey);
+}
+
+int32_t DrmPlugin::getErrorContext() const {
+ return getIntProperty(kErrorContextKey);
+}
+
+//
// The secure stop in ClearKey implementation is not installed securely.
// This function merely creates a test environment for testing secure stops APIs.
// The content in this secure stop is implementation dependent, the clearkey
@@ -127,7 +150,10 @@
mSessionLibrary->destroySession(session);
if (session->getMockError() != clearkeydrm::OK) {
sendSessionLostState(in_sessionId);
- return toNdkScopedAStatus(Status::ERROR_DRM_INVALID_STATE);
+ return toNdkScopedAStatus(Status::ERROR_DRM_INVALID_STATE,
+ nullptr,
+ getOemError(),
+ getErrorContext());
}
mCloseSessionOkCount++;
return toNdkScopedAStatus(Status::OK);
@@ -198,7 +224,8 @@
if (!session.get()) {
return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED);
} else if (session->getMockError() != clearkeydrm::OK) {
- return toNdkScopedAStatus(session->getMockError());
+ auto err = static_cast<Status>(session->getMockError());
+ return toNdkScopedAStatus(err, nullptr, getOemError(), getErrorContext());
}
keyRequestType = KeyRequestType::INITIAL;
}
@@ -381,6 +408,10 @@
value = mStringProperties[kDrmErrorTestKey];
} else if (name == kAidlVersionKey) {
value = mStringProperties[kAidlVersionKey];
+ } else if (name == kOemErrorKey) {
+ value = mStringProperties[kOemErrorKey];
+ } else if (name == kErrorContextKey) {
+ value = mStringProperties[kErrorContextKey];
} else {
ALOGE("App requested unknown string property %s", name.c_str());
status = Status::ERROR_DRM_CANNOT_HANDLE;
@@ -920,6 +951,13 @@
}
}
+ if (in_propertyName == kOemErrorKey || in_propertyName == kErrorContextKey) {
+ int32_t err = 0;
+ if (!::android::base::ParseInt(in_value, &err)) {
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+ }
+
mStringProperties[key] = std::string(in_value.c_str());
return toNdkScopedAStatus(Status::OK);
}
diff --git a/drm/mediadrm/plugins/clearkey/aidl/fuzzer.cpp b/drm/mediadrm/plugins/clearkey/aidl/fuzzer.cpp
new file mode 100644
index 0000000..9ef331f
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/fuzzer.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 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 <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "CreatePluginFactories.h"
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using ::aidl::android::hardware::drm::clearkey::createDrmFactory;
+using ::aidl::android::hardware::drm::clearkey::DrmFactory;
+
+using android::fuzzService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ std::shared_ptr<DrmFactory> drmFactory = createDrmFactory();
+ fuzzService(drmFactory->asBinder().get(), FuzzedDataProvider(data, size));
+
+ return 0;
+}
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h b/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
index 9257b17..0db3c37 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
@@ -15,9 +15,12 @@
*/
#pragma once
+#include <cstdint>
#include <string>
#include <vector>
+#include <json/json.h>
+
#include <android/binder_auto_utils.h>
#include "aidl/android/hardware/drm/Status.h"
#include "ClearKeyTypes.h"
@@ -41,17 +44,32 @@
}
inline ::ndk::ScopedAStatus toNdkScopedAStatus(::aidl::android::hardware::drm::Status status,
- const char* msg = nullptr) {
+ const char* msg = nullptr,
+ int32_t oemError = 0,
+ int32_t errorContext = 0) {
+
+
if (Status::OK == status) {
return ::ndk::ScopedAStatus::ok();
- } else {
- auto err = static_cast<int32_t>(status);
- if (msg) {
- return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(err, msg);
- } else {
- return ::ndk::ScopedAStatus::fromServiceSpecificError(err);
- }
}
+
+ Json::Value errObj(Json::objectValue);
+ auto err = static_cast<int32_t>(status);
+ errObj["cdmError"] = err;
+
+ if (oemError) {
+ errObj["oemError"] = oemError;
+ }
+ if (errorContext) {
+ errObj["context"] = errorContext;
+ }
+ if (msg) {
+ errObj["errorMessage"] = msg;
+ }
+
+ Json::FastWriter writer;
+ return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ err, writer.write(errObj).c_str());
}
inline ::ndk::ScopedAStatus toNdkScopedAStatus(clearkeydrm::CdmResponseType res) {
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
index 25c05f0..ea85ac8 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
@@ -148,6 +148,9 @@
private:
void initProperties();
+ int32_t getIntProperty(const std::string& prop, int32_t defaultVal = 0) const;
+ int32_t getOemError() const;
+ int32_t getErrorContext() const;
void installSecureStop(const std::vector<uint8_t>& sessionId);
bool makeKeySetId(std::string* keySetId);
void setPlayPolicy();
diff --git a/drm/mediadrm/plugins/clearkey/common/Android.bp b/drm/mediadrm/plugins/clearkey/common/Android.bp
index a6a5b28..6913df4 100644
--- a/drm/mediadrm/plugins/clearkey/common/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/common/Android.bp
@@ -97,3 +97,54 @@
integer_overflow: true,
},
}
+
+cc_library_static {
+ name: "libclearkeydevicefiles-protos.common_fuzz",
+
+ proto: {
+ export_proto_headers: true,
+ type: "lite",
+ },
+ srcs: ["protos/DeviceFiles.proto"],
+}
+
+cc_library_static {
+ name: "libclearkeybase_fuzz",
+
+ srcs: [
+ "AesCtrDecryptor.cpp",
+ "Base64.cpp",
+ "Buffer.cpp",
+ "ClearKeyUUID.cpp",
+ "DeviceFiles.cpp",
+ "InitDataParser.cpp",
+ "JsonWebKey.cpp",
+ "MemoryFileSystem.cpp",
+ "Session.cpp",
+ "SessionLibrary.cpp",
+ "Utils.cpp",
+ ],
+
+ cflags: ["-Wall", "-Werror"],
+
+ include_dirs: ["frameworks/av/include"],
+
+ shared_libs: [
+ "libutils",
+ "libcrypto",
+ ],
+
+ whole_static_libs: [
+ "libjsmn",
+ "libclearkeydevicefiles-protos.common_fuzz",
+ ],
+
+ export_include_dirs: [
+ "include",
+ "include/clearkeydrm",
+ ],
+
+ sanitize: {
+ integer_overflow: true,
+ },
+}
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
index bfda388..d4e641e 100644
--- a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
@@ -21,7 +21,7 @@
static const std::string kVendorKey("vendor");
static const std::string kVendorValue("Google");
static const std::string kVersionKey("version");
-static const std::string kVersionValue("1.2");
+static const std::string kVersionValue("14"); // sync with Android OS version
static const std::string kPluginDescriptionKey("description");
static const std::string kPluginDescriptionValue("ClearKey CDM");
static const std::string kAlgorithmsKey("algorithms");
@@ -35,6 +35,8 @@
static const std::string kFrameTooLargeValue("frameTooLarge");
static const std::string kInvalidStateValue("invalidState");
static const std::string kAidlVersionKey("aidlVersion");
+static const std::string kOemErrorKey("oemError");
+static const std::string kErrorContextKey("errorContext");
static const std::string kDeviceIdKey("deviceId");
static const uint8_t kTestDeviceIdData[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
index 7bc320d..64a43b0 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
@@ -211,6 +211,10 @@
_hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid decrypt parameter size");
return Void();
}
+ if (!mSession) {
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "session not found");
+ return Void();
+ }
Status_V1_2 res = mSession->decrypt(keyId.data(), iv.data(), srcPtr,
static_cast<uint8_t*>(destPtr), toVector(subSamples), &bytesDecrypted);
if (res == Status_V1_2::OK) {
diff --git a/include/media/MicrophoneInfo.h b/include/media/MicrophoneInfo.h
deleted file mode 100644
index a5045b9..0000000
--- a/include/media/MicrophoneInfo.h
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_MICROPHONE_INFO_H
-#define ANDROID_MICROPHONE_INFO_H
-
-#include <android/media/MicrophoneInfoData.h>
-#include <binder/Parcel.h>
-#include <binder/Parcelable.h>
-#include <media/AidlConversionUtil.h>
-#include <system/audio.h>
-
-namespace android {
-namespace media {
-
-class MicrophoneInfo : public Parcelable {
-public:
- MicrophoneInfo() = default;
- MicrophoneInfo(const MicrophoneInfo& microphoneInfo) = default;
- MicrophoneInfo(audio_microphone_characteristic_t& characteristic) {
- mDeviceId = std::string(&characteristic.device_id[0]);
- mPortId = characteristic.id;
- mType = characteristic.device;
- mAddress = std::string(&characteristic.address[0]);
- mDeviceLocation = characteristic.location;
- mDeviceGroup = characteristic.group;
- mIndexInTheGroup = characteristic.index_in_the_group;
- mGeometricLocation.push_back(characteristic.geometric_location.x);
- mGeometricLocation.push_back(characteristic.geometric_location.y);
- mGeometricLocation.push_back(characteristic.geometric_location.z);
- mOrientation.push_back(characteristic.orientation.x);
- mOrientation.push_back(characteristic.orientation.y);
- mOrientation.push_back(characteristic.orientation.z);
- std::vector<float> frequencies;
- std::vector<float> responses;
- for (size_t i = 0; i < characteristic.num_frequency_responses; i++) {
- frequencies.push_back(characteristic.frequency_responses[0][i]);
- responses.push_back(characteristic.frequency_responses[1][i]);
- }
- mFrequencyResponses.push_back(frequencies);
- mFrequencyResponses.push_back(responses);
- for (size_t i = 0; i < AUDIO_CHANNEL_COUNT_MAX; i++) {
- mChannelMapping.push_back(characteristic.channel_mapping[i]);
- }
- mSensitivity = characteristic.sensitivity;
- mMaxSpl = characteristic.max_spl;
- mMinSpl = characteristic.min_spl;
- mDirectionality = characteristic.directionality;
- }
-
- virtual ~MicrophoneInfo() = default;
-
- virtual status_t writeToParcel(Parcel* parcel) const {
- MicrophoneInfoData parcelable;
- return writeToParcelable(&parcelable)
- ?: parcelable.writeToParcel(parcel);
- }
-
- virtual status_t writeToParcelable(MicrophoneInfoData* parcelable) const {
- parcelable->deviceId = mDeviceId;
- parcelable->portId = mPortId;
- parcelable->type = VALUE_OR_RETURN_STATUS(convertReinterpret<int32_t>(mType));
- parcelable->address = mAddress;
- parcelable->deviceGroup = mDeviceGroup;
- parcelable->indexInTheGroup = mIndexInTheGroup;
- parcelable->geometricLocation = mGeometricLocation;
- parcelable->orientation = mOrientation;
- if (mFrequencyResponses.size() != 2) {
- return BAD_VALUE;
- }
- parcelable->frequencies = mFrequencyResponses[0];
- parcelable->frequencyResponses = mFrequencyResponses[1];
- parcelable->channelMapping = mChannelMapping;
- parcelable->sensitivity = mSensitivity;
- parcelable->maxSpl = mMaxSpl;
- parcelable->minSpl = mMinSpl;
- parcelable->directionality = mDirectionality;
- return OK;
- }
-
- virtual status_t readFromParcel(const Parcel* parcel) {
- MicrophoneInfoData data;
- return data.readFromParcel(parcel)
- ?: readFromParcelable(data);
- }
-
- virtual status_t readFromParcelable(const MicrophoneInfoData& parcelable) {
- mDeviceId = parcelable.deviceId;
- mPortId = parcelable.portId;
- mType = VALUE_OR_RETURN_STATUS(convertReinterpret<uint32_t>(parcelable.type));
- mAddress = parcelable.address;
- mDeviceLocation = parcelable.deviceLocation;
- mDeviceGroup = parcelable.deviceGroup;
- mIndexInTheGroup = parcelable.indexInTheGroup;
- if (parcelable.geometricLocation.size() != 3) {
- return BAD_VALUE;
- }
- mGeometricLocation = parcelable.geometricLocation;
- if (parcelable.orientation.size() != 3) {
- return BAD_VALUE;
- }
- mOrientation = parcelable.orientation;
- if (parcelable.frequencies.size() != parcelable.frequencyResponses.size()) {
- return BAD_VALUE;
- }
-
- mFrequencyResponses.push_back(parcelable.frequencies);
- mFrequencyResponses.push_back(parcelable.frequencyResponses);
- if (parcelable.channelMapping.size() != AUDIO_CHANNEL_COUNT_MAX) {
- return BAD_VALUE;
- }
- mChannelMapping = parcelable.channelMapping;
- mSensitivity = parcelable.sensitivity;
- mMaxSpl = parcelable.maxSpl;
- mMinSpl = parcelable.minSpl;
- mDirectionality = parcelable.directionality;
- return OK;
- }
-
- std::string getDeviceId() const {
- return mDeviceId;
- }
-
- int getPortId() const {
- return mPortId;
- }
-
- unsigned int getType() const {
- return mType;
- }
-
- std::string getAddress() const {
- return mAddress;
- }
-
- int getDeviceLocation() const {
- return mDeviceLocation;
- }
-
- int getDeviceGroup() const {
- return mDeviceGroup;
- }
-
- int getIndexInTheGroup() const {
- return mIndexInTheGroup;
- }
-
- const std::vector<float>& getGeometricLocation() const {
- return mGeometricLocation;
- }
-
- const std::vector<float>& getOrientation() const {
- return mOrientation;
- }
-
- const std::vector<std::vector<float>>& getFrequencyResponses() const {
- return mFrequencyResponses;
- }
-
- const std::vector<int>& getChannelMapping() const {
- return mChannelMapping;
- }
-
- float getSensitivity() const {
- return mSensitivity;
- }
-
- float getMaxSpl() const {
- return mMaxSpl;
- }
-
- float getMinSpl() const {
- return mMinSpl;
- }
-
- int getDirectionality() const {
- return mDirectionality;
- }
-
-private:
- std::string mDeviceId;
- int32_t mPortId;
- uint32_t mType;
- std::string mAddress;
- int32_t mDeviceLocation;
- int32_t mDeviceGroup;
- int32_t mIndexInTheGroup;
- std::vector<float> mGeometricLocation;
- std::vector<float> mOrientation;
- std::vector<std::vector<float>> mFrequencyResponses;
- std::vector<int> mChannelMapping;
- float mSensitivity;
- float mMaxSpl;
- float mMinSpl;
- int32_t mDirectionality;
-};
-
-// Conversion routines, according to AidlConversion.h conventions.
-inline ConversionResult<MicrophoneInfo>
-aidl2legacy_MicrophoneInfo(const media::MicrophoneInfoData& aidl) {
- MicrophoneInfo legacy;
- RETURN_IF_ERROR(legacy.readFromParcelable(aidl));
- return legacy;
-}
-
-inline ConversionResult<media::MicrophoneInfoData>
-legacy2aidl_MicrophoneInfo(const MicrophoneInfo& legacy) {
- media::MicrophoneInfoData aidl;
- RETURN_IF_ERROR(legacy.writeToParcelable(&aidl));
- return aidl;
-}
-
-} // namespace media
-} // namespace android
-
-#endif
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
index 048301f..9aa896c 100644
--- a/media/TEST_MAPPING
+++ b/media/TEST_MAPPING
@@ -1,7 +1,24 @@
// for frameworks/av/media
{
- // TODO (b/229286407) Add EncodeDecodeTest and DecodeEditEncodeTest to
- // presubmit-large once issues in cuttlefish are fixed
+ "presubmit-large": [
+ // runs whenever we change something in this tree
+ {
+ "name": "CtsMediaCodecTestCases",
+ "options": [
+ {
+ "include-filter": "android.media.codec.cts.EncodeDecodeTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsMediaCodecTestCases",
+ "options": [
+ {
+ "include-filter": "android.media.codec.cts.DecodeEditEncodeTest"
+ }
+ ]
+ }
+ ],
"presubmit": [
{
"name": "GtsMediaTestCases",
@@ -15,13 +32,17 @@
{
"include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
}
- ]
- }
- ],
-
- "imports": [
+ ],
+ "file_patterns": ["(?i)drm|crypto"]
+ },
{
- "path": "frameworks/av/drm/mediadrm/plugins"
+ "name": "CtsMediaDrmFrameworkTestCases",
+ "options" : [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ }
+ ],
+ "file_patterns": ["(?i)drm|crypto"]
}
],
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
new file mode 100644
index 0000000..8c2b940
--- /dev/null
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -0,0 +1,3014 @@
+/*
+ * Copyright (C) 2022 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 <algorithm>
+#include <map>
+#include <utility>
+#include <vector>
+
+#define LOG_TAG "AidlConversionCppNdk"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "media/AidlConversionCppNdk.h"
+
+#include <media/ShmemCompat.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// AIDL CPP/NDK backend to legacy audio data structure conversion utilities.
+
+#if defined(BACKEND_NDK)
+/* AIDL String generated in NDK is different than CPP */
+#define GET_DEVICE_DESC_CONNECTION(x) AudioDeviceDescription::CONNECTION_##x
+namespace aidl {
+#else
+#define GET_DEVICE_DESC_CONNECTION(x) AudioDeviceDescription::CONNECTION_##x()
+#endif
+
+namespace android {
+
+using ::android::BAD_VALUE;
+using ::android::OK;
+using ::android::String16;
+using ::android::String8;
+using ::android::status_t;
+using ::android::base::unexpected;
+
+using media::audio::common::AudioChannelLayout;
+using media::audio::common::AudioConfig;
+using media::audio::common::AudioConfigBase;
+using media::audio::common::AudioContentType;
+using media::audio::common::AudioDevice;
+using media::audio::common::AudioDeviceAddress;
+using media::audio::common::AudioDeviceDescription;
+using media::audio::common::AudioDeviceType;
+using media::audio::common::AudioDualMonoMode;
+using media::audio::common::AudioEncapsulationMetadataType;
+using media::audio::common::AudioEncapsulationMode;
+using media::audio::common::AudioEncapsulationType;
+using media::audio::common::AudioFormatDescription;
+using media::audio::common::AudioFormatType;
+using media::audio::common::AudioGain;
+using media::audio::common::AudioGainConfig;
+using media::audio::common::AudioGainMode;
+using media::audio::common::AudioInputFlags;
+using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioLatencyMode;
+using media::audio::common::AudioMode;
+using media::audio::common::AudioOffloadInfo;
+using media::audio::common::AudioOutputFlags;
+using media::audio::common::AudioPlaybackRate;
+using media::audio::common::AudioPort;
+using media::audio::common::AudioPortConfig;
+using media::audio::common::AudioPortDeviceExt;
+using media::audio::common::AudioPortExt;
+using media::audio::common::AudioPortMixExt;
+using media::audio::common::AudioPortMixExtUseCase;
+using media::audio::common::AudioProfile;
+using media::audio::common::AudioSource;
+using media::audio::common::AudioStandard;
+using media::audio::common::AudioStreamType;
+using media::audio::common::AudioUsage;
+using media::audio::common::AudioUuid;
+using media::audio::common::ExtraAudioDescriptor;
+using media::audio::common::Int;
+using media::audio::common::MicrophoneDynamicInfo;
+using media::audio::common::MicrophoneInfo;
+using media::audio::common::PcmType;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Converters
+
+::android::status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize) {
+ if (aidl.size() > maxSize - 1) {
+ return BAD_VALUE;
+ }
+ aidl.copy(dest, aidl.size());
+ dest[aidl.size()] = '\0';
+ return OK;
+}
+
+ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize) {
+ if (legacy == nullptr) {
+ return unexpected(BAD_VALUE);
+ }
+ if (strnlen(legacy, maxSize) == maxSize) {
+ // No null-terminator.
+ return unexpected(BAD_VALUE);
+ }
+ return std::string(legacy);
+}
+
+ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl) {
+ return convertReinterpret<audio_module_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl) {
+ return convertReinterpret<audio_io_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl) {
+ return convertReinterpret<audio_port_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl) {
+ return convertReinterpret<audio_patch_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl) {
+ return convertReinterpret<audio_unique_id_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl) {
+ return convertReinterpret<audio_hw_sync_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl) {
+ return convertReinterpret<pid_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl) {
+ return convertReinterpret<uid_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl) {
+ return String16(aidl.data(), aidl.size());
+}
+
+ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy) {
+ return std::string(String8(legacy).c_str());
+}
+
+// TODO b/182392769: create an optional -> optional util
+ConversionResult<std::optional<String16>>
+aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl) {
+ if (!aidl.has_value()) {
+ return std::nullopt;
+ }
+ ConversionResult<String16> conversion =
+ VALUE_OR_RETURN(aidl2legacy_string_view_String16(aidl.value()));
+ return conversion.value();
+}
+
+ConversionResult<std::optional<std::string_view>>
+legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy) {
+ if (!legacy.has_value()) {
+ return std::nullopt;
+ }
+ ConversionResult<std::string> conversion =
+ VALUE_OR_RETURN(legacy2aidl_String16_string(legacy.value()));
+ return conversion.value();
+}
+
+ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl) {
+ return String8(aidl.data(), aidl.size());
+}
+
+ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy) {
+ return std::string(legacy.c_str());
+}
+
+namespace {
+
+namespace detail {
+using AudioChannelBitPair = std::pair<audio_channel_mask_t, int>;
+using AudioChannelBitPairs = std::vector<AudioChannelBitPair>;
+using AudioChannelPair = std::pair<audio_channel_mask_t, AudioChannelLayout>;
+using AudioChannelPairs = std::vector<AudioChannelPair>;
+using AudioDevicePair = std::pair<audio_devices_t, AudioDeviceDescription>;
+using AudioDevicePairs = std::vector<AudioDevicePair>;
+using AudioFormatPair = std::pair<audio_format_t, AudioFormatDescription>;
+using AudioFormatPairs = std::vector<AudioFormatPair>;
+}
+
+const detail::AudioChannelBitPairs& getInAudioChannelBits() {
+ static const detail::AudioChannelBitPairs pairs = {
+ { AUDIO_CHANNEL_IN_LEFT, AudioChannelLayout::CHANNEL_FRONT_LEFT },
+ { AUDIO_CHANNEL_IN_RIGHT, AudioChannelLayout::CHANNEL_FRONT_RIGHT },
+ // AUDIO_CHANNEL_IN_FRONT is at the end
+ { AUDIO_CHANNEL_IN_BACK, AudioChannelLayout::CHANNEL_BACK_CENTER },
+ // AUDIO_CHANNEL_IN_*_PROCESSED not supported
+ // AUDIO_CHANNEL_IN_PRESSURE not supported
+ // AUDIO_CHANNEL_IN_*_AXIS not supported
+ // AUDIO_CHANNEL_IN_VOICE_* not supported
+ { AUDIO_CHANNEL_IN_BACK_LEFT, AudioChannelLayout::CHANNEL_BACK_LEFT },
+ { AUDIO_CHANNEL_IN_BACK_RIGHT, AudioChannelLayout::CHANNEL_BACK_RIGHT },
+ { AUDIO_CHANNEL_IN_CENTER, AudioChannelLayout::CHANNEL_FRONT_CENTER },
+ { AUDIO_CHANNEL_IN_LOW_FREQUENCY, AudioChannelLayout::CHANNEL_LOW_FREQUENCY },
+ { AUDIO_CHANNEL_IN_TOP_LEFT, AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT },
+ { AUDIO_CHANNEL_IN_TOP_RIGHT, AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT },
+ // When going from aidl to legacy, IN_CENTER is used
+ { AUDIO_CHANNEL_IN_FRONT, AudioChannelLayout::CHANNEL_FRONT_CENTER }
+ };
+ return pairs;
+}
+
+const detail::AudioChannelPairs& getInAudioChannelPairs() {
+ static const detail::AudioChannelPairs pairs = {
+#define DEFINE_INPUT_LAYOUT(n) \
+ { \
+ AUDIO_CHANNEL_IN_##n, \
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
+ AudioChannelLayout::LAYOUT_##n) \
+ }
+
+ DEFINE_INPUT_LAYOUT(MONO),
+ DEFINE_INPUT_LAYOUT(STEREO),
+ DEFINE_INPUT_LAYOUT(FRONT_BACK),
+ // AUDIO_CHANNEL_IN_6 not supported
+ DEFINE_INPUT_LAYOUT(2POINT0POINT2),
+ DEFINE_INPUT_LAYOUT(2POINT1POINT2),
+ DEFINE_INPUT_LAYOUT(3POINT0POINT2),
+ DEFINE_INPUT_LAYOUT(3POINT1POINT2),
+ DEFINE_INPUT_LAYOUT(5POINT1)
+#undef DEFINE_INPUT_LAYOUT
+ };
+ return pairs;
+}
+
+const detail::AudioChannelBitPairs& getOutAudioChannelBits() {
+ static const detail::AudioChannelBitPairs pairs = {
+#define DEFINE_OUTPUT_BITS(n) \
+ { AUDIO_CHANNEL_OUT_##n, AudioChannelLayout::CHANNEL_##n }
+
+ DEFINE_OUTPUT_BITS(FRONT_LEFT),
+ DEFINE_OUTPUT_BITS(FRONT_RIGHT),
+ DEFINE_OUTPUT_BITS(FRONT_CENTER),
+ DEFINE_OUTPUT_BITS(LOW_FREQUENCY),
+ DEFINE_OUTPUT_BITS(BACK_LEFT),
+ DEFINE_OUTPUT_BITS(BACK_RIGHT),
+ DEFINE_OUTPUT_BITS(FRONT_LEFT_OF_CENTER),
+ DEFINE_OUTPUT_BITS(FRONT_RIGHT_OF_CENTER),
+ DEFINE_OUTPUT_BITS(BACK_CENTER),
+ DEFINE_OUTPUT_BITS(SIDE_LEFT),
+ DEFINE_OUTPUT_BITS(SIDE_RIGHT),
+ DEFINE_OUTPUT_BITS(TOP_CENTER),
+ DEFINE_OUTPUT_BITS(TOP_FRONT_LEFT),
+ DEFINE_OUTPUT_BITS(TOP_FRONT_CENTER),
+ DEFINE_OUTPUT_BITS(TOP_FRONT_RIGHT),
+ DEFINE_OUTPUT_BITS(TOP_BACK_LEFT),
+ DEFINE_OUTPUT_BITS(TOP_BACK_CENTER),
+ DEFINE_OUTPUT_BITS(TOP_BACK_RIGHT),
+ DEFINE_OUTPUT_BITS(TOP_SIDE_LEFT),
+ DEFINE_OUTPUT_BITS(TOP_SIDE_RIGHT),
+ DEFINE_OUTPUT_BITS(BOTTOM_FRONT_LEFT),
+ DEFINE_OUTPUT_BITS(BOTTOM_FRONT_CENTER),
+ DEFINE_OUTPUT_BITS(BOTTOM_FRONT_RIGHT),
+ DEFINE_OUTPUT_BITS(LOW_FREQUENCY_2),
+ DEFINE_OUTPUT_BITS(FRONT_WIDE_LEFT),
+ DEFINE_OUTPUT_BITS(FRONT_WIDE_RIGHT),
+#undef DEFINE_OUTPUT_BITS
+ { AUDIO_CHANNEL_OUT_HAPTIC_A, AudioChannelLayout::CHANNEL_HAPTIC_A },
+ { AUDIO_CHANNEL_OUT_HAPTIC_B, AudioChannelLayout::CHANNEL_HAPTIC_B }
+ };
+ return pairs;
+}
+
+const detail::AudioChannelPairs& getOutAudioChannelPairs() {
+ static const detail::AudioChannelPairs pairs = {
+#define DEFINE_OUTPUT_LAYOUT(n) \
+ { \
+ AUDIO_CHANNEL_OUT_##n, \
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
+ AudioChannelLayout::LAYOUT_##n) \
+ }
+
+ DEFINE_OUTPUT_LAYOUT(MONO),
+ DEFINE_OUTPUT_LAYOUT(STEREO),
+ DEFINE_OUTPUT_LAYOUT(2POINT1),
+ DEFINE_OUTPUT_LAYOUT(TRI),
+ DEFINE_OUTPUT_LAYOUT(TRI_BACK),
+ DEFINE_OUTPUT_LAYOUT(3POINT1),
+ DEFINE_OUTPUT_LAYOUT(2POINT0POINT2),
+ DEFINE_OUTPUT_LAYOUT(2POINT1POINT2),
+ DEFINE_OUTPUT_LAYOUT(3POINT0POINT2),
+ DEFINE_OUTPUT_LAYOUT(3POINT1POINT2),
+ DEFINE_OUTPUT_LAYOUT(QUAD),
+ DEFINE_OUTPUT_LAYOUT(QUAD_SIDE),
+ DEFINE_OUTPUT_LAYOUT(SURROUND),
+ DEFINE_OUTPUT_LAYOUT(PENTA),
+ DEFINE_OUTPUT_LAYOUT(5POINT1),
+ DEFINE_OUTPUT_LAYOUT(5POINT1_SIDE),
+ DEFINE_OUTPUT_LAYOUT(5POINT1POINT2),
+ DEFINE_OUTPUT_LAYOUT(5POINT1POINT4),
+ DEFINE_OUTPUT_LAYOUT(6POINT1),
+ DEFINE_OUTPUT_LAYOUT(7POINT1),
+ DEFINE_OUTPUT_LAYOUT(7POINT1POINT2),
+ DEFINE_OUTPUT_LAYOUT(7POINT1POINT4),
+ DEFINE_OUTPUT_LAYOUT(13POINT_360RA),
+ DEFINE_OUTPUT_LAYOUT(22POINT2),
+ DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_A),
+ DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_A),
+ DEFINE_OUTPUT_LAYOUT(HAPTIC_AB),
+ DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_AB),
+ DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_AB)
+#undef DEFINE_OUTPUT_LAYOUT
+ };
+ return pairs;
+}
+
+const detail::AudioChannelPairs& getVoiceAudioChannelPairs() {
+ static const detail::AudioChannelPairs pairs = {
+#define DEFINE_VOICE_LAYOUT(n) \
+ { \
+ AUDIO_CHANNEL_IN_VOICE_##n, \
+ AudioChannelLayout::make<AudioChannelLayout::Tag::voiceMask>( \
+ AudioChannelLayout::VOICE_##n) \
+ }
+ DEFINE_VOICE_LAYOUT(UPLINK_MONO),
+ DEFINE_VOICE_LAYOUT(DNLINK_MONO),
+ DEFINE_VOICE_LAYOUT(CALL_MONO)
+#undef DEFINE_VOICE_LAYOUT
+ };
+ return pairs;
+}
+
+AudioDeviceDescription make_AudioDeviceDescription(AudioDeviceType type,
+ const std::string& connection = "") {
+ AudioDeviceDescription result;
+ result.type = type;
+ result.connection = connection;
+ return result;
+}
+
+void append_AudioDeviceDescription(detail::AudioDevicePairs& pairs,
+ audio_devices_t inputType, audio_devices_t outputType,
+ AudioDeviceType inType, AudioDeviceType outType,
+ const std::string& connection = "") {
+ pairs.push_back(std::make_pair(inputType, make_AudioDeviceDescription(inType, connection)));
+ pairs.push_back(std::make_pair(outputType, make_AudioDeviceDescription(outType, connection)));
+}
+
+const detail::AudioDevicePairs& getAudioDevicePairs() {
+ static const detail::AudioDevicePairs pairs = []() {
+ detail::AudioDevicePairs pairs = {{
+ {
+ AUDIO_DEVICE_NONE, AudioDeviceDescription{}
+ },
+ {
+ AUDIO_DEVICE_OUT_EARPIECE, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_SPEAKER_EARPIECE)
+ },
+ {
+ AUDIO_DEVICE_OUT_SPEAKER, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_SPEAKER)
+ },
+ {
+ AUDIO_DEVICE_OUT_WIRED_HEADPHONE, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_HEADPHONE,
+ GET_DEVICE_DESC_CONNECTION(ANALOG))
+ },
+ {
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(BT_SCO))
+ },
+ {
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_CARKIT,
+ GET_DEVICE_DESC_CONNECTION(BT_SCO))
+ },
+ {
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_HEADPHONE,
+ GET_DEVICE_DESC_CONNECTION(BT_A2DP))
+ },
+ {
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_SPEAKER,
+ GET_DEVICE_DESC_CONNECTION(BT_A2DP))
+ },
+ {
+ AUDIO_DEVICE_OUT_TELEPHONY_TX, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_TELEPHONY_TX)
+ },
+ {
+ AUDIO_DEVICE_OUT_AUX_LINE, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_LINE_AUX)
+ },
+ {
+ AUDIO_DEVICE_OUT_SPEAKER_SAFE, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_SPEAKER_SAFE)
+ },
+ {
+ AUDIO_DEVICE_OUT_HEARING_AID, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_HEARING_AID,
+ GET_DEVICE_DESC_CONNECTION(WIRELESS))
+ },
+ {
+ AUDIO_DEVICE_OUT_ECHO_CANCELLER, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_ECHO_CANCELLER)
+ },
+ {
+ AUDIO_DEVICE_OUT_BLE_SPEAKER, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_SPEAKER,
+ GET_DEVICE_DESC_CONNECTION(BT_LE))
+ },
+ {
+ AUDIO_DEVICE_OUT_BLE_BROADCAST, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_BROADCAST,
+ GET_DEVICE_DESC_CONNECTION(BT_LE))
+ },
+ // AUDIO_DEVICE_IN_AMBIENT and IN_COMMUNICATION are removed since they were deprecated.
+ {
+ AUDIO_DEVICE_IN_BUILTIN_MIC, make_AudioDeviceDescription(
+ AudioDeviceType::IN_MICROPHONE)
+ },
+ {
+ AUDIO_DEVICE_IN_BACK_MIC, make_AudioDeviceDescription(
+ AudioDeviceType::IN_MICROPHONE_BACK)
+ },
+ {
+ AUDIO_DEVICE_IN_TELEPHONY_RX, make_AudioDeviceDescription(
+ AudioDeviceType::IN_TELEPHONY_RX)
+ },
+ {
+ AUDIO_DEVICE_IN_TV_TUNER, make_AudioDeviceDescription(
+ AudioDeviceType::IN_TV_TUNER)
+ },
+ {
+ AUDIO_DEVICE_IN_LOOPBACK, make_AudioDeviceDescription(
+ AudioDeviceType::IN_LOOPBACK)
+ },
+ {
+ AUDIO_DEVICE_IN_BLUETOOTH_BLE, make_AudioDeviceDescription(
+ AudioDeviceType::IN_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(BT_LE))
+ },
+ {
+ AUDIO_DEVICE_IN_ECHO_REFERENCE, make_AudioDeviceDescription(
+ AudioDeviceType::IN_ECHO_REFERENCE)
+ },
+ {
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, make_AudioDeviceDescription(
+ AudioDeviceType::IN_SUBMIX)
+ },
+ {
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_SUBMIX,
+ GET_DEVICE_DESC_CONNECTION(VIRTUAL))
+ }
+ }};
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT,
+ AudioDeviceType::IN_DEFAULT, AudioDeviceType::OUT_DEFAULT);
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET,
+ AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+ GET_DEVICE_DESC_CONNECTION(ANALOG));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
+ AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+ GET_DEVICE_DESC_CONNECTION(BT_SCO));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_HDMI, AUDIO_DEVICE_OUT_HDMI,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(HDMI));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET,
+ AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
+ GET_DEVICE_DESC_CONNECTION(ANALOG));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
+ AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
+ GET_DEVICE_DESC_CONNECTION(USB));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_ACCESSORY,
+ AudioDeviceType::IN_ACCESSORY, AudioDeviceType::OUT_ACCESSORY,
+ GET_DEVICE_DESC_CONNECTION(USB));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_OUT_USB_DEVICE,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(USB));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_FM_TUNER, AUDIO_DEVICE_OUT_FM,
+ AudioDeviceType::IN_FM_TUNER, AudioDeviceType::OUT_FM);
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_LINE, AUDIO_DEVICE_OUT_LINE,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(ANALOG));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_SPDIF, AUDIO_DEVICE_OUT_SPDIF,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(SPDIF));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(BT_A2DP));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_IP, AUDIO_DEVICE_OUT_IP,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(IP_V4));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_BUS, AUDIO_DEVICE_OUT_BUS,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(BUS));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_PROXY, AUDIO_DEVICE_OUT_PROXY,
+ AudioDeviceType::IN_AFE_PROXY, AudioDeviceType::OUT_AFE_PROXY);
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
+ AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+ GET_DEVICE_DESC_CONNECTION(USB));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_HDMI_ARC, AUDIO_DEVICE_OUT_HDMI_ARC,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(HDMI_ARC));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_HDMI_EARC, AUDIO_DEVICE_OUT_HDMI_EARC,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(HDMI_EARC));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_OUT_BLE_HEADSET,
+ AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+ GET_DEVICE_DESC_CONNECTION(BT_LE));
+ return pairs;
+ }();
+#undef GET_DEVICE_DESC_CONNECTION
+ return pairs;
+}
+
+AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
+ AudioFormatDescription result;
+ result.type = type;
+ return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
+ auto result = make_AudioFormatDescription(AudioFormatType::PCM);
+ result.pcm = pcm;
+ return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(const std::string& encoding) {
+ AudioFormatDescription result;
+ result.encoding = encoding;
+ return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType transport,
+ const std::string& encoding) {
+ auto result = make_AudioFormatDescription(encoding);
+ result.pcm = transport;
+ return result;
+}
+
+const detail::AudioFormatPairs& getAudioFormatPairs() {
+ static const detail::AudioFormatPairs pairs = {{
+ {AUDIO_FORMAT_INVALID,
+ make_AudioFormatDescription(AudioFormatType::SYS_RESERVED_INVALID)},
+ {AUDIO_FORMAT_DEFAULT, AudioFormatDescription{}},
+ {AUDIO_FORMAT_PCM_16_BIT, make_AudioFormatDescription(PcmType::INT_16_BIT)},
+ {AUDIO_FORMAT_PCM_8_BIT, make_AudioFormatDescription(PcmType::UINT_8_BIT)},
+ {AUDIO_FORMAT_PCM_32_BIT, make_AudioFormatDescription(PcmType::INT_32_BIT)},
+ {AUDIO_FORMAT_PCM_8_24_BIT, make_AudioFormatDescription(PcmType::FIXED_Q_8_24)},
+ {AUDIO_FORMAT_PCM_FLOAT, make_AudioFormatDescription(PcmType::FLOAT_32_BIT)},
+ {AUDIO_FORMAT_PCM_24_BIT_PACKED, make_AudioFormatDescription(PcmType::INT_24_BIT)},
+ {AUDIO_FORMAT_MP3, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEG)},
+ {AUDIO_FORMAT_AMR_NB,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AMR_NB)},
+ {AUDIO_FORMAT_AMR_WB,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AMR_WB)},
+ {AUDIO_FORMAT_AAC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_MP4)},
+ {AUDIO_FORMAT_AAC_MAIN,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_MAIN)},
+ {AUDIO_FORMAT_AAC_LC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LC)},
+ {AUDIO_FORMAT_AAC_SSR,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_SSR)},
+ {AUDIO_FORMAT_AAC_LTP,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LTP)},
+ {AUDIO_FORMAT_AAC_HE_V1,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_HE_V1)},
+ {AUDIO_FORMAT_AAC_SCALABLE,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_SCALABLE)},
+ {AUDIO_FORMAT_AAC_ERLC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ERLC)},
+ {AUDIO_FORMAT_AAC_LD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LD)},
+ {AUDIO_FORMAT_AAC_HE_V2,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_HE_V2)},
+ {AUDIO_FORMAT_AAC_ELD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ELD)},
+ {AUDIO_FORMAT_AAC_XHE,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_XHE)
+
+ },
+ // AUDIO_FORMAT_HE_AAC_V1 and HE_AAC_V2 are removed since they were deprecated long time
+ // ago.
+ {AUDIO_FORMAT_VORBIS,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_VORBIS)},
+ {AUDIO_FORMAT_OPUS, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_OPUS)},
+ {AUDIO_FORMAT_AC3, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AC3)},
+ {AUDIO_FORMAT_E_AC3, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EAC3)},
+ {AUDIO_FORMAT_E_AC3_JOC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EAC3_JOC)},
+ {AUDIO_FORMAT_DTS, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS)},
+ {AUDIO_FORMAT_DTS_HD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_HD)},
+ {AUDIO_FORMAT_DTS_HD_MA,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_HD_MA)},
+ {AUDIO_FORMAT_DTS_UHD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1)},
+ {AUDIO_FORMAT_DTS_UHD_P2,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2)},
+ // In the future, we would like to represent encapsulated bitstreams as
+ // nested AudioFormatDescriptions. The legacy 'AUDIO_FORMAT_IEC61937' type doesn't
+ // specify the format of the encapsulated bitstream.
+ {AUDIO_FORMAT_IEC61937,
+ make_AudioFormatDescription(PcmType::INT_16_BIT,
+ ::android::MEDIA_MIMETYPE_AUDIO_IEC61937)},
+ {AUDIO_FORMAT_DOLBY_TRUEHD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD)},
+ {AUDIO_FORMAT_EVRC, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRC)},
+ {AUDIO_FORMAT_EVRCB,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRCB)},
+ {AUDIO_FORMAT_EVRCWB,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRCWB)},
+ {AUDIO_FORMAT_EVRCNW,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRCNW)},
+ {AUDIO_FORMAT_AAC_ADIF,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADIF)},
+ {AUDIO_FORMAT_WMA, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_WMA)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_WMA_PRO, make_AudioFormatDescription("audio/x-ms-wma.pro")},
+ {AUDIO_FORMAT_AMR_WB_PLUS,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)},
+ {AUDIO_FORMAT_MP2,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II)},
+ {AUDIO_FORMAT_QCELP,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_QCELP)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_DSD, make_AudioFormatDescription("audio/vnd.sony.dsd")},
+ {AUDIO_FORMAT_FLAC, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_FLAC)},
+ {AUDIO_FORMAT_ALAC, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_ALAC)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_APE, make_AudioFormatDescription("audio/x-ape")},
+ {AUDIO_FORMAT_AAC_ADTS,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS)},
+ {AUDIO_FORMAT_AAC_ADTS_MAIN,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_MAIN)},
+ {AUDIO_FORMAT_AAC_ADTS_LC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LC)},
+ {AUDIO_FORMAT_AAC_ADTS_SSR,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SSR)},
+ {AUDIO_FORMAT_AAC_ADTS_LTP,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LTP)},
+ {AUDIO_FORMAT_AAC_ADTS_HE_V1,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V1)},
+ {AUDIO_FORMAT_AAC_ADTS_SCALABLE,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SCALABLE)},
+ {AUDIO_FORMAT_AAC_ADTS_ERLC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ERLC)},
+ {AUDIO_FORMAT_AAC_ADTS_LD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LD)},
+ {AUDIO_FORMAT_AAC_ADTS_HE_V2,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V2)},
+ {AUDIO_FORMAT_AAC_ADTS_ELD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ELD)},
+ {AUDIO_FORMAT_AAC_ADTS_XHE,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_XHE)},
+ {// Note: not in the IANA registry. "vnd.octel.sbc" is not BT SBC.
+ AUDIO_FORMAT_SBC, make_AudioFormatDescription("audio/x-sbc")},
+ {AUDIO_FORMAT_APTX, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_APTX)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_APTX_HD, make_AudioFormatDescription("audio/vnd.qcom.aptx.hd")},
+ {AUDIO_FORMAT_AC4, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AC4)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_LDAC, make_AudioFormatDescription("audio/vnd.sony.ldac")},
+ {AUDIO_FORMAT_MAT,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_MAT_1_0,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT +
+ std::string(".1.0"))},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_MAT_2_0,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT +
+ std::string(".2.0"))},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_MAT_2_1,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT +
+ std::string(".2.1"))},
+ {AUDIO_FORMAT_AAC_LATM,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC)},
+ {AUDIO_FORMAT_AAC_LATM_LC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LATM_LC)},
+ {AUDIO_FORMAT_AAC_LATM_HE_V1,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V1)},
+ {AUDIO_FORMAT_AAC_LATM_HE_V2,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V2)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_CELT, make_AudioFormatDescription("audio/x-celt")},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_APTX_ADAPTIVE,
+ make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive")},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_LHDC, make_AudioFormatDescription("audio/vnd.savitech.lhdc")},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_LHDC_LL, make_AudioFormatDescription("audio/vnd.savitech.lhdc.ll")},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_APTX_TWSP, make_AudioFormatDescription("audio/vnd.qcom.aptx.twsp")},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_LC3, make_AudioFormatDescription("audio/x-lc3")},
+ {AUDIO_FORMAT_MPEGH,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1)},
+ {AUDIO_FORMAT_MPEGH_BL_L3,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L3)},
+ {AUDIO_FORMAT_MPEGH_BL_L4,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L4)},
+ {AUDIO_FORMAT_MPEGH_LC_L3,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L3)},
+ {AUDIO_FORMAT_MPEGH_LC_L4,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L4)},
+ {AUDIO_FORMAT_IEC60958,
+ make_AudioFormatDescription(PcmType::INT_24_BIT,
+ ::android::MEDIA_MIMETYPE_AUDIO_IEC60958)},
+ {AUDIO_FORMAT_DRA, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DRA)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_APTX_ADAPTIVE_QLEA,
+ make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive.r3")},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_APTX_ADAPTIVE_R4,
+ make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive.r4")},
+ }};
+ return pairs;
+}
+
+template<typename S, typename T>
+std::map<S, T> make_DirectMap(const std::vector<std::pair<S, T>>& v) {
+ std::map<S, T> result(v.begin(), v.end());
+ LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
+ return result;
+}
+
+template<typename S, typename T>
+std::map<S, T> make_DirectMap(
+ const std::vector<std::pair<S, T>>& v1, const std::vector<std::pair<S, T>>& v2) {
+ std::map<S, T> result(v1.begin(), v1.end());
+ LOG_ALWAYS_FATAL_IF(result.size() != v1.size(), "Duplicate key elements detected in v1");
+ result.insert(v2.begin(), v2.end());
+ LOG_ALWAYS_FATAL_IF(result.size() != v1.size() + v2.size(),
+ "Duplicate key elements detected in v1+v2");
+ return result;
+}
+
+template<typename S, typename T>
+std::map<T, S> make_ReverseMap(const std::vector<std::pair<S, T>>& v) {
+ std::map<T, S> result;
+ std::transform(v.begin(), v.end(), std::inserter(result, result.begin()),
+ [](const std::pair<S, T>& p) {
+ return std::make_pair(p.second, p.first);
+ });
+ LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
+ return result;
+}
+
+} // namespace
+
+audio_channel_mask_t aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+ int aidlLayout, bool isInput) {
+ auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
+ const int aidlLayoutInitial = aidlLayout; // for error message
+ audio_channel_mask_t legacy = AUDIO_CHANNEL_NONE;
+ for (const auto& bitPair : bitMapping) {
+ if ((aidlLayout & bitPair.second) == bitPair.second) {
+ legacy = static_cast<audio_channel_mask_t>(legacy | bitPair.first);
+ aidlLayout &= ~bitPair.second;
+ if (aidlLayout == 0) {
+ return legacy;
+ }
+ }
+ }
+ ALOGE("%s: aidl layout 0x%x contains bits 0x%x that have no match to legacy %s bits",
+ __func__, aidlLayoutInitial, aidlLayout, isInput ? "input" : "output");
+ return AUDIO_CHANNEL_NONE;
+}
+
+ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ const AudioChannelLayout& aidl, bool isInput) {
+ using ReverseMap = std::map<AudioChannelLayout, audio_channel_mask_t>;
+ using Tag = AudioChannelLayout::Tag;
+ static const ReverseMap mIn = make_ReverseMap(getInAudioChannelPairs());
+ static const ReverseMap mOut = make_ReverseMap(getOutAudioChannelPairs());
+ static const ReverseMap mVoice = make_ReverseMap(getVoiceAudioChannelPairs());
+
+ auto convert = [](const AudioChannelLayout& aidl, const ReverseMap& m,
+ const char* func, const char* type) -> ConversionResult<audio_channel_mask_t> {
+ if (auto it = m.find(aidl); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGW("%s: no legacy %s audio_channel_mask_t found for %s", func, type,
+ aidl.toString().c_str());
+ return unexpected(BAD_VALUE);
+ }
+ };
+
+ switch (aidl.getTag()) {
+ case Tag::none:
+ return AUDIO_CHANNEL_NONE;
+ case Tag::invalid:
+ return AUDIO_CHANNEL_INVALID;
+ case Tag::indexMask:
+ // Index masks do not have pre-defined values.
+ if (const int bits = aidl.get<Tag::indexMask>();
+ __builtin_popcount(bits) != 0 &&
+ __builtin_popcount(bits) <= (int)AUDIO_CHANNEL_COUNT_MAX) {
+ return audio_channel_mask_from_representation_and_bits(
+ AUDIO_CHANNEL_REPRESENTATION_INDEX, bits);
+ } else {
+ ALOGE("%s: invalid indexMask value 0x%x in %s",
+ __func__, bits, aidl.toString().c_str());
+ return unexpected(BAD_VALUE);
+ }
+ case Tag::layoutMask:
+ // The fast path is to find a direct match for some known layout mask.
+ if (const auto layoutMatch = convert(aidl, isInput ? mIn : mOut, __func__,
+ isInput ? "input" : "output");
+ layoutMatch.ok()) {
+ return layoutMatch;
+ }
+ // If a match for a predefined layout wasn't found, make a custom one from bits.
+ if (audio_channel_mask_t bitMask =
+ aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+ aidl.get<Tag::layoutMask>(), isInput);
+ bitMask != AUDIO_CHANNEL_NONE) {
+ return bitMask;
+ }
+ return unexpected(BAD_VALUE);
+ case Tag::voiceMask:
+ return convert(aidl, mVoice, __func__, "voice");
+ }
+ ALOGE("%s: unexpected tag value %d", __func__, aidl.getTag());
+ return unexpected(BAD_VALUE);
+}
+
+int legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
+ audio_channel_mask_t legacy, bool isInput) {
+ auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
+ const int legacyInitial = legacy; // for error message
+ int aidlLayout = 0;
+ for (const auto& bitPair : bitMapping) {
+ if ((legacy & bitPair.first) == bitPair.first) {
+ aidlLayout |= bitPair.second;
+ legacy = static_cast<audio_channel_mask_t>(legacy & ~bitPair.first);
+ if (legacy == 0) {
+ return aidlLayout;
+ }
+ }
+ }
+ ALOGE("%s: legacy %s audio_channel_mask_t 0x%x contains unrecognized bits 0x%x",
+ __func__, isInput ? "input" : "output", legacyInitial, legacy);
+ return 0;
+}
+
+ConversionResult<AudioChannelLayout> legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+ audio_channel_mask_t legacy, bool isInput) {
+ using DirectMap = std::map<audio_channel_mask_t, AudioChannelLayout>;
+ using Tag = AudioChannelLayout::Tag;
+ static const DirectMap mInAndVoice = make_DirectMap(
+ getInAudioChannelPairs(), getVoiceAudioChannelPairs());
+ static const DirectMap mOut = make_DirectMap(getOutAudioChannelPairs());
+
+ auto convert = [](const audio_channel_mask_t legacy, const DirectMap& m,
+ const char* func, const char* type) -> ConversionResult<AudioChannelLayout> {
+ if (auto it = m.find(legacy); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGW("%s: no AudioChannelLayout found for legacy %s audio_channel_mask_t value 0x%x",
+ func, type, legacy);
+ return unexpected(BAD_VALUE);
+ }
+ };
+
+ if (legacy == AUDIO_CHANNEL_NONE) {
+ return AudioChannelLayout{};
+ } else if (legacy == AUDIO_CHANNEL_INVALID) {
+ return AudioChannelLayout::make<Tag::invalid>(0);
+ }
+
+ const audio_channel_representation_t repr = audio_channel_mask_get_representation(legacy);
+ if (repr == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+ if (audio_channel_mask_is_valid(legacy)) {
+ const int indexMask = VALUE_OR_RETURN(
+ convertIntegral<int>(audio_channel_mask_get_bits(legacy)));
+ return AudioChannelLayout::make<Tag::indexMask>(indexMask);
+ } else {
+ ALOGE("%s: legacy audio_channel_mask_t value 0x%x is invalid", __func__, legacy);
+ return unexpected(BAD_VALUE);
+ }
+ } else if (repr == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
+ // The fast path is to find a direct match for some known layout mask.
+ if (const auto layoutMatch = convert(legacy, isInput ? mInAndVoice : mOut, __func__,
+ isInput ? "input / voice" : "output");
+ layoutMatch.ok()) {
+ return layoutMatch;
+ }
+ // If a match for a predefined layout wasn't found, make a custom one from bits,
+ // rejecting those with voice channel bits.
+ if (!isInput ||
+ (legacy & (AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK)) == 0) {
+ if (int bitMaskLayout =
+ legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
+ legacy, isInput);
+ bitMaskLayout != 0) {
+ return AudioChannelLayout::make<Tag::layoutMask>(bitMaskLayout);
+ }
+ } else {
+ ALOGE("%s: legacy audio_channel_mask_t value 0x%x contains voice bits",
+ __func__, legacy);
+ }
+ return unexpected(BAD_VALUE);
+ }
+
+ ALOGE("%s: unknown representation %d in audio_channel_mask_t value 0x%x",
+ __func__, repr, legacy);
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
+ const AudioDeviceDescription& aidl) {
+ static const std::map<AudioDeviceDescription, audio_devices_t> m =
+ make_ReverseMap(getAudioDevicePairs());
+ if (auto it = m.find(aidl); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGE("%s: no legacy audio_devices_t found for %s", __func__, aidl.toString().c_str());
+ return unexpected(BAD_VALUE);
+ }
+}
+
+ConversionResult<AudioDeviceDescription> legacy2aidl_audio_devices_t_AudioDeviceDescription(
+ audio_devices_t legacy) {
+ static const std::map<audio_devices_t, AudioDeviceDescription> m =
+ make_DirectMap(getAudioDevicePairs());
+ if (auto it = m.find(legacy); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGE("%s: no AudioDeviceDescription found for legacy audio_devices_t value 0x%x",
+ __func__, legacy);
+ return unexpected(BAD_VALUE);
+ }
+}
+
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+ const AudioDevice& aidl,
+ audio_devices_t* legacyType, char* legacyAddress) {
+ *legacyType = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
+ return aidl2legacy_string(
+ aidl.address.get<AudioDeviceAddress::id>(),
+ legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN);
+}
+
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+ const AudioDevice& aidl,
+ audio_devices_t* legacyType, String8* legacyAddress) {
+ *legacyType = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
+ *legacyAddress = VALUE_OR_RETURN_STATUS(aidl2legacy_string_view_String8(
+ aidl.address.get<AudioDeviceAddress::id>()));
+ return OK;
+}
+
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+ const AudioDevice& aidl,
+ audio_devices_t* legacyType, std::string* legacyAddress) {
+ *legacyType = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
+ *legacyAddress = aidl.address.get<AudioDeviceAddress::id>();
+ return OK;
+}
+
+ConversionResult<AudioDevice> legacy2aidl_audio_device_AudioDevice(
+ audio_devices_t legacyType, const char* legacyAddress) {
+ AudioDevice aidl;
+ aidl.type = VALUE_OR_RETURN(
+ legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
+ const std::string aidl_id = VALUE_OR_RETURN(
+ legacy2aidl_string(legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN));
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
+ return aidl;
+}
+
+ConversionResult<AudioDevice>
+legacy2aidl_audio_device_AudioDevice(
+ audio_devices_t legacyType, const String8& legacyAddress) {
+ AudioDevice aidl;
+ aidl.type = VALUE_OR_RETURN(
+ legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
+ const std::string aidl_id = VALUE_OR_RETURN(
+ legacy2aidl_String8_string(legacyAddress));
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
+ return aidl;
+}
+
+ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
+ const AudioFormatDescription& aidl) {
+ static const std::map<AudioFormatDescription, audio_format_t> m =
+ make_ReverseMap(getAudioFormatPairs());
+ if (auto it = m.find(aidl); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGE("%s: no legacy audio_format_t found for %s", __func__, aidl.toString().c_str());
+ return unexpected(BAD_VALUE);
+ }
+}
+
+ConversionResult<AudioFormatDescription> legacy2aidl_audio_format_t_AudioFormatDescription(
+ audio_format_t legacy) {
+ static const std::map<audio_format_t, AudioFormatDescription> m =
+ make_DirectMap(getAudioFormatPairs());
+ if (auto it = m.find(legacy); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGE("%s: no AudioFormatDescription found for legacy audio_format_t value 0x%x",
+ __func__, legacy);
+ return unexpected(BAD_VALUE);
+ }
+}
+
+ConversionResult<audio_gain_mode_t> aidl2legacy_AudioGainMode_audio_gain_mode_t(
+ AudioGainMode aidl) {
+ switch (aidl) {
+ case AudioGainMode::JOINT:
+ return AUDIO_GAIN_MODE_JOINT;
+ case AudioGainMode::CHANNELS:
+ return AUDIO_GAIN_MODE_CHANNELS;
+ case AudioGainMode::RAMP:
+ return AUDIO_GAIN_MODE_RAMP;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioGainMode> legacy2aidl_audio_gain_mode_t_AudioGainMode(
+ audio_gain_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_GAIN_MODE_JOINT:
+ return AudioGainMode::JOINT;
+ case AUDIO_GAIN_MODE_CHANNELS:
+ return AudioGainMode::CHANNELS;
+ case AUDIO_GAIN_MODE_RAMP:
+ return AudioGainMode::RAMP;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl) {
+ return convertBitmask<audio_gain_mode_t, int32_t, audio_gain_mode_t, AudioGainMode>(
+ aidl, aidl2legacy_AudioGainMode_audio_gain_mode_t,
+ // AudioGainMode is index-based.
+ indexToEnum_index<AudioGainMode>,
+ // AUDIO_GAIN_MODE_* constants are mask-based.
+ enumToMask_bitmask<audio_gain_mode_t, audio_gain_mode_t>);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy) {
+ return convertBitmask<int32_t, audio_gain_mode_t, AudioGainMode, audio_gain_mode_t>(
+ legacy, legacy2aidl_audio_gain_mode_t_AudioGainMode,
+ // AUDIO_GAIN_MODE_* constants are mask-based.
+ indexToEnum_bitmask<audio_gain_mode_t>,
+ // AudioGainMode is index-based.
+ enumToMask_index<int32_t, AudioGainMode>);
+}
+
+ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
+ const AudioGainConfig& aidl, bool isInput) {
+ audio_gain_config legacy;
+ legacy.index = VALUE_OR_RETURN(convertIntegral<int>(aidl.index));
+ legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
+ legacy.channel_mask = VALUE_OR_RETURN(
+ aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
+ const bool isJoint = bitmaskIsSet(aidl.mode, AudioGainMode::JOINT);
+ size_t numValues = isJoint ? 1
+ : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
+ : audio_channel_count_from_out_mask(legacy.channel_mask);
+ if (aidl.values.size() != numValues || aidl.values.size() > std::size(legacy.values)) {
+ return unexpected(BAD_VALUE);
+ }
+ for (size_t i = 0; i < numValues; ++i) {
+ legacy.values[i] = VALUE_OR_RETURN(convertIntegral<int>(aidl.values[i]));
+ }
+ legacy.ramp_duration_ms = VALUE_OR_RETURN(convertIntegral<int>(aidl.rampDurationMs));
+ return legacy;
+}
+
+ConversionResult<AudioGainConfig> legacy2aidl_audio_gain_config_AudioGainConfig(
+ const audio_gain_config& legacy, bool isInput) {
+ AudioGainConfig aidl;
+ aidl.index = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.index));
+ aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
+ aidl.channelMask = VALUE_OR_RETURN(
+ legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+ const bool isJoint = (legacy.mode & AUDIO_GAIN_MODE_JOINT) != 0;
+ size_t numValues = isJoint ? 1
+ : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
+ : audio_channel_count_from_out_mask(legacy.channel_mask);
+ aidl.values.resize(numValues);
+ for (size_t i = 0; i < numValues; ++i) {
+ aidl.values[i] = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.values[i]));
+ }
+ aidl.rampDurationMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.ramp_duration_ms));
+ return aidl;
+}
+
+ConversionResult<audio_input_flags_t> aidl2legacy_AudioInputFlags_audio_input_flags_t(
+ AudioInputFlags aidl) {
+ switch (aidl) {
+ case AudioInputFlags::FAST:
+ return AUDIO_INPUT_FLAG_FAST;
+ case AudioInputFlags::HW_HOTWORD:
+ return AUDIO_INPUT_FLAG_HW_HOTWORD;
+ case AudioInputFlags::RAW:
+ return AUDIO_INPUT_FLAG_RAW;
+ case AudioInputFlags::SYNC:
+ return AUDIO_INPUT_FLAG_SYNC;
+ case AudioInputFlags::MMAP_NOIRQ:
+ return AUDIO_INPUT_FLAG_MMAP_NOIRQ;
+ case AudioInputFlags::VOIP_TX:
+ return AUDIO_INPUT_FLAG_VOIP_TX;
+ case AudioInputFlags::HW_AV_SYNC:
+ return AUDIO_INPUT_FLAG_HW_AV_SYNC;
+ case AudioInputFlags::DIRECT:
+ return AUDIO_INPUT_FLAG_DIRECT;
+ case AudioInputFlags::ULTRASOUND:
+ return AUDIO_INPUT_FLAG_ULTRASOUND;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
+ audio_input_flags_t legacy) {
+ switch (legacy) {
+ case AUDIO_INPUT_FLAG_NONE:
+ break; // shouldn't get here. must be listed -Werror,-Wswitch
+ case AUDIO_INPUT_FLAG_FAST:
+ return AudioInputFlags::FAST;
+ case AUDIO_INPUT_FLAG_HW_HOTWORD:
+ return AudioInputFlags::HW_HOTWORD;
+ case AUDIO_INPUT_FLAG_RAW:
+ return AudioInputFlags::RAW;
+ case AUDIO_INPUT_FLAG_SYNC:
+ return AudioInputFlags::SYNC;
+ case AUDIO_INPUT_FLAG_MMAP_NOIRQ:
+ return AudioInputFlags::MMAP_NOIRQ;
+ case AUDIO_INPUT_FLAG_VOIP_TX:
+ return AudioInputFlags::VOIP_TX;
+ case AUDIO_INPUT_FLAG_HW_AV_SYNC:
+ return AudioInputFlags::HW_AV_SYNC;
+ case AUDIO_INPUT_FLAG_DIRECT:
+ return AudioInputFlags::DIRECT;
+ case AUDIO_INPUT_FLAG_ULTRASOUND:
+ return AudioInputFlags::ULTRASOUND;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
+ AudioOutputFlags aidl) {
+ switch (aidl) {
+ case AudioOutputFlags::DIRECT:
+ return AUDIO_OUTPUT_FLAG_DIRECT;
+ case AudioOutputFlags::PRIMARY:
+ return AUDIO_OUTPUT_FLAG_PRIMARY;
+ case AudioOutputFlags::FAST:
+ return AUDIO_OUTPUT_FLAG_FAST;
+ case AudioOutputFlags::DEEP_BUFFER:
+ return AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+ case AudioOutputFlags::COMPRESS_OFFLOAD:
+ return AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+ case AudioOutputFlags::NON_BLOCKING:
+ return AUDIO_OUTPUT_FLAG_NON_BLOCKING;
+ case AudioOutputFlags::HW_AV_SYNC:
+ return AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
+ case AudioOutputFlags::TTS:
+ return AUDIO_OUTPUT_FLAG_TTS;
+ case AudioOutputFlags::RAW:
+ return AUDIO_OUTPUT_FLAG_RAW;
+ case AudioOutputFlags::SYNC:
+ return AUDIO_OUTPUT_FLAG_SYNC;
+ case AudioOutputFlags::IEC958_NONAUDIO:
+ return AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
+ case AudioOutputFlags::DIRECT_PCM:
+ return AUDIO_OUTPUT_FLAG_DIRECT_PCM;
+ case AudioOutputFlags::MMAP_NOIRQ:
+ return AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+ case AudioOutputFlags::VOIP_RX:
+ return AUDIO_OUTPUT_FLAG_VOIP_RX;
+ case AudioOutputFlags::INCALL_MUSIC:
+ return AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
+ case AudioOutputFlags::GAPLESS_OFFLOAD:
+ return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
+ case AudioOutputFlags::ULTRASOUND:
+ return AUDIO_OUTPUT_FLAG_ULTRASOUND;
+ case AudioOutputFlags::SPATIALIZER:
+ return AUDIO_OUTPUT_FLAG_SPATIALIZER;
+ case AudioOutputFlags::BIT_PERFECT:
+ return AUDIO_OUTPUT_FLAG_BIT_PERFECT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
+ audio_output_flags_t legacy) {
+ switch (legacy) {
+ case AUDIO_OUTPUT_FLAG_NONE:
+ break; // shouldn't get here. must be listed -Werror,-Wswitch
+ case AUDIO_OUTPUT_FLAG_DIRECT:
+ return AudioOutputFlags::DIRECT;
+ case AUDIO_OUTPUT_FLAG_PRIMARY:
+ return AudioOutputFlags::PRIMARY;
+ case AUDIO_OUTPUT_FLAG_FAST:
+ return AudioOutputFlags::FAST;
+ case AUDIO_OUTPUT_FLAG_DEEP_BUFFER:
+ return AudioOutputFlags::DEEP_BUFFER;
+ case AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD:
+ return AudioOutputFlags::COMPRESS_OFFLOAD;
+ case AUDIO_OUTPUT_FLAG_NON_BLOCKING:
+ return AudioOutputFlags::NON_BLOCKING;
+ case AUDIO_OUTPUT_FLAG_HW_AV_SYNC:
+ return AudioOutputFlags::HW_AV_SYNC;
+ case AUDIO_OUTPUT_FLAG_TTS:
+ return AudioOutputFlags::TTS;
+ case AUDIO_OUTPUT_FLAG_RAW:
+ return AudioOutputFlags::RAW;
+ case AUDIO_OUTPUT_FLAG_SYNC:
+ return AudioOutputFlags::SYNC;
+ case AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO:
+ return AudioOutputFlags::IEC958_NONAUDIO;
+ case AUDIO_OUTPUT_FLAG_DIRECT_PCM:
+ return AudioOutputFlags::DIRECT_PCM;
+ case AUDIO_OUTPUT_FLAG_MMAP_NOIRQ:
+ return AudioOutputFlags::MMAP_NOIRQ;
+ case AUDIO_OUTPUT_FLAG_VOIP_RX:
+ return AudioOutputFlags::VOIP_RX;
+ case AUDIO_OUTPUT_FLAG_INCALL_MUSIC:
+ return AudioOutputFlags::INCALL_MUSIC;
+ case AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD:
+ return AudioOutputFlags::GAPLESS_OFFLOAD;
+ case AUDIO_OUTPUT_FLAG_ULTRASOUND:
+ return AudioOutputFlags::ULTRASOUND;
+ case AUDIO_OUTPUT_FLAG_SPATIALIZER:
+ return AudioOutputFlags::SPATIALIZER;
+ case AUDIO_OUTPUT_FLAG_BIT_PERFECT:
+ return AudioOutputFlags::BIT_PERFECT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
+ int32_t aidl) {
+ using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
+
+ LegacyMask converted = VALUE_OR_RETURN(
+ (convertBitmask<LegacyMask, int32_t, audio_input_flags_t, AudioInputFlags>(
+ aidl, aidl2legacy_AudioInputFlags_audio_input_flags_t,
+ indexToEnum_index<AudioInputFlags>,
+ enumToMask_bitmask<LegacyMask, audio_input_flags_t>)));
+ return static_cast<audio_input_flags_t>(converted);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
+ audio_input_flags_t legacy) {
+ using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
+
+ LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
+ return convertBitmask<int32_t, LegacyMask, AudioInputFlags, audio_input_flags_t>(
+ legacyMask, legacy2aidl_audio_input_flags_t_AudioInputFlags,
+ indexToEnum_bitmask<audio_input_flags_t>,
+ enumToMask_index<int32_t, AudioInputFlags>);
+}
+
+ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
+ int32_t aidl) {
+ return convertBitmask<audio_output_flags_t,
+ int32_t,
+ audio_output_flags_t,
+ AudioOutputFlags>(
+ aidl, aidl2legacy_AudioOutputFlags_audio_output_flags_t,
+ indexToEnum_index<AudioOutputFlags>,
+ enumToMask_bitmask<audio_output_flags_t, audio_output_flags_t>);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
+ audio_output_flags_t legacy) {
+ using LegacyMask = std::underlying_type_t<audio_output_flags_t>;
+
+ LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
+ return convertBitmask<int32_t, LegacyMask, AudioOutputFlags, audio_output_flags_t>(
+ legacyMask, legacy2aidl_audio_output_flags_t_AudioOutputFlags,
+ indexToEnum_bitmask<audio_output_flags_t>,
+ enumToMask_index<int32_t, AudioOutputFlags>);
+}
+
+ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
+ const AudioIoFlags& aidl, bool isInput) {
+ audio_io_flags legacy;
+ if (isInput) {
+ legacy.input = VALUE_OR_RETURN(
+ aidl2legacy_int32_t_audio_input_flags_t_mask(
+ VALUE_OR_RETURN(UNION_GET(aidl, input))));
+ } else {
+ legacy.output = VALUE_OR_RETURN(
+ aidl2legacy_int32_t_audio_output_flags_t_mask(
+ VALUE_OR_RETURN(UNION_GET(aidl, output))));
+ }
+ return legacy;
+}
+
+ConversionResult<AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
+ const audio_io_flags& legacy, bool isInput) {
+ AudioIoFlags aidl;
+ if (isInput) {
+ UNION_SET(aidl, input,
+ VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(legacy.input)));
+ } else {
+ UNION_SET(aidl, output,
+ VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(legacy.output)));
+ }
+ return aidl;
+}
+
+ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
+ AudioStreamType aidl) {
+ switch (aidl) {
+ case AudioStreamType::INVALID:
+ break; // return error
+ case AudioStreamType::SYS_RESERVED_DEFAULT:
+ return AUDIO_STREAM_DEFAULT;
+ case AudioStreamType::VOICE_CALL:
+ return AUDIO_STREAM_VOICE_CALL;
+ case AudioStreamType::SYSTEM:
+ return AUDIO_STREAM_SYSTEM;
+ case AudioStreamType::RING:
+ return AUDIO_STREAM_RING;
+ case AudioStreamType::MUSIC:
+ return AUDIO_STREAM_MUSIC;
+ case AudioStreamType::ALARM:
+ return AUDIO_STREAM_ALARM;
+ case AudioStreamType::NOTIFICATION:
+ return AUDIO_STREAM_NOTIFICATION;
+ case AudioStreamType::BLUETOOTH_SCO:
+ return AUDIO_STREAM_BLUETOOTH_SCO;
+ case AudioStreamType::ENFORCED_AUDIBLE:
+ return AUDIO_STREAM_ENFORCED_AUDIBLE;
+ case AudioStreamType::DTMF:
+ return AUDIO_STREAM_DTMF;
+ case AudioStreamType::TTS:
+ return AUDIO_STREAM_TTS;
+ case AudioStreamType::ACCESSIBILITY:
+ return AUDIO_STREAM_ACCESSIBILITY;
+ case AudioStreamType::ASSISTANT:
+ return AUDIO_STREAM_ASSISTANT;
+ case AudioStreamType::SYS_RESERVED_REROUTING:
+ return AUDIO_STREAM_REROUTING;
+ case AudioStreamType::SYS_RESERVED_PATCH:
+ return AUDIO_STREAM_PATCH;
+ case AudioStreamType::CALL_ASSISTANT:
+ return AUDIO_STREAM_CALL_ASSISTANT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioStreamType> legacy2aidl_audio_stream_type_t_AudioStreamType(
+ audio_stream_type_t legacy) {
+ switch (legacy) {
+ case AUDIO_STREAM_DEFAULT:
+ return AudioStreamType::SYS_RESERVED_DEFAULT;
+ case AUDIO_STREAM_VOICE_CALL:
+ return AudioStreamType::VOICE_CALL;
+ case AUDIO_STREAM_SYSTEM:
+ return AudioStreamType::SYSTEM;
+ case AUDIO_STREAM_RING:
+ return AudioStreamType::RING;
+ case AUDIO_STREAM_MUSIC:
+ return AudioStreamType::MUSIC;
+ case AUDIO_STREAM_ALARM:
+ return AudioStreamType::ALARM;
+ case AUDIO_STREAM_NOTIFICATION:
+ return AudioStreamType::NOTIFICATION;
+ case AUDIO_STREAM_BLUETOOTH_SCO:
+ return AudioStreamType::BLUETOOTH_SCO;
+ case AUDIO_STREAM_ENFORCED_AUDIBLE:
+ return AudioStreamType::ENFORCED_AUDIBLE;
+ case AUDIO_STREAM_DTMF:
+ return AudioStreamType::DTMF;
+ case AUDIO_STREAM_TTS:
+ return AudioStreamType::TTS;
+ case AUDIO_STREAM_ACCESSIBILITY:
+ return AudioStreamType::ACCESSIBILITY;
+ case AUDIO_STREAM_ASSISTANT:
+ return AudioStreamType::ASSISTANT;
+ case AUDIO_STREAM_REROUTING:
+ return AudioStreamType::SYS_RESERVED_REROUTING;
+ case AUDIO_STREAM_PATCH:
+ return AudioStreamType::SYS_RESERVED_PATCH;
+ case AUDIO_STREAM_CALL_ASSISTANT:
+ return AudioStreamType::CALL_ASSISTANT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
+ AudioSource aidl) {
+ switch (aidl) {
+ case AudioSource::SYS_RESERVED_INVALID:
+ return AUDIO_SOURCE_INVALID;
+ case AudioSource::DEFAULT:
+ return AUDIO_SOURCE_DEFAULT;
+ case AudioSource::MIC:
+ return AUDIO_SOURCE_MIC;
+ case AudioSource::VOICE_UPLINK:
+ return AUDIO_SOURCE_VOICE_UPLINK;
+ case AudioSource::VOICE_DOWNLINK:
+ return AUDIO_SOURCE_VOICE_DOWNLINK;
+ case AudioSource::VOICE_CALL:
+ return AUDIO_SOURCE_VOICE_CALL;
+ case AudioSource::CAMCORDER:
+ return AUDIO_SOURCE_CAMCORDER;
+ case AudioSource::VOICE_RECOGNITION:
+ return AUDIO_SOURCE_VOICE_RECOGNITION;
+ case AudioSource::VOICE_COMMUNICATION:
+ return AUDIO_SOURCE_VOICE_COMMUNICATION;
+ case AudioSource::REMOTE_SUBMIX:
+ return AUDIO_SOURCE_REMOTE_SUBMIX;
+ case AudioSource::UNPROCESSED:
+ return AUDIO_SOURCE_UNPROCESSED;
+ case AudioSource::VOICE_PERFORMANCE:
+ return AUDIO_SOURCE_VOICE_PERFORMANCE;
+ case AudioSource::ULTRASOUND:
+ return AUDIO_SOURCE_ULTRASOUND;
+ case AudioSource::ECHO_REFERENCE:
+ return AUDIO_SOURCE_ECHO_REFERENCE;
+ case AudioSource::FM_TUNER:
+ return AUDIO_SOURCE_FM_TUNER;
+ case AudioSource::HOTWORD:
+ return AUDIO_SOURCE_HOTWORD;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioSource> legacy2aidl_audio_source_t_AudioSource(
+ audio_source_t legacy) {
+ switch (legacy) {
+ case AUDIO_SOURCE_INVALID:
+ return AudioSource::SYS_RESERVED_INVALID;
+ case AUDIO_SOURCE_DEFAULT:
+ return AudioSource::DEFAULT;
+ case AUDIO_SOURCE_MIC:
+ return AudioSource::MIC;
+ case AUDIO_SOURCE_VOICE_UPLINK:
+ return AudioSource::VOICE_UPLINK;
+ case AUDIO_SOURCE_VOICE_DOWNLINK:
+ return AudioSource::VOICE_DOWNLINK;
+ case AUDIO_SOURCE_VOICE_CALL:
+ return AudioSource::VOICE_CALL;
+ case AUDIO_SOURCE_CAMCORDER:
+ return AudioSource::CAMCORDER;
+ case AUDIO_SOURCE_VOICE_RECOGNITION:
+ return AudioSource::VOICE_RECOGNITION;
+ case AUDIO_SOURCE_VOICE_COMMUNICATION:
+ return AudioSource::VOICE_COMMUNICATION;
+ case AUDIO_SOURCE_REMOTE_SUBMIX:
+ return AudioSource::REMOTE_SUBMIX;
+ case AUDIO_SOURCE_UNPROCESSED:
+ return AudioSource::UNPROCESSED;
+ case AUDIO_SOURCE_VOICE_PERFORMANCE:
+ return AudioSource::VOICE_PERFORMANCE;
+ case AUDIO_SOURCE_ULTRASOUND:
+ return AudioSource::ULTRASOUND;
+ case AUDIO_SOURCE_ECHO_REFERENCE:
+ return AudioSource::ECHO_REFERENCE;
+ case AUDIO_SOURCE_FM_TUNER:
+ return AudioSource::FM_TUNER;
+ case AUDIO_SOURCE_HOTWORD:
+ return AudioSource::HOTWORD;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl) {
+ return convertReinterpret<audio_session_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_content_type_t>
+aidl2legacy_AudioContentType_audio_content_type_t(AudioContentType aidl) {
+ switch (aidl) {
+ case AudioContentType::UNKNOWN:
+ return AUDIO_CONTENT_TYPE_UNKNOWN;
+ case AudioContentType::SPEECH:
+ return AUDIO_CONTENT_TYPE_SPEECH;
+ case AudioContentType::MUSIC:
+ return AUDIO_CONTENT_TYPE_MUSIC;
+ case AudioContentType::MOVIE:
+ return AUDIO_CONTENT_TYPE_MOVIE;
+ case AudioContentType::SONIFICATION:
+ return AUDIO_CONTENT_TYPE_SONIFICATION;
+ case AudioContentType::ULTRASOUND:
+ return AUDIO_CONTENT_TYPE_ULTRASOUND;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioContentType>
+legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy) {
+ switch (legacy) {
+ case AUDIO_CONTENT_TYPE_UNKNOWN:
+ return AudioContentType::UNKNOWN;
+ case AUDIO_CONTENT_TYPE_SPEECH:
+ return AudioContentType::SPEECH;
+ case AUDIO_CONTENT_TYPE_MUSIC:
+ return AudioContentType::MUSIC;
+ case AUDIO_CONTENT_TYPE_MOVIE:
+ return AudioContentType::MOVIE;
+ case AUDIO_CONTENT_TYPE_SONIFICATION:
+ return AudioContentType::SONIFICATION;
+ case AUDIO_CONTENT_TYPE_ULTRASOUND:
+ return AudioContentType::ULTRASOUND;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_usage_t>
+aidl2legacy_AudioUsage_audio_usage_t(AudioUsage aidl) {
+ switch (aidl) {
+ case AudioUsage::INVALID:
+ break; // return error
+ case AudioUsage::UNKNOWN:
+ return AUDIO_USAGE_UNKNOWN;
+ case AudioUsage::MEDIA:
+ return AUDIO_USAGE_MEDIA;
+ case AudioUsage::VOICE_COMMUNICATION:
+ return AUDIO_USAGE_VOICE_COMMUNICATION;
+ case AudioUsage::VOICE_COMMUNICATION_SIGNALLING:
+ return AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+ case AudioUsage::ALARM:
+ return AUDIO_USAGE_ALARM;
+ case AudioUsage::NOTIFICATION:
+ return AUDIO_USAGE_NOTIFICATION;
+ case AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE:
+ return AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+ case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST:
+ return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
+ case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT:
+ return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT;
+ case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED:
+ return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED;
+ case AudioUsage::NOTIFICATION_EVENT:
+ return AUDIO_USAGE_NOTIFICATION_EVENT;
+ case AudioUsage::ASSISTANCE_ACCESSIBILITY:
+ return AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+ case AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE:
+ return AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
+ case AudioUsage::ASSISTANCE_SONIFICATION:
+ return AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+ case AudioUsage::GAME:
+ return AUDIO_USAGE_GAME;
+ case AudioUsage::VIRTUAL_SOURCE:
+ return AUDIO_USAGE_VIRTUAL_SOURCE;
+ case AudioUsage::ASSISTANT:
+ return AUDIO_USAGE_ASSISTANT;
+ case AudioUsage::CALL_ASSISTANT:
+ return AUDIO_USAGE_CALL_ASSISTANT;
+ case AudioUsage::EMERGENCY:
+ return AUDIO_USAGE_EMERGENCY;
+ case AudioUsage::SAFETY:
+ return AUDIO_USAGE_SAFETY;
+ case AudioUsage::VEHICLE_STATUS:
+ return AUDIO_USAGE_VEHICLE_STATUS;
+ case AudioUsage::ANNOUNCEMENT:
+ return AUDIO_USAGE_ANNOUNCEMENT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioUsage>
+legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy) {
+ switch (legacy) {
+ case AUDIO_USAGE_UNKNOWN:
+ return AudioUsage::UNKNOWN;
+ case AUDIO_USAGE_MEDIA:
+ return AudioUsage::MEDIA;
+ case AUDIO_USAGE_VOICE_COMMUNICATION:
+ return AudioUsage::VOICE_COMMUNICATION;
+ case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
+ return AudioUsage::VOICE_COMMUNICATION_SIGNALLING;
+ case AUDIO_USAGE_ALARM:
+ return AudioUsage::ALARM;
+ case AUDIO_USAGE_NOTIFICATION:
+ return AudioUsage::NOTIFICATION;
+ case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
+ return AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE;
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+ return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST;
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+ return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT;
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+ return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED;
+ case AUDIO_USAGE_NOTIFICATION_EVENT:
+ return AudioUsage::NOTIFICATION_EVENT;
+ case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+ return AudioUsage::ASSISTANCE_ACCESSIBILITY;
+ case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+ return AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE;
+ case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
+ return AudioUsage::ASSISTANCE_SONIFICATION;
+ case AUDIO_USAGE_GAME:
+ return AudioUsage::GAME;
+ case AUDIO_USAGE_VIRTUAL_SOURCE:
+ return AudioUsage::VIRTUAL_SOURCE;
+ case AUDIO_USAGE_ASSISTANT:
+ return AudioUsage::ASSISTANT;
+ case AUDIO_USAGE_CALL_ASSISTANT:
+ return AudioUsage::CALL_ASSISTANT;
+ case AUDIO_USAGE_EMERGENCY:
+ return AudioUsage::EMERGENCY;
+ case AUDIO_USAGE_SAFETY:
+ return AudioUsage::SAFETY;
+ case AUDIO_USAGE_VEHICLE_STATUS:
+ return AudioUsage::VEHICLE_STATUS;
+ case AUDIO_USAGE_ANNOUNCEMENT:
+ return AudioUsage::ANNOUNCEMENT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+
+ConversionResult<audio_encapsulation_mode_t>
+aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(AudioEncapsulationMode aidl) {
+ switch (aidl) {
+ case AudioEncapsulationMode::INVALID:
+ break; // return error
+ case AudioEncapsulationMode::NONE:
+ return AUDIO_ENCAPSULATION_MODE_NONE;
+ case AudioEncapsulationMode::ELEMENTARY_STREAM:
+ return AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM;
+ case AudioEncapsulationMode::HANDLE:
+ return AUDIO_ENCAPSULATION_MODE_HANDLE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioEncapsulationMode>
+legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_ENCAPSULATION_MODE_NONE:
+ return AudioEncapsulationMode::NONE;
+ case AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM:
+ return AudioEncapsulationMode::ELEMENTARY_STREAM;
+ case AUDIO_ENCAPSULATION_MODE_HANDLE:
+ return AudioEncapsulationMode::HANDLE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_offload_info_t>
+aidl2legacy_AudioOffloadInfo_audio_offload_info_t(const AudioOffloadInfo& aidl) {
+ audio_offload_info_t legacy = AUDIO_INFO_INITIALIZER;
+ audio_config_base_t base = VALUE_OR_RETURN(
+ aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, false /*isInput*/));
+ legacy.sample_rate = base.sample_rate;
+ legacy.channel_mask = base.channel_mask;
+ legacy.format = base.format;
+ legacy.stream_type = VALUE_OR_RETURN(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
+ legacy.bit_rate = VALUE_OR_RETURN(convertIntegral<int32_t>(aidl.bitRatePerSecond));
+ legacy.duration_us = VALUE_OR_RETURN(convertIntegral<int64_t>(aidl.durationUs));
+ legacy.has_video = aidl.hasVideo;
+ legacy.is_streaming = aidl.isStreaming;
+ legacy.bit_width = VALUE_OR_RETURN(convertIntegral<int32_t>(aidl.bitWidth));
+ legacy.offload_buffer_size = VALUE_OR_RETURN(convertIntegral<int32_t>(aidl.offloadBufferSize));
+ legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
+ legacy.encapsulation_mode = VALUE_OR_RETURN(
+ aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(aidl.encapsulationMode));
+ legacy.content_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.contentId));
+ legacy.sync_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.syncId));
+ return legacy;
+}
+
+ConversionResult<AudioOffloadInfo>
+legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy) {
+ AudioOffloadInfo aidl;
+ // Version 0.1 fields.
+ if (legacy.size < offsetof(audio_offload_info_t, usage) + sizeof(audio_offload_info_t::usage)) {
+ return unexpected(BAD_VALUE);
+ }
+ const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
+ .channel_mask = legacy.channel_mask, .format = legacy.format };
+ aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(
+ base, false /*isInput*/));
+ aidl.streamType = VALUE_OR_RETURN(
+ legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream_type));
+ aidl.bitRatePerSecond = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_rate));
+ aidl.durationUs = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.duration_us));
+ aidl.hasVideo = legacy.has_video;
+ aidl.isStreaming = legacy.is_streaming;
+ aidl.bitWidth = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_width));
+ aidl.offloadBufferSize = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.offload_buffer_size));
+ aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
+
+ // Version 0.2 fields.
+ if (legacy.version >= AUDIO_OFFLOAD_INFO_VERSION_0_2) {
+ if (legacy.size <
+ offsetof(audio_offload_info_t, sync_id) + sizeof(audio_offload_info_t::sync_id)) {
+ return unexpected(BAD_VALUE);
+ }
+ aidl.encapsulationMode = VALUE_OR_RETURN(
+ legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(
+ legacy.encapsulation_mode));
+ aidl.contentId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.content_id));
+ aidl.syncId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.sync_id));
+ }
+ return aidl;
+}
+
+ConversionResult<AudioPortDirection> portDirection(audio_port_role_t role, audio_port_type_t type) {
+ switch (type) {
+ case AUDIO_PORT_TYPE_NONE:
+ case AUDIO_PORT_TYPE_SESSION:
+ break; // must be listed -Werror,-Wswitch
+ case AUDIO_PORT_TYPE_DEVICE:
+ switch (role) {
+ case AUDIO_PORT_ROLE_NONE:
+ break; // must be listed -Werror,-Wswitch
+ case AUDIO_PORT_ROLE_SOURCE:
+ return AudioPortDirection::INPUT;
+ case AUDIO_PORT_ROLE_SINK:
+ return AudioPortDirection::OUTPUT;
+ }
+ break;
+ case AUDIO_PORT_TYPE_MIX:
+ switch (role) {
+ case AUDIO_PORT_ROLE_NONE:
+ break; // must be listed -Werror,-Wswitch
+ case AUDIO_PORT_ROLE_SOURCE:
+ return AudioPortDirection::OUTPUT;
+ case AUDIO_PORT_ROLE_SINK:
+ return AudioPortDirection::INPUT;
+ }
+ break;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_port_role_t> portRole(AudioPortDirection direction, audio_port_type_t type) {
+ switch (type) {
+ case AUDIO_PORT_TYPE_NONE:
+ case AUDIO_PORT_TYPE_SESSION:
+ break; // must be listed -Werror,-Wswitch
+ case AUDIO_PORT_TYPE_DEVICE:
+ switch (direction) {
+ case AudioPortDirection::INPUT:
+ return AUDIO_PORT_ROLE_SOURCE;
+ case AudioPortDirection::OUTPUT:
+ return AUDIO_PORT_ROLE_SINK;
+ }
+ break;
+ case AUDIO_PORT_TYPE_MIX:
+ switch (direction) {
+ case AudioPortDirection::OUTPUT:
+ return AUDIO_PORT_ROLE_SOURCE;
+ case AudioPortDirection::INPUT:
+ return AUDIO_PORT_ROLE_SINK;
+ }
+ break;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_config_t>
+aidl2legacy_AudioConfig_audio_config_t(const AudioConfig& aidl, bool isInput) {
+ const audio_config_base_t legacyBase = VALUE_OR_RETURN(
+ aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, isInput));
+ audio_config_t legacy = AUDIO_CONFIG_INITIALIZER;
+ legacy.sample_rate = legacyBase.sample_rate;
+ legacy.channel_mask = legacyBase.channel_mask;
+ legacy.format = legacyBase.format;
+ legacy.offload_info = VALUE_OR_RETURN(
+ aidl2legacy_AudioOffloadInfo_audio_offload_info_t(aidl.offloadInfo));
+ legacy.frame_count = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.frameCount));
+ return legacy;
+}
+
+ConversionResult<AudioConfig>
+legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput) {
+ const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
+ .channel_mask = legacy.channel_mask, .format = legacy.format };
+ AudioConfig aidl;
+ aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(base, isInput));
+ aidl.offloadInfo = VALUE_OR_RETURN(
+ legacy2aidl_audio_offload_info_t_AudioOffloadInfo(legacy.offload_info));
+ aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.frame_count));
+ return aidl;
+}
+
+ConversionResult<audio_config_base_t>
+aidl2legacy_AudioConfigBase_audio_config_base_t(const AudioConfigBase& aidl, bool isInput) {
+ audio_config_base_t legacy;
+ legacy.sample_rate = VALUE_OR_RETURN(convertIntegral<int>(aidl.sampleRate));
+ legacy.channel_mask = VALUE_OR_RETURN(
+ aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
+ legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
+ return legacy;
+}
+
+ConversionResult<AudioConfigBase>
+legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput) {
+ AudioConfigBase aidl;
+ aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
+ aidl.channelMask = VALUE_OR_RETURN(
+ legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+ aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
+ return aidl;
+}
+
+ConversionResult<audio_uuid_t>
+aidl2legacy_AudioUuid_audio_uuid_t(const AudioUuid& aidl) {
+ audio_uuid_t legacy;
+ legacy.timeLow = VALUE_OR_RETURN(convertReinterpret<uint32_t>(aidl.timeLow));
+ legacy.timeMid = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeMid));
+ legacy.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeHiAndVersion));
+ legacy.clockSeq = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.clockSeq));
+ if (aidl.node.size() != std::size(legacy.node)) {
+ return unexpected(BAD_VALUE);
+ }
+ std::copy(aidl.node.begin(), aidl.node.end(), legacy.node);
+ return legacy;
+}
+
+ConversionResult<AudioUuid>
+legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy) {
+ AudioUuid aidl;
+ aidl.timeLow = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.timeLow));
+ aidl.timeMid = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeMid));
+ aidl.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeHiAndVersion));
+ aidl.clockSeq = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.clockSeq));
+ std::copy(legacy.node, legacy.node + std::size(legacy.node), std::back_inserter(aidl.node));
+ return aidl;
+}
+
+ConversionResult<audio_encapsulation_metadata_type_t>
+aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
+ AudioEncapsulationMetadataType aidl) {
+ switch (aidl) {
+ case AudioEncapsulationMetadataType::NONE:
+ return AUDIO_ENCAPSULATION_METADATA_TYPE_NONE;
+ case AudioEncapsulationMetadataType::FRAMEWORK_TUNER:
+ return AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER;
+ case AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR:
+ return AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioEncapsulationMetadataType>
+legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
+ audio_encapsulation_metadata_type_t legacy) {
+ switch (legacy) {
+ case AUDIO_ENCAPSULATION_METADATA_TYPE_NONE:
+ return AudioEncapsulationMetadataType::NONE;
+ case AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER:
+ return AudioEncapsulationMetadataType::FRAMEWORK_TUNER;
+ case AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR:
+ return AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<uint32_t>
+aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl) {
+ return convertBitmask<uint32_t,
+ int32_t,
+ audio_encapsulation_mode_t,
+ AudioEncapsulationMode>(
+ aidl, aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t,
+ indexToEnum_index<AudioEncapsulationMode>,
+ enumToMask_index<uint32_t, audio_encapsulation_mode_t>);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy) {
+ return convertBitmask<int32_t,
+ uint32_t,
+ AudioEncapsulationMode,
+ audio_encapsulation_mode_t>(
+ legacy, legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode,
+ indexToEnum_index<audio_encapsulation_mode_t>,
+ enumToMask_index<int32_t, AudioEncapsulationMode>);
+}
+
+ConversionResult<uint32_t>
+aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl) {
+ return convertBitmask<uint32_t,
+ int32_t,
+ audio_encapsulation_metadata_type_t,
+ AudioEncapsulationMetadataType>(
+ aidl, aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t,
+ indexToEnum_index<AudioEncapsulationMetadataType>,
+ enumToMask_index<uint32_t, audio_encapsulation_metadata_type_t>);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy) {
+ return convertBitmask<int32_t,
+ uint32_t,
+ AudioEncapsulationMetadataType,
+ audio_encapsulation_metadata_type_t>(
+ legacy, legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType,
+ indexToEnum_index<audio_encapsulation_metadata_type_t>,
+ enumToMask_index<int32_t, AudioEncapsulationMetadataType>);
+}
+
+ConversionResult<audio_port_config_mix_ext_usecase>
+aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+ const AudioPortMixExtUseCase& aidl, bool isInput) {
+ audio_port_config_mix_ext_usecase legacy{};
+ if (aidl.getTag() != AudioPortMixExtUseCase::Tag::unspecified) {
+ if (!isInput) {
+ legacy.stream = VALUE_OR_RETURN(aidl2legacy_AudioStreamType_audio_stream_type_t(
+ VALUE_OR_RETURN(UNION_GET(aidl, stream))));
+ } else {
+ legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(
+ VALUE_OR_RETURN(UNION_GET(aidl, source))));
+ }
+ }
+ return legacy;
+}
+
+ConversionResult<AudioPortMixExtUseCase>
+legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+ const audio_port_config_mix_ext_usecase& legacy, bool isInput) {
+ AudioPortMixExtUseCase aidl;
+ if (!isInput) {
+ UNION_SET(aidl, stream, VALUE_OR_RETURN(
+ legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream)));
+ } else {
+ UNION_SET(aidl, source, VALUE_OR_RETURN(
+ legacy2aidl_audio_source_t_AudioSource(legacy.source)));
+ }
+ return aidl;
+}
+
+ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortMixExt_audio_port_config_mix_ext(
+ const AudioPortMixExt& aidl, bool isInput) {
+ audio_port_config_mix_ext legacy{};
+ legacy.handle = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.handle));
+ legacy.usecase = VALUE_OR_RETURN(
+ aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+ aidl.usecase, isInput));
+ return legacy;
+}
+
+ConversionResult<AudioPortMixExt> legacy2aidl_audio_port_config_mix_ext_AudioPortMixExt(
+ const audio_port_config_mix_ext& legacy, bool isInput) {
+ AudioPortMixExt aidl;
+ aidl.handle = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
+ aidl.usecase = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+ legacy.usecase, isInput));
+ return aidl;
+}
+
+ConversionResult<audio_port_config_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(const AudioPortDeviceExt& aidl) {
+ audio_port_config_device_ext legacy{};
+ RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+ aidl.device, &legacy.type, legacy.address));
+ return legacy;
+}
+
+ConversionResult<AudioPortDeviceExt> legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
+ const audio_port_config_device_ext& legacy) {
+ AudioPortDeviceExt aidl;
+ aidl.device = VALUE_OR_RETURN(
+ legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
+ return aidl;
+}
+
+// This type is unnamed in the original definition, thus we name it here.
+using audio_port_config_ext = decltype(audio_port_config::ext);
+
+status_t aidl2legacy_AudioPortExt_audio_port_config_ext(
+ const AudioPortExt& aidl, bool isInput,
+ audio_port_config_ext* legacy, audio_port_type_t* type) {
+ switch (aidl.getTag()) {
+ case AudioPortExt::Tag::unspecified:
+ // Just verify that the union is empty.
+ VALUE_OR_RETURN_STATUS(UNION_GET(aidl, unspecified));
+ *legacy = {};
+ *type = AUDIO_PORT_TYPE_NONE;
+ return OK;
+ case AudioPortExt::Tag::device:
+ legacy->device = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
+ VALUE_OR_RETURN_STATUS(UNION_GET(aidl, device))));
+ *type = AUDIO_PORT_TYPE_DEVICE;
+ return OK;
+ case AudioPortExt::Tag::mix:
+ legacy->mix = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioPortMixExt_audio_port_config_mix_ext(
+ VALUE_OR_RETURN_STATUS(UNION_GET(aidl, mix)), isInput));
+ *type = AUDIO_PORT_TYPE_MIX;
+ return OK;
+ case AudioPortExt::Tag::session:
+ // This variant is not used in the HAL scenario.
+ legacy->session.session = AUDIO_SESSION_NONE;
+ *type = AUDIO_PORT_TYPE_SESSION;
+ return OK;
+
+ }
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
+}
+
+ConversionResult<AudioPortExt> legacy2aidl_audio_port_config_ext_AudioPortExt(
+ const audio_port_config_ext& legacy, audio_port_type_t type, bool isInput) {
+ AudioPortExt aidl;
+ switch (type) {
+ case AUDIO_PORT_TYPE_NONE:
+ UNION_SET(aidl, unspecified, false);
+ return aidl;
+ case AUDIO_PORT_TYPE_DEVICE: {
+ AudioPortDeviceExt device = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(legacy.device));
+ UNION_SET(aidl, device, device);
+ return aidl;
+ }
+ case AUDIO_PORT_TYPE_MIX: {
+ AudioPortMixExt mix = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_config_mix_ext_AudioPortMixExt(legacy.mix, isInput));
+ UNION_SET(aidl, mix, mix);
+ return aidl;
+ }
+ case AUDIO_PORT_TYPE_SESSION:
+ // This variant is not used in the HAL scenario.
+ UNION_SET(aidl, unspecified, false);
+ return aidl;
+ }
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
+}
+
+status_t aidl2legacy_AudioPortConfig_audio_port_config(
+ const AudioPortConfig& aidl, bool isInput, audio_port_config* legacy, int32_t* portId) {
+ legacy->id = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_port_handle_t(aidl.id));
+ *portId = aidl.portId;
+ if (aidl.sampleRate.has_value()) {
+ legacy->sample_rate = VALUE_OR_RETURN_STATUS(
+ convertIntegral<unsigned int>(aidl.sampleRate.value().value));
+ legacy->config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
+ }
+ if (aidl.channelMask.has_value()) {
+ legacy->channel_mask =
+ VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ aidl.channelMask.value(), isInput));
+ legacy->config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
+ }
+ if (aidl.format.has_value()) {
+ legacy->format = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format.value()));
+ legacy->config_mask |= AUDIO_PORT_CONFIG_FORMAT;
+ }
+ if (aidl.gain.has_value()) {
+ legacy->gain = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioGainConfig_audio_gain_config(
+ aidl.gain.value(), isInput));
+ legacy->config_mask |= AUDIO_PORT_CONFIG_GAIN;
+ }
+ if (aidl.flags.has_value()) {
+ legacy->flags = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioIoFlags_audio_io_flags(aidl.flags.value(), isInput));
+ legacy->config_mask |= AUDIO_PORT_CONFIG_FLAGS;
+ }
+ RETURN_STATUS_IF_ERROR(aidl2legacy_AudioPortExt_audio_port_config_ext(
+ aidl.ext, isInput, &legacy->ext, &legacy->type));
+ legacy->role = VALUE_OR_RETURN_STATUS(portRole(isInput ?
+ AudioPortDirection::INPUT : AudioPortDirection::OUTPUT, legacy->type));
+ return OK;
+}
+
+ConversionResult<AudioPortConfig>
+legacy2aidl_audio_port_config_AudioPortConfig(
+ const audio_port_config& legacy, bool isInput, int32_t portId) {
+ AudioPortConfig aidl;
+ aidl.id = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+ aidl.portId = portId;
+ if (legacy.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
+ Int aidl_sampleRate;
+ aidl_sampleRate.value = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
+ aidl.sampleRate = aidl_sampleRate;
+ }
+ if (legacy.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
+ aidl.channelMask = VALUE_OR_RETURN(
+ legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+ }
+ if (legacy.config_mask & AUDIO_PORT_CONFIG_FORMAT) {
+ aidl.format = VALUE_OR_RETURN(
+ legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
+ }
+ if (legacy.config_mask & AUDIO_PORT_CONFIG_GAIN) {
+ aidl.gain = VALUE_OR_RETURN(
+ legacy2aidl_audio_gain_config_AudioGainConfig(legacy.gain, isInput));
+ }
+ if (legacy.config_mask & AUDIO_PORT_CONFIG_FLAGS) {
+ aidl.flags = VALUE_OR_RETURN(
+ legacy2aidl_audio_io_flags_AudioIoFlags(legacy.flags, isInput));
+ }
+ aidl.ext = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_config_ext_AudioPortExt(legacy.ext, legacy.type, isInput));
+ return aidl;
+}
+
+ConversionResult<audio_port_mix_ext> aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
+ const AudioPortMixExt& aidl) {
+ audio_port_mix_ext legacy{};
+ legacy.handle = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.handle));
+ return legacy;
+}
+
+ConversionResult<AudioPortMixExt> legacy2aidl_audio_port_mix_ext_AudioPortMixExt(
+ const audio_port_mix_ext& legacy) {
+ AudioPortMixExt aidl;
+ aidl.handle = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
+ return aidl;
+}
+
+ConversionResult<audio_port_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(const AudioPortDeviceExt& aidl) {
+ audio_port_device_ext legacy{};
+ RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+ aidl.device, &legacy.type, legacy.address));
+ legacy.encapsulation_modes = VALUE_OR_RETURN(
+ aidl2legacy_AudioEncapsulationMode_mask(aidl.encapsulationModes));
+ legacy.encapsulation_metadata_types = VALUE_OR_RETURN(
+ aidl2legacy_AudioEncapsulationMetadataType_mask(
+ aidl.encapsulationMetadataTypes));
+ return legacy;
+}
+
+ConversionResult<AudioPortDeviceExt> legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
+ const audio_port_device_ext& legacy) {
+ AudioPortDeviceExt aidl;
+ aidl.device = VALUE_OR_RETURN(
+ legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
+ aidl.encapsulationModes = VALUE_OR_RETURN(
+ legacy2aidl_AudioEncapsulationMode_mask(legacy.encapsulation_modes));
+ aidl.encapsulationMetadataTypes = VALUE_OR_RETURN(
+ legacy2aidl_AudioEncapsulationMetadataType_mask(legacy.encapsulation_metadata_types));
+ return aidl;
+}
+
+// This type is unnamed in the original definition, thus we name it here.
+using audio_port_v7_ext = decltype(audio_port_v7::ext);
+
+status_t aidl2legacy_AudioPortExt_audio_port_v7_ext(
+ const AudioPortExt& aidl, audio_port_v7_ext* legacy, audio_port_type_t* type) {
+ switch (aidl.getTag()) {
+ case AudioPortExt::Tag::unspecified:
+ // Just verify that the union is empty.
+ VALUE_OR_RETURN_STATUS(UNION_GET(aidl, unspecified));
+ *legacy = {};
+ *type = AUDIO_PORT_TYPE_NONE;
+ return OK;
+ case AudioPortExt::Tag::device:
+ legacy->device = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
+ VALUE_OR_RETURN_STATUS(UNION_GET(aidl, device))));
+ *type = AUDIO_PORT_TYPE_DEVICE;
+ return OK;
+ case AudioPortExt::Tag::mix:
+ legacy->mix = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
+ VALUE_OR_RETURN_STATUS(UNION_GET(aidl, mix))));
+ *type = AUDIO_PORT_TYPE_MIX;
+ return OK;
+ case AudioPortExt::Tag::session:
+ // This variant is not used in the HAL scenario.
+ legacy->session.session = AUDIO_SESSION_NONE;
+ *type = AUDIO_PORT_TYPE_SESSION;
+ return OK;
+
+ }
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
+}
+
+ConversionResult<AudioPortExt> legacy2aidl_audio_port_v7_ext_AudioPortExt(
+ const audio_port_v7_ext& legacy, audio_port_type_t type) {
+ AudioPortExt aidl;
+ switch (type) {
+ case AUDIO_PORT_TYPE_NONE:
+ UNION_SET(aidl, unspecified, false);
+ return aidl;
+ case AUDIO_PORT_TYPE_DEVICE: {
+ AudioPortDeviceExt device = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(legacy.device));
+ UNION_SET(aidl, device, device);
+ return aidl;
+ }
+ case AUDIO_PORT_TYPE_MIX: {
+ AudioPortMixExt mix = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_mix_ext_AudioPortMixExt(legacy.mix));
+ UNION_SET(aidl, mix, mix);
+ return aidl;
+ }
+ case AUDIO_PORT_TYPE_SESSION:
+ // This variant is not used in the HAL scenario.
+ UNION_SET(aidl, unspecified, false);
+ return aidl;
+ }
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
+}
+
+ConversionResult<audio_port_v7>
+aidl2legacy_AudioPort_audio_port_v7(const AudioPort& aidl, bool isInput) {
+ audio_port_v7 legacy;
+ legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.id));
+ RETURN_IF_ERROR(aidl2legacy_string(aidl.name, legacy.name, sizeof(legacy.name)));
+
+ if (aidl.profiles.size() > std::size(legacy.audio_profiles)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(convertRange(
+ aidl.profiles.begin(), aidl.profiles.end(), legacy.audio_profiles,
+ [isInput](const AudioProfile& p) {
+ return aidl2legacy_AudioProfile_audio_profile(p, isInput);
+ }));
+ legacy.num_audio_profiles = aidl.profiles.size();
+
+ if (aidl.extraAudioDescriptors.size() > std::size(legacy.extra_audio_descriptors)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(
+ aidl.extraAudioDescriptors.begin(), aidl.extraAudioDescriptors.end(),
+ legacy.extra_audio_descriptors,
+ aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor));
+ legacy.num_extra_audio_descriptors = aidl.extraAudioDescriptors.size();
+
+ if (aidl.gains.size() > std::size(legacy.gains)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(convertRange(aidl.gains.begin(), aidl.gains.end(), legacy.gains,
+ [isInput](const AudioGain& g) {
+ return aidl2legacy_AudioGain_audio_gain(g, isInput);
+ }));
+ legacy.num_gains = aidl.gains.size();
+
+ RETURN_IF_ERROR(aidl2legacy_AudioPortExt_audio_port_v7_ext(
+ aidl.ext, &legacy.ext, &legacy.type));
+ legacy.role = VALUE_OR_RETURN(portRole(
+ isInput ? AudioPortDirection::INPUT : AudioPortDirection::OUTPUT, legacy.type));
+
+ AudioPortConfig aidlPortConfig;
+ int32_t portId;
+ aidlPortConfig.flags = aidl.flags;
+ aidlPortConfig.ext = aidl.ext;
+ RETURN_IF_ERROR(aidl2legacy_AudioPortConfig_audio_port_config(
+ aidlPortConfig, isInput, &legacy.active_config, &portId));
+ return legacy;
+}
+
+ConversionResult<AudioPort>
+legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy, bool isInput) {
+ AudioPort aidl;
+ aidl.id = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+ aidl.name = VALUE_OR_RETURN(legacy2aidl_string(legacy.name, sizeof(legacy.name)));
+
+ if (legacy.num_audio_profiles > std::size(legacy.audio_profiles)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(legacy.audio_profiles, legacy.audio_profiles + legacy.num_audio_profiles,
+ std::back_inserter(aidl.profiles),
+ [isInput](const audio_profile& p) {
+ return legacy2aidl_audio_profile_AudioProfile(p, isInput);
+ }));
+
+ if (legacy.num_extra_audio_descriptors > std::size(legacy.extra_audio_descriptors)) {
+ return unexpected(BAD_VALUE);
+ }
+ aidl.profiles.resize(legacy.num_audio_profiles);
+ RETURN_IF_ERROR(
+ convertRange(legacy.extra_audio_descriptors,
+ legacy.extra_audio_descriptors + legacy.num_extra_audio_descriptors,
+ std::back_inserter(aidl.extraAudioDescriptors),
+ legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor));
+
+ if (legacy.num_gains > std::size(legacy.gains)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(legacy.gains, legacy.gains + legacy.num_gains,
+ std::back_inserter(aidl.gains),
+ [isInput](const audio_gain& g) {
+ return legacy2aidl_audio_gain_AudioGain(g, isInput);
+ }));
+ aidl.gains.resize(legacy.num_gains);
+
+ aidl.ext = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_v7_ext_AudioPortExt(legacy.ext, legacy.type));
+
+ AudioPortConfig aidlPortConfig = VALUE_OR_RETURN(legacy2aidl_audio_port_config_AudioPortConfig(
+ legacy.active_config, isInput, aidl.id));
+ if (aidlPortConfig.flags.has_value()) {
+ aidl.flags = aidlPortConfig.flags.value();
+ } else {
+ aidl.flags = isInput ?
+ AudioIoFlags::make<AudioIoFlags::Tag::input>(0) :
+ AudioIoFlags::make<AudioIoFlags::Tag::output>(0);
+ }
+ return aidl;
+}
+
+ConversionResult<audio_profile>
+aidl2legacy_AudioProfile_audio_profile(const AudioProfile& aidl, bool isInput) {
+ audio_profile legacy;
+ legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
+
+ if (aidl.sampleRates.size() > std::size(legacy.sample_rates)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(aidl.sampleRates.begin(), aidl.sampleRates.end(), legacy.sample_rates,
+ convertIntegral<int32_t, unsigned int>));
+ legacy.num_sample_rates = aidl.sampleRates.size();
+
+ if (aidl.channelMasks.size() > std::size(legacy.channel_masks)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(aidl.channelMasks.begin(), aidl.channelMasks.end(), legacy.channel_masks,
+ [isInput](const AudioChannelLayout& l) {
+ return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
+ }));
+ legacy.num_channel_masks = aidl.channelMasks.size();
+
+ legacy.encapsulation_type = VALUE_OR_RETURN(
+ aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(aidl.encapsulationType));
+ return legacy;
+}
+
+ConversionResult<AudioProfile>
+legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput) {
+ AudioProfile aidl;
+ aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
+
+ if (legacy.num_sample_rates > std::size(legacy.sample_rates)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(legacy.sample_rates, legacy.sample_rates + legacy.num_sample_rates,
+ std::back_inserter(aidl.sampleRates),
+ convertIntegral<unsigned int, int32_t>));
+
+ if (legacy.num_channel_masks > std::size(legacy.channel_masks)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(legacy.channel_masks, legacy.channel_masks + legacy.num_channel_masks,
+ std::back_inserter(aidl.channelMasks),
+ [isInput](audio_channel_mask_t m) {
+ return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
+ }));
+
+ aidl.encapsulationType = VALUE_OR_RETURN(
+ legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+ legacy.encapsulation_type));
+ return aidl;
+}
+
+ConversionResult<audio_gain>
+aidl2legacy_AudioGain_audio_gain(const AudioGain& aidl, bool isInput) {
+ audio_gain legacy;
+ legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
+ legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ aidl.channelMask, isInput));
+ legacy.min_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.minValue));
+ legacy.max_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.maxValue));
+ legacy.default_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.defaultValue));
+ legacy.step_value = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.stepValue));
+ legacy.min_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.minRampMs));
+ legacy.max_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.maxRampMs));
+ return legacy;
+}
+
+ConversionResult<AudioGain>
+legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput) {
+ AudioGain aidl;
+ aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
+ aidl.channelMask = VALUE_OR_RETURN(
+ legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+ aidl.minValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_value));
+ aidl.maxValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_value));
+ aidl.defaultValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.default_value));
+ aidl.stepValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.step_value));
+ aidl.minRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_ramp_ms));
+ aidl.maxRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_ramp_ms));
+ return aidl;
+}
+
+ConversionResult<audio_mode_t>
+aidl2legacy_AudioMode_audio_mode_t(AudioMode aidl) {
+ switch (aidl) {
+ case AudioMode::SYS_RESERVED_INVALID:
+ return AUDIO_MODE_INVALID;
+ case AudioMode::SYS_RESERVED_CURRENT:
+ return AUDIO_MODE_CURRENT;
+ case AudioMode::NORMAL:
+ return AUDIO_MODE_NORMAL;
+ case AudioMode::RINGTONE:
+ return AUDIO_MODE_RINGTONE;
+ case AudioMode::IN_CALL:
+ return AUDIO_MODE_IN_CALL;
+ case AudioMode::IN_COMMUNICATION:
+ return AUDIO_MODE_IN_COMMUNICATION;
+ case AudioMode::CALL_SCREEN:
+ return AUDIO_MODE_CALL_SCREEN;
+ case AudioMode::SYS_RESERVED_CALL_REDIRECT:
+ return AUDIO_MODE_CALL_REDIRECT;
+ case AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT:
+ return AUDIO_MODE_COMMUNICATION_REDIRECT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioMode>
+legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_MODE_INVALID:
+ return AudioMode::SYS_RESERVED_INVALID;
+ case AUDIO_MODE_CURRENT:
+ return AudioMode::SYS_RESERVED_CURRENT;
+ case AUDIO_MODE_NORMAL:
+ return AudioMode::NORMAL;
+ case AUDIO_MODE_RINGTONE:
+ return AudioMode::RINGTONE;
+ case AUDIO_MODE_IN_CALL:
+ return AudioMode::IN_CALL;
+ case AUDIO_MODE_IN_COMMUNICATION:
+ return AudioMode::IN_COMMUNICATION;
+ case AUDIO_MODE_CALL_SCREEN:
+ return AudioMode::CALL_SCREEN;
+ case AUDIO_MODE_CALL_REDIRECT:
+ return AudioMode::SYS_RESERVED_CALL_REDIRECT;
+ case AUDIO_MODE_COMMUNICATION_REDIRECT:
+ return AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT;
+ case AUDIO_MODE_CNT:
+ break;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_standard_t>
+aidl2legacy_AudioStandard_audio_standard_t(AudioStandard aidl) {
+ switch (aidl) {
+ case AudioStandard::NONE:
+ return AUDIO_STANDARD_NONE;
+ case AudioStandard::EDID:
+ return AUDIO_STANDARD_EDID;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioStandard>
+legacy2aidl_audio_standard_t_AudioStandard(audio_standard_t legacy) {
+ switch (legacy) {
+ case AUDIO_STANDARD_NONE:
+ return AudioStandard::NONE;
+ case AUDIO_STANDARD_EDID:
+ return AudioStandard::EDID;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_extra_audio_descriptor>
+aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
+ const ExtraAudioDescriptor& aidl) {
+ audio_extra_audio_descriptor legacy;
+ legacy.standard = VALUE_OR_RETURN(aidl2legacy_AudioStandard_audio_standard_t(aidl.standard));
+ if (aidl.audioDescriptor.size() > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
+ return unexpected(BAD_VALUE);
+ }
+ legacy.descriptor_length = aidl.audioDescriptor.size();
+ std::copy(aidl.audioDescriptor.begin(), aidl.audioDescriptor.end(),
+ std::begin(legacy.descriptor));
+ legacy.encapsulation_type =
+ VALUE_OR_RETURN(aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
+ aidl.encapsulationType));
+ return legacy;
+}
+
+ConversionResult<ExtraAudioDescriptor>
+legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
+ const audio_extra_audio_descriptor& legacy) {
+ ExtraAudioDescriptor aidl;
+ aidl.standard = VALUE_OR_RETURN(legacy2aidl_audio_standard_t_AudioStandard(legacy.standard));
+ if (legacy.descriptor_length > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
+ return unexpected(BAD_VALUE);
+ }
+ aidl.audioDescriptor.resize(legacy.descriptor_length);
+ std::copy(legacy.descriptor, legacy.descriptor + legacy.descriptor_length,
+ aidl.audioDescriptor.begin());
+ aidl.encapsulationType =
+ VALUE_OR_RETURN(legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+ legacy.encapsulation_type));
+ return aidl;
+}
+
+ConversionResult<audio_encapsulation_type_t>
+aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
+ const AudioEncapsulationType& aidl) {
+ switch (aidl) {
+ case AudioEncapsulationType::NONE:
+ return AUDIO_ENCAPSULATION_TYPE_NONE;
+ case AudioEncapsulationType::IEC61937:
+ return AUDIO_ENCAPSULATION_TYPE_IEC61937;
+ case AudioEncapsulationType::PCM:
+ return AUDIO_ENCAPSULATION_TYPE_PCM;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioEncapsulationType>
+legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+ const audio_encapsulation_type_t & legacy) {
+ switch (legacy) {
+ case AUDIO_ENCAPSULATION_TYPE_NONE:
+ return AudioEncapsulationType::NONE;
+ case AUDIO_ENCAPSULATION_TYPE_IEC61937:
+ return AudioEncapsulationType::IEC61937;
+ case AUDIO_ENCAPSULATION_TYPE_PCM:
+ return AudioEncapsulationType::PCM;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(AudioDualMonoMode aidl) {
+ switch (aidl) {
+ case AudioDualMonoMode::OFF:
+ return AUDIO_DUAL_MONO_MODE_OFF;
+ case AudioDualMonoMode::LR:
+ return AUDIO_DUAL_MONO_MODE_LR;
+ case AudioDualMonoMode::LL:
+ return AUDIO_DUAL_MONO_MODE_LL;
+ case AudioDualMonoMode::RR:
+ return AUDIO_DUAL_MONO_MODE_RR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_DUAL_MONO_MODE_OFF:
+ return AudioDualMonoMode::OFF;
+ case AUDIO_DUAL_MONO_MODE_LR:
+ return AudioDualMonoMode::LR;
+ case AUDIO_DUAL_MONO_MODE_LL:
+ return AudioDualMonoMode::LL;
+ case AUDIO_DUAL_MONO_MODE_RR:
+ return AudioDualMonoMode::RR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+ AudioPlaybackRate::TimestretchFallbackMode aidl) {
+ switch (aidl) {
+ case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT:
+ return AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT;
+ case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT:
+ return AUDIO_TIMESTRETCH_FALLBACK_DEFAULT;
+ case AudioPlaybackRate::TimestretchFallbackMode::MUTE:
+ return AUDIO_TIMESTRETCH_FALLBACK_MUTE;
+ case AudioPlaybackRate::TimestretchFallbackMode::FAIL:
+ return AUDIO_TIMESTRETCH_FALLBACK_FAIL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+ audio_timestretch_fallback_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
+ return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT;
+ case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
+ return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT;
+ case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
+ return AudioPlaybackRate::TimestretchFallbackMode::MUTE;
+ case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
+ return AudioPlaybackRate::TimestretchFallbackMode::FAIL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+ AudioPlaybackRate::TimestretchMode aidl) {
+ switch (aidl) {
+ case AudioPlaybackRate::TimestretchMode::DEFAULT:
+ return AUDIO_TIMESTRETCH_STRETCH_DEFAULT;
+ case AudioPlaybackRate::TimestretchMode::VOICE:
+ return AUDIO_TIMESTRETCH_STRETCH_VOICE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+ audio_timestretch_stretch_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_TIMESTRETCH_STRETCH_DEFAULT:
+ return AudioPlaybackRate::TimestretchMode::DEFAULT;
+ case AUDIO_TIMESTRETCH_STRETCH_VOICE:
+ return AudioPlaybackRate::TimestretchMode::VOICE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const AudioPlaybackRate& aidl) {
+ audio_playback_rate_t legacy;
+ legacy.mSpeed = aidl.speed;
+ legacy.mPitch = aidl.pitch;
+ legacy.mFallbackMode = VALUE_OR_RETURN(
+ aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+ aidl.fallbackMode));
+ legacy.mStretchMode = VALUE_OR_RETURN(
+ aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(aidl.timestretchMode));
+ return legacy;
+}
+
+ConversionResult<AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
+ AudioPlaybackRate aidl;
+ aidl.speed = legacy.mSpeed;
+ aidl.pitch = legacy.mPitch;
+ aidl.fallbackMode = VALUE_OR_RETURN(
+ legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+ legacy.mFallbackMode));
+ aidl.timestretchMode = VALUE_OR_RETURN(
+ legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(legacy.mStretchMode));
+ return aidl;
+}
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(AudioLatencyMode aidl) {
+ switch (aidl) {
+ case AudioLatencyMode::FREE:
+ return AUDIO_LATENCY_MODE_FREE;
+ case AudioLatencyMode::LOW:
+ return AUDIO_LATENCY_MODE_LOW;
+ case AudioLatencyMode::DYNAMIC_SPATIAL_AUDIO_SOFTWARE:
+ return AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_SOFTWARE;
+ case AudioLatencyMode::DYNAMIC_SPATIAL_AUDIO_HARDWARE:
+ return AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_HARDWARE;
+ }
+ return unexpected(BAD_VALUE);
+}
+ConversionResult<AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_LATENCY_MODE_FREE:
+ return AudioLatencyMode::FREE;
+ case AUDIO_LATENCY_MODE_LOW:
+ return AudioLatencyMode::LOW;
+ case AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_SOFTWARE:
+ return AudioLatencyMode::DYNAMIC_SPATIAL_AUDIO_SOFTWARE;
+ case AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_HARDWARE:
+ return AudioLatencyMode::DYNAMIC_SPATIAL_AUDIO_HARDWARE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_microphone_location_t>
+aidl2legacy_MicrophoneInfoLocation_audio_microphone_location_t(MicrophoneInfo::Location aidl) {
+ switch (aidl) {
+ case MicrophoneInfo::Location::UNKNOWN:
+ return AUDIO_MICROPHONE_LOCATION_UNKNOWN;
+ case MicrophoneInfo::Location::MAINBODY:
+ return AUDIO_MICROPHONE_LOCATION_MAINBODY;
+ case MicrophoneInfo::Location::MAINBODY_MOVABLE:
+ return AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE;
+ case MicrophoneInfo::Location::PERIPHERAL:
+ return AUDIO_MICROPHONE_LOCATION_PERIPHERAL;
+ }
+ return unexpected(BAD_VALUE);
+}
+ConversionResult<MicrophoneInfo::Location>
+legacy2aidl_audio_microphone_location_t_MicrophoneInfoLocation(audio_microphone_location_t legacy) {
+ switch (legacy) {
+ case AUDIO_MICROPHONE_LOCATION_UNKNOWN:
+ return MicrophoneInfo::Location::UNKNOWN;
+ case AUDIO_MICROPHONE_LOCATION_MAINBODY:
+ return MicrophoneInfo::Location::MAINBODY;
+ case AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE:
+ return MicrophoneInfo::Location::MAINBODY_MOVABLE;
+ case AUDIO_MICROPHONE_LOCATION_PERIPHERAL:
+ return MicrophoneInfo::Location::PERIPHERAL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_microphone_group_t> aidl2legacy_int32_t_audio_microphone_group_t(
+ int32_t aidl) {
+ return convertReinterpret<audio_microphone_group_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_microphone_group_t_int32_t(
+ audio_microphone_group_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_microphone_directionality_t>
+aidl2legacy_MicrophoneInfoDirectionality_audio_microphone_directionality_t(
+ MicrophoneInfo::Directionality aidl) {
+ switch (aidl) {
+ case MicrophoneInfo::Directionality::UNKNOWN:
+ return AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN;
+ case MicrophoneInfo::Directionality::OMNI:
+ return AUDIO_MICROPHONE_DIRECTIONALITY_OMNI;
+ case MicrophoneInfo::Directionality::BI_DIRECTIONAL:
+ return AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL;
+ case MicrophoneInfo::Directionality::CARDIOID:
+ return AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID;
+ case MicrophoneInfo::Directionality::HYPER_CARDIOID:
+ return AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID;
+ case MicrophoneInfo::Directionality::SUPER_CARDIOID:
+ return AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID;
+ }
+ return unexpected(BAD_VALUE);
+}
+ConversionResult<MicrophoneInfo::Directionality>
+legacy2aidl_audio_microphone_directionality_t_MicrophoneInfoDirectionality(
+ audio_microphone_directionality_t legacy) {
+ switch (legacy) {
+ case AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN:
+ return MicrophoneInfo::Directionality::UNKNOWN;
+ case AUDIO_MICROPHONE_DIRECTIONALITY_OMNI:
+ return MicrophoneInfo::Directionality::OMNI;
+ case AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL:
+ return MicrophoneInfo::Directionality::BI_DIRECTIONAL;
+ case AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID:
+ return MicrophoneInfo::Directionality::CARDIOID;
+ case AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID:
+ return MicrophoneInfo::Directionality::HYPER_CARDIOID;
+ case AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID:
+ return MicrophoneInfo::Directionality::SUPER_CARDIOID;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_microphone_coordinate>
+aidl2legacy_MicrophoneInfoCoordinate_audio_microphone_coordinate(
+ const MicrophoneInfo::Coordinate& aidl) {
+ audio_microphone_coordinate legacy;
+ legacy.x = aidl.x;
+ legacy.y = aidl.y;
+ legacy.z = aidl.z;
+ return legacy;
+}
+ConversionResult<MicrophoneInfo::Coordinate>
+legacy2aidl_audio_microphone_coordinate_MicrophoneInfoCoordinate(
+ const audio_microphone_coordinate& legacy) {
+ MicrophoneInfo::Coordinate aidl;
+ aidl.x = legacy.x;
+ aidl.y = legacy.y;
+ aidl.z = legacy.z;
+ return aidl;
+}
+
+ConversionResult<audio_microphone_channel_mapping_t>
+aidl2legacy_MicrophoneDynamicInfoChannelMapping_audio_microphone_channel_mapping_t(
+ MicrophoneDynamicInfo::ChannelMapping aidl) {
+ switch (aidl) {
+ case MicrophoneDynamicInfo::ChannelMapping::UNUSED:
+ return AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
+ case MicrophoneDynamicInfo::ChannelMapping::DIRECT:
+ return AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT;
+ case MicrophoneDynamicInfo::ChannelMapping::PROCESSED:
+ return AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED;
+ }
+ return unexpected(BAD_VALUE);
+}
+ConversionResult<MicrophoneDynamicInfo::ChannelMapping>
+legacy2aidl_audio_microphone_channel_mapping_t_MicrophoneDynamicInfoChannelMapping(
+ audio_microphone_channel_mapping_t legacy) {
+ switch (legacy) {
+ case AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED:
+ return MicrophoneDynamicInfo::ChannelMapping::UNUSED;
+ case AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT:
+ return MicrophoneDynamicInfo::ChannelMapping::DIRECT;
+ case AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED:
+ return MicrophoneDynamicInfo::ChannelMapping::PROCESSED;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_microphone_characteristic_t>
+aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t(
+ const MicrophoneInfo& aidlInfo, const MicrophoneDynamicInfo& aidlDynamic) {
+ static const audio_microphone_coordinate kCoordinateUnknown = {
+ AUDIO_MICROPHONE_COORDINATE_UNKNOWN, AUDIO_MICROPHONE_COORDINATE_UNKNOWN,
+ AUDIO_MICROPHONE_COORDINATE_UNKNOWN };
+ audio_microphone_characteristic_t legacy{};
+ if (aidlInfo.id != aidlDynamic.id) {
+ return unexpected(BAD_VALUE);
+ }
+ // Note: in the legacy structure, 'device_id' is the mic's ID, 'id' is APM port id.
+ RETURN_IF_ERROR(aidl2legacy_string(aidlInfo.id, legacy.device_id, AUDIO_MICROPHONE_ID_MAX_LEN));
+ RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+ aidlInfo.device, &legacy.device, legacy.address));
+ legacy.location = VALUE_OR_RETURN(
+ aidl2legacy_MicrophoneInfoLocation_audio_microphone_location_t(aidlInfo.location));
+ legacy.group = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_microphone_group_t(aidlInfo.group));
+ // For some reason, the legacy field is unsigned, however in the SDK layer it is signed,
+ // as it is in AIDL. So, use UINT_MAX for INDEX_IN_THE_GROUP_UNKNOWN which is -1.
+ if (aidlInfo.indexInTheGroup != MicrophoneInfo::INDEX_IN_THE_GROUP_UNKNOWN) {
+ legacy.index_in_the_group = VALUE_OR_RETURN(
+ convertReinterpret<unsigned int>(aidlInfo.indexInTheGroup));
+ } else {
+ legacy.index_in_the_group = UINT_MAX;
+ }
+ if (aidlInfo.sensitivity.has_value()) {
+ legacy.sensitivity = aidlInfo.sensitivity.value().leveldBFS;
+ legacy.max_spl = aidlInfo.sensitivity.value().maxSpldB;
+ legacy.min_spl = aidlInfo.sensitivity.value().minSpldB;
+ } else {
+ legacy.sensitivity = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN;
+ legacy.max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
+ legacy.min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
+ }
+ legacy.directionality = VALUE_OR_RETURN(
+ aidl2legacy_MicrophoneInfoDirectionality_audio_microphone_directionality_t(
+ aidlInfo.directionality));
+ if (aidlInfo.frequencyResponse.size() > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+ return unexpected(BAD_VALUE);
+ }
+ legacy.num_frequency_responses = 0;
+ for (const auto& p: aidlInfo.frequencyResponse) {
+ legacy.frequency_responses[0][legacy.num_frequency_responses] = p.frequencyHz;
+ legacy.frequency_responses[1][legacy.num_frequency_responses++] = p.leveldB;
+ }
+ if (aidlInfo.position.has_value()) {
+ legacy.geometric_location = VALUE_OR_RETURN(
+ aidl2legacy_MicrophoneInfoCoordinate_audio_microphone_coordinate(
+ aidlInfo.position.value()));
+ } else {
+ legacy.geometric_location = kCoordinateUnknown;
+ }
+ if (aidlInfo.orientation.has_value()) {
+ legacy.orientation = VALUE_OR_RETURN(
+ aidl2legacy_MicrophoneInfoCoordinate_audio_microphone_coordinate(
+ aidlInfo.orientation.value()));
+ } else {
+ legacy.orientation = kCoordinateUnknown;
+ }
+ if (aidlDynamic.channelMapping.size() > AUDIO_CHANNEL_COUNT_MAX) {
+ return unexpected(BAD_VALUE);
+ }
+ size_t i = 0;
+ for (; i < aidlDynamic.channelMapping.size(); ++i) {
+ legacy.channel_mapping[i] = VALUE_OR_RETURN(
+ aidl2legacy_MicrophoneDynamicInfoChannelMapping_audio_microphone_channel_mapping_t(
+ aidlDynamic.channelMapping[i]));
+ }
+ for (; i < AUDIO_CHANNEL_COUNT_MAX; ++i) {
+ legacy.channel_mapping[i] = AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
+ }
+ return legacy;
+}
+
+status_t
+legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfos(
+ const audio_microphone_characteristic_t& legacy,
+ MicrophoneInfo* aidlInfo, MicrophoneDynamicInfo* aidlDynamic) {
+ aidlInfo->id = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_string(legacy.device_id, AUDIO_MICROPHONE_ID_MAX_LEN));
+ aidlDynamic->id = aidlInfo->id;
+ aidlInfo->device = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_device_AudioDevice(
+ legacy.device, legacy.address));
+ aidlInfo->location = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_microphone_location_t_MicrophoneInfoLocation(legacy.location));
+ aidlInfo->group = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_microphone_group_t_int32_t(legacy.group));
+ // For some reason, the legacy field is unsigned, however in the SDK layer it is signed,
+ // as it is in AIDL. So, use UINT_MAX for INDEX_IN_THE_GROUP_UNKNOWN which is -1.
+ if (legacy.index_in_the_group != UINT_MAX) {
+ aidlInfo->indexInTheGroup = VALUE_OR_RETURN_STATUS(
+ convertReinterpret<int32_t>(legacy.index_in_the_group));
+ } else {
+ aidlInfo->indexInTheGroup = MicrophoneInfo::INDEX_IN_THE_GROUP_UNKNOWN;
+ }
+ if (legacy.sensitivity != AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN &&
+ legacy.max_spl != AUDIO_MICROPHONE_SPL_UNKNOWN &&
+ legacy.min_spl != AUDIO_MICROPHONE_SPL_UNKNOWN) {
+ MicrophoneInfo::Sensitivity sensitivity;
+ sensitivity.leveldBFS = legacy.sensitivity;
+ sensitivity.maxSpldB = legacy.max_spl;
+ sensitivity.minSpldB = legacy.min_spl;
+ aidlInfo->sensitivity = std::move(sensitivity);
+ } else {
+ aidlInfo->sensitivity = {};
+ }
+ aidlInfo->directionality = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_microphone_directionality_t_MicrophoneInfoDirectionality(
+ legacy.directionality));
+ if (legacy.num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+ return BAD_VALUE;
+ }
+ aidlInfo->frequencyResponse.resize(legacy.num_frequency_responses);
+ for (size_t i = 0; i < legacy.num_frequency_responses; ++i) {
+ aidlInfo->frequencyResponse[i].frequencyHz = legacy.frequency_responses[0][i];
+ aidlInfo->frequencyResponse[i].leveldB = legacy.frequency_responses[1][i];
+ }
+ if (legacy.geometric_location.x != AUDIO_MICROPHONE_COORDINATE_UNKNOWN &&
+ legacy.geometric_location.y != AUDIO_MICROPHONE_COORDINATE_UNKNOWN &&
+ legacy.geometric_location.z != AUDIO_MICROPHONE_COORDINATE_UNKNOWN) {
+ aidlInfo->position = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_microphone_coordinate_MicrophoneInfoCoordinate(
+ legacy.geometric_location));
+ } else {
+ aidlInfo->position = {};
+ }
+ if (legacy.orientation.x != AUDIO_MICROPHONE_COORDINATE_UNKNOWN &&
+ legacy.orientation.y != AUDIO_MICROPHONE_COORDINATE_UNKNOWN &&
+ legacy.orientation.z != AUDIO_MICROPHONE_COORDINATE_UNKNOWN) {
+ aidlInfo->orientation = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_microphone_coordinate_MicrophoneInfoCoordinate(
+ legacy.orientation));
+ } else {
+ aidlInfo->orientation = {};
+ }
+ size_t channelsUsed = AUDIO_CHANNEL_COUNT_MAX;
+ while (channelsUsed != 0 &&
+ legacy.channel_mapping[--channelsUsed] == AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {}
+ // Doing an increment is correct even when channel 0 is 'UNUSED',
+ // that's because AIDL requires to have at least 1 element in the mapping.
+ ++channelsUsed;
+ aidlDynamic->channelMapping.resize(channelsUsed);
+ for (size_t i = 0; i < channelsUsed; ++i) {
+ aidlDynamic->channelMapping[i] = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_microphone_channel_mapping_t_MicrophoneDynamicInfoChannelMapping(
+ legacy.channel_mapping[i]));
+ }
+ return OK;
+}
+
+} // namespace android
+
+#if defined(BACKEND_NDK)
+} // aidl
+#endif
diff --git a/media/audioaidlconversion/AidlConversionEffect.cpp b/media/audioaidlconversion/AidlConversionEffect.cpp
new file mode 100644
index 0000000..611cfab
--- /dev/null
+++ b/media/audioaidlconversion/AidlConversionEffect.cpp
@@ -0,0 +1,475 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <inttypes.h>
+#include <utility>
+
+#define LOG_TAG "AidlConversionEffect"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <aidl/android/hardware/audio/effect/DefaultExtension.h>
+#include <aidl/android/hardware/audio/effect/VendorExtension.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionEffect.h>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// AIDL NDK backend to legacy audio data structure conversion utilities.
+
+namespace aidl {
+namespace android {
+
+using ::aidl::android::hardware::audio::effect::AcousticEchoCanceler;
+using ::aidl::android::hardware::audio::effect::AutomaticGainControlV2;
+using ::aidl::android::hardware::audio::effect::BassBoost;
+using ::aidl::android::hardware::audio::effect::DefaultExtension;
+using ::aidl::android::hardware::audio::effect::Descriptor;
+using ::aidl::android::hardware::audio::effect::Downmix;
+using ::aidl::android::hardware::audio::effect::DynamicsProcessing;
+using ::aidl::android::hardware::audio::effect::Flags;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::PresetReverb;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::aidl::android::hardware::audio::effect::Visualizer;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+
+using ::android::BAD_VALUE;
+using ::android::OK;
+using ::android::status_t;
+using ::android::base::unexpected;
+using ::android::effect::utils::EffectParamReader;
+using ::android::effect::utils::EffectParamWriter;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Converters
+
+ConversionResult<uint32_t> aidl2legacy_Flags_Type_uint32(Flags::Type type) {
+ switch (type) {
+ case Flags::Type::INSERT:
+ return EFFECT_FLAG_TYPE_INSERT;
+ case Flags::Type::AUXILIARY:
+ return EFFECT_FLAG_TYPE_AUXILIARY;
+ case Flags::Type::REPLACE:
+ return EFFECT_FLAG_TYPE_REPLACE;
+ case Flags::Type::PRE_PROC:
+ return EFFECT_FLAG_TYPE_PRE_PROC;
+ case Flags::Type::POST_PROC:
+ return EFFECT_FLAG_TYPE_POST_PROC;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Flags::Type> legacy2aidl_uint32_Flags_Type(uint32_t legacy) {
+ switch (legacy & EFFECT_FLAG_TYPE_MASK) {
+ case EFFECT_FLAG_TYPE_INSERT:
+ return Flags::Type::INSERT;
+ case EFFECT_FLAG_TYPE_AUXILIARY:
+ return Flags::Type::AUXILIARY;
+ case EFFECT_FLAG_TYPE_REPLACE:
+ return Flags::Type::REPLACE;
+ case EFFECT_FLAG_TYPE_PRE_PROC:
+ return Flags::Type::PRE_PROC;
+ case EFFECT_FLAG_TYPE_POST_PROC:
+ return Flags::Type::POST_PROC;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Flags_Insert_uint32(Flags::Insert insert) {
+ switch (insert) {
+ case Flags::Insert::ANY:
+ return EFFECT_FLAG_INSERT_ANY;
+ case Flags::Insert::FIRST:
+ return EFFECT_FLAG_INSERT_FIRST;
+ case Flags::Insert::LAST:
+ return EFFECT_FLAG_INSERT_LAST;
+ case Flags::Insert::EXCLUSIVE:
+ return EFFECT_FLAG_INSERT_EXCLUSIVE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Flags::Insert> legacy2aidl_uint32_Flags_Insert(uint32_t legacy) {
+ switch (legacy & EFFECT_FLAG_INSERT_MASK) {
+ case EFFECT_FLAG_INSERT_ANY:
+ return Flags::Insert::ANY;
+ case EFFECT_FLAG_INSERT_FIRST:
+ return Flags::Insert::FIRST;
+ case EFFECT_FLAG_INSERT_LAST:
+ return Flags::Insert::LAST;
+ case EFFECT_FLAG_INSERT_EXCLUSIVE:
+ return Flags::Insert::EXCLUSIVE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Flags_Volume_uint32(Flags::Volume volume) {
+ switch (volume) {
+ case Flags::Volume::NONE:
+ return 0;
+ case Flags::Volume::CTRL:
+ return EFFECT_FLAG_VOLUME_CTRL;
+ case Flags::Volume::IND:
+ return EFFECT_FLAG_VOLUME_IND;
+ case Flags::Volume::MONITOR:
+ return EFFECT_FLAG_VOLUME_MONITOR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Flags::Volume> legacy2aidl_uint32_Flags_Volume(uint32_t legacy) {
+ switch (legacy & EFFECT_FLAG_VOLUME_MASK) {
+ case EFFECT_FLAG_VOLUME_CTRL:
+ return Flags::Volume::CTRL;
+ case EFFECT_FLAG_VOLUME_IND:
+ return Flags::Volume::IND;
+ case EFFECT_FLAG_VOLUME_MONITOR:
+ return Flags::Volume::MONITOR;
+ case EFFECT_FLAG_VOLUME_NONE:
+ return Flags::Volume::NONE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Flags_uint32(Flags aidl) {
+ uint32_t legacy = 0;
+ legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_Type_uint32(aidl.type));
+ legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_Insert_uint32(aidl.insert));
+ legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_Volume_uint32(aidl.volume));
+ legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_HardwareAccelerator_uint32(aidl.hwAcceleratorMode));
+
+ if (aidl.offloadIndication) {
+ legacy |= EFFECT_FLAG_OFFLOAD_SUPPORTED;
+ }
+ if (aidl.deviceIndication) {
+ legacy |= EFFECT_FLAG_DEVICE_IND;
+ }
+ if (aidl.audioModeIndication) {
+ legacy |= EFFECT_FLAG_AUDIO_MODE_IND;
+ }
+ if (aidl.audioSourceIndication) {
+ legacy |= EFFECT_FLAG_AUDIO_SOURCE_IND;
+ }
+ if (aidl.bypass) {
+ legacy |= EFFECT_FLAG_NO_PROCESS;
+ }
+ return legacy;
+}
+
+ConversionResult<Flags> legacy2aidl_uint32_Flags(uint32_t legacy) {
+ Flags aidl;
+
+ aidl.type = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_Type(legacy));
+ aidl.insert = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_Insert(legacy));
+ aidl.volume = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_Volume(legacy));
+ aidl.hwAcceleratorMode = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_HardwareAccelerator(legacy));
+ aidl.offloadIndication = (legacy & EFFECT_FLAG_OFFLOAD_SUPPORTED);
+ aidl.deviceIndication = (legacy & EFFECT_FLAG_DEVICE_IND);
+ aidl.audioModeIndication = (legacy & EFFECT_FLAG_AUDIO_MODE_IND);
+ aidl.audioSourceIndication = (legacy & EFFECT_FLAG_AUDIO_SOURCE_IND);
+ aidl.bypass = (legacy & EFFECT_FLAG_NO_PROCESS);
+ return aidl;
+}
+
+ConversionResult<uint32_t> aidl2legacy_Flags_HardwareAccelerator_uint32(
+ Flags::HardwareAccelerator hwAcceleratorMode) {
+ switch (hwAcceleratorMode) {
+ case Flags::HardwareAccelerator::NONE:
+ return 0;
+ case Flags::HardwareAccelerator::SIMPLE:
+ return EFFECT_FLAG_HW_ACC_SIMPLE;
+ case Flags::HardwareAccelerator::TUNNEL:
+ return EFFECT_FLAG_HW_ACC_TUNNEL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Flags::HardwareAccelerator> legacy2aidl_uint32_Flags_HardwareAccelerator(
+ uint32_t legacy) {
+ switch (legacy & EFFECT_FLAG_HW_ACC_MASK) {
+ case EFFECT_FLAG_HW_ACC_SIMPLE:
+ return Flags::HardwareAccelerator::SIMPLE;
+ case EFFECT_FLAG_HW_ACC_TUNNEL:
+ return Flags::HardwareAccelerator::TUNNEL;
+ case 0:
+ return Flags::HardwareAccelerator::NONE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<effect_descriptor_t>
+aidl2legacy_Descriptor_effect_descriptor(const Descriptor& aidl) {
+ effect_descriptor_t legacy;
+ legacy.type = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.common.id.type));
+ legacy.uuid = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.common.id.uuid));
+ // legacy descriptor doesn't have proxy information
+ // proxy = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.proxy));
+ legacy.apiVersion = EFFECT_CONTROL_API_VERSION;
+ legacy.flags = VALUE_OR_RETURN(aidl2legacy_Flags_uint32(aidl.common.flags));
+ legacy.cpuLoad = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.common.cpuLoad));
+ legacy.memoryUsage = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.common.memoryUsage));
+ RETURN_IF_ERROR(aidl2legacy_string(aidl.common.name, legacy.name, sizeof(legacy.name)));
+ RETURN_IF_ERROR(aidl2legacy_string(aidl.common.implementor, legacy.implementor,
+ sizeof(legacy.implementor)));
+ return legacy;
+}
+
+ConversionResult<Descriptor>
+legacy2aidl_effect_descriptor_Descriptor(const effect_descriptor_t& legacy) {
+ Descriptor aidl;
+ aidl.common.id.type = VALUE_OR_RETURN(legacy2aidl_audio_uuid_t_AudioUuid(legacy.type));
+ aidl.common.id.uuid = VALUE_OR_RETURN(legacy2aidl_audio_uuid_t_AudioUuid(legacy.uuid));
+ // legacy descriptor doesn't have proxy information
+ // aidl.common.id.proxy
+ aidl.common.flags = VALUE_OR_RETURN(legacy2aidl_uint32_Flags(legacy.flags));
+ aidl.common.cpuLoad = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.cpuLoad));
+ aidl.common.memoryUsage = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.memoryUsage));
+ aidl.common.name = VALUE_OR_RETURN(legacy2aidl_string(legacy.name, sizeof(legacy.name)));
+ aidl.common.implementor =
+ VALUE_OR_RETURN(legacy2aidl_string(legacy.implementor, sizeof(legacy.implementor)));
+ return aidl;
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_echoDelay(const Parameter& aidl) {
+ int echoDelay = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, AcousticEchoCanceler, acousticEchoCanceler,
+ AcousticEchoCanceler::echoDelayUs, int));
+ return VALUE_OR_RETURN(convertReinterpret<uint32_t>(echoDelay));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_echoDelay_Parameter_aec(uint32_t legacy) {
+ int delay = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy));
+ return MAKE_SPECIFIC_PARAMETER(AcousticEchoCanceler, acousticEchoCanceler, echoDelayUs, delay);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_mobileMode(const Parameter& aidl) {
+ bool mobileMode = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, AcousticEchoCanceler, acousticEchoCanceler,
+ AcousticEchoCanceler::mobileMode, bool));
+ return VALUE_OR_RETURN(convertIntegral<uint32_t>(mobileMode));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_mobileMode_Parameter_aec(uint32_t legacy) {
+ bool mode = VALUE_OR_RETURN(convertIntegral<bool>(legacy));
+ return MAKE_SPECIFIC_PARAMETER(AcousticEchoCanceler, acousticEchoCanceler, mobileMode, mode);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(
+ const Parameter& aidl) {
+ int gain = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, AutomaticGainControlV2, automaticGainControlV2,
+ AutomaticGainControlV2::fixedDigitalGainMb, int));
+ return VALUE_OR_RETURN(convertReinterpret<uint32_t>(gain));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_fixedDigitalGain_Parameter_agc(uint32_t legacy) {
+ int gain = VALUE_OR_RETURN(convertReinterpret<int>(legacy));
+ return MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV2, automaticGainControlV2,
+ fixedDigitalGainMb, gain);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_levelEstimator(
+ const Parameter& aidl) {
+ const auto& le = VALUE_OR_RETURN(GET_PARAMETER_SPECIFIC_FIELD(
+ aidl, AutomaticGainControlV2, automaticGainControlV2,
+ AutomaticGainControlV2::levelEstimator, AutomaticGainControlV2::LevelEstimator));
+ return static_cast<uint32_t>(le);
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_levelEstimator_Parameter_agc(uint32_t legacy) {
+ if (legacy > (uint32_t)AutomaticGainControlV2::LevelEstimator::PEAK) {
+ return unexpected(BAD_VALUE);
+ }
+ AutomaticGainControlV2::LevelEstimator le =
+ static_cast<AutomaticGainControlV2::LevelEstimator>(legacy);
+ return MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV2, automaticGainControlV2, levelEstimator,
+ le);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_saturationMargin(
+ const Parameter& aidl) {
+ int saturationMargin = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, AutomaticGainControlV2, automaticGainControlV2,
+ AutomaticGainControlV2::saturationMarginMb, int));
+ return VALUE_OR_RETURN(convertIntegral<uint32_t>(saturationMargin));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_saturationMargin_Parameter_agc(uint32_t legacy) {
+ int saturationMargin = VALUE_OR_RETURN(convertIntegral<int>(legacy));
+ return MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV2, automaticGainControlV2,
+ saturationMarginMb, saturationMargin);
+}
+
+ConversionResult<uint16_t> aidl2legacy_Parameter_BassBoost_uint16_strengthPm(
+ const Parameter& aidl) {
+ int strength = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, BassBoost, bassBoost, BassBoost::strengthPm, int));
+ return VALUE_OR_RETURN(convertIntegral<uint16_t>(strength));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint16_strengthPm_Parameter_BassBoost(uint16_t legacy) {
+ int strength = VALUE_OR_RETURN(convertIntegral<int>(legacy));
+ return MAKE_SPECIFIC_PARAMETER(BassBoost, bassBoost, strengthPm, strength);
+}
+
+ConversionResult<int16_t> aidl2legacy_Parameter_Downmix_int16_type(const Parameter& aidl) {
+ Downmix::Type aidlType = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, Downmix, downmix, Downmix::type, Downmix::Type));
+ return VALUE_OR_RETURN(convertIntegral<int16_t>(static_cast<uint32_t>(aidlType)));
+}
+
+ConversionResult<Parameter> legacy2aidl_int16_type_Parameter_Downmix(int16_t legacy) {
+ if (legacy > (uint32_t) Downmix::Type::FOLD) {
+ return unexpected(BAD_VALUE);
+ }
+ Downmix::Type aidlType = static_cast<Downmix::Type>(legacy);
+ return MAKE_SPECIFIC_PARAMETER(Downmix, downmix, type, aidlType);
+}
+
+ConversionResult<int16_t> aidl2legacy_DynamicsProcessing_ResolutionPreference_uint32_(
+ const Parameter& aidl) {
+ Downmix::Type aidlType = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, Downmix, downmix, Downmix::type, Downmix::Type));
+ return VALUE_OR_RETURN(convertIntegral<int16_t>(static_cast<uint32_t>(aidlType)));
+}
+
+ConversionResult<DynamicsProcessing::ResolutionPreference>
+legacy2aidl_int32_DynamicsProcessing_ResolutionPreference(int32_t legacy) {
+ if (legacy > (int32_t)DynamicsProcessing::ResolutionPreference::FAVOR_TIME_RESOLUTION) {
+ return unexpected(BAD_VALUE);
+ }
+ return static_cast<DynamicsProcessing::ResolutionPreference>(legacy);
+}
+
+ConversionResult<int32_t> aidl2legacy_DynamicsProcessing_ResolutionPreference_int32(
+ DynamicsProcessing::ResolutionPreference aidl) {
+ return static_cast<int32_t>(aidl);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_ScalingMode_uint32(
+ Visualizer::ScalingMode aidl) {
+ switch (aidl) {
+ case Visualizer::ScalingMode::NORMALIZED: {
+ return 0;
+ }
+ case Visualizer::ScalingMode::AS_PLAYED: {
+ return 1;
+ }
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Visualizer::ScalingMode> legacy2aidl_Parameter_Visualizer_uint32_ScalingMode(
+ uint32_t legacy) {
+ if (legacy == 0) {
+ return Visualizer::ScalingMode::NORMALIZED;
+ } else if (legacy == 1) {
+ return Visualizer::ScalingMode::AS_PLAYED;
+ } else {
+ return unexpected(BAD_VALUE);
+ }
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_MeasurementMode_uint32(
+ Visualizer::MeasurementMode aidl) {
+ switch (aidl) {
+ case Visualizer::MeasurementMode::NONE: {
+ return 0;
+ }
+ case Visualizer::MeasurementMode::PEAK_RMS: {
+ return 1;
+ }
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Visualizer::MeasurementMode>
+legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(uint32_t legacy) {
+ if (legacy == 0) {
+ return Visualizer::MeasurementMode::NONE;
+ } else if (legacy == 1) {
+ return Visualizer::MeasurementMode::PEAK_RMS;
+ } else {
+ return unexpected(BAD_VALUE);
+ }
+}
+
+/**
+ * Copy the parameter area of effect_param_t to DefaultExtension::bytes.
+ */
+ConversionResult<VendorExtension> legacy2aidl_EffectParameterReader_Param_VendorExtension(
+ EffectParamReader& param) {
+ size_t len = param.getParameterSize();
+ DefaultExtension defaultExt;
+ defaultExt.bytes.resize(len);
+ RETURN_IF_ERROR(param.readFromParameter(defaultExt.bytes.data(), len));
+
+ VendorExtension ext;
+ ext.extension.setParcelable(defaultExt);
+ return ext;
+}
+
+/**
+ * Copy the data area of effect_param_t to DefaultExtension::bytes.
+ */
+ConversionResult<VendorExtension> legacy2aidl_EffectParameterReader_Data_VendorExtension(
+ EffectParamReader& param) {
+ size_t len = param.getValueSize();
+ DefaultExtension defaultExt;
+ defaultExt.bytes.resize(len);
+ RETURN_IF_ERROR(param.readFromValue(defaultExt.bytes.data(), len));
+
+ VendorExtension ext;
+ ext.extension.setParcelable(defaultExt);
+ return ext;
+}
+
+/**
+ * Copy DefaultExtension::bytes to the data area of effect_param_t.
+ */
+ConversionResult<status_t> aidl2legacy_VendorExtension_EffectParameterWriter_Data(
+ EffectParamWriter& param, VendorExtension ext) {
+ std::optional<DefaultExtension> defaultExt;
+ RETURN_IF_ERROR(ext.extension.getParcelable(&defaultExt));
+ if (!defaultExt.has_value()) {
+ return unexpected(BAD_VALUE);
+ }
+
+ RETURN_IF_ERROR(param.writeToValue(defaultExt->bytes.data(), defaultExt->bytes.size()));
+
+ return OK;
+}
+
+ConversionResult<Parameter> legacy2aidl_EffectParameterReader_ParameterExtension(
+ EffectParamReader& param) {
+ VendorExtension ext =
+ VALUE_OR_RETURN(legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ return UNION_MAKE(Parameter, specific, UNION_MAKE(Parameter::Specific, vendorEffect, ext));
+}
+
+ConversionResult<::android::status_t> aidl2legacy_ParameterExtension_EffectParameterWriter(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl,
+ EffectParamWriter& legacy) {
+ VendorExtension ext = VALUE_OR_RETURN(
+ (::aidl::android::getParameterSpecific<Parameter, VendorExtension,
+ Parameter::Specific::vendorEffect>(aidl)));
+ return VALUE_OR_RETURN_STATUS(
+ aidl2legacy_VendorExtension_EffectParameterWriter_Data(legacy, ext));
+}
+
+} // namespace android
+} // aidl
diff --git a/media/audioaidlconversion/AidlConversionNdk.cpp b/media/audioaidlconversion/AidlConversionNdk.cpp
new file mode 100644
index 0000000..71c547c
--- /dev/null
+++ b/media/audioaidlconversion/AidlConversionNdk.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2022 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 <sstream>
+#include <utility>
+
+#include <system/audio.h>
+#define LOG_TAG "AidlConversionNdk"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+#include <utils/Errors.h>
+
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <Utils.h>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// AIDL NDK backend to legacy audio data structure conversion utilities.
+
+namespace aidl {
+namespace android {
+
+using hardware::audio::common::PlaybackTrackMetadata;
+using hardware::audio::common::RecordTrackMetadata;
+using ::android::BAD_VALUE;
+using ::android::OK;
+
+namespace {
+
+::android::status_t combineString(
+ const std::vector<std::string>& v, char separator, std::string* result) {
+ std::ostringstream oss;
+ for (const auto& s : v) {
+ if (oss.tellp() > 0) {
+ oss << separator;
+ }
+ if (s.find(separator) == std::string::npos) {
+ oss << s;
+ } else {
+ ALOGE("%s: string \"%s\" contains separator character \"%c\"",
+ __func__, s.c_str(), separator);
+ return BAD_VALUE;
+ }
+ }
+ *result = oss.str();
+ return OK;
+}
+
+std::vector<std::string> splitString(const std::string& s, char separator) {
+ std::istringstream iss(s);
+ std::string t;
+ std::vector<std::string> result;
+ while (std::getline(iss, t, separator)) {
+ result.push_back(std::move(t));
+ }
+ return result;
+}
+
+std::vector<std::string> filterOutNonVendorTags(const std::vector<std::string>& tags) {
+ std::vector<std::string> result;
+ std::copy_if(tags.begin(), tags.end(), std::back_inserter(result),
+ ::aidl::android::hardware::audio::common::maybeVendorExtension);
+ return result;
+}
+
+} // namespace
+
+// buffer_provider_t is not supported thus skipped
+ConversionResult<buffer_config_t> aidl2legacy_AudioConfigBase_buffer_config_t(
+ const media::audio::common::AudioConfigBase& aidl, bool isInput) {
+ buffer_config_t legacy;
+
+ legacy.samplingRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
+ legacy.mask |= EFFECT_CONFIG_SMP_RATE;
+
+ legacy.channels = VALUE_OR_RETURN(
+ aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
+ legacy.mask |= EFFECT_CONFIG_CHANNELS;
+
+ legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
+ legacy.mask |= EFFECT_CONFIG_FORMAT;
+
+ // TODO: add accessMode and mask
+ return legacy;
+}
+
+ConversionResult<media::audio::common::AudioConfigBase>
+legacy2aidl_buffer_config_t_AudioConfigBase(const buffer_config_t& legacy, bool isInput) {
+ media::audio::common::AudioConfigBase aidl;
+
+ if (legacy.mask & EFFECT_CONFIG_SMP_RATE) {
+ aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.samplingRate));
+ }
+ if (legacy.mask & EFFECT_CONFIG_CHANNELS) {
+ aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+ static_cast<audio_channel_mask_t>(legacy.channels), isInput));
+ }
+ if (legacy.mask & EFFECT_CONFIG_FORMAT) {
+ aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(
+ static_cast<audio_format_t>(legacy.format)));
+ }
+
+ // TODO: add accessMode and mask
+ return aidl;
+}
+
+::android::status_t aidl2legacy_AudioAttributesTags(
+ const std::vector<std::string>& aidl, char* legacy) {
+ std::string aidlTags;
+ RETURN_STATUS_IF_ERROR(combineString(
+ filterOutNonVendorTags(aidl), AUDIO_ATTRIBUTES_TAGS_SEPARATOR, &aidlTags));
+ RETURN_STATUS_IF_ERROR(aidl2legacy_string(aidlTags, legacy, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE));
+ return OK;
+}
+
+ConversionResult<std::vector<std::string>> legacy2aidl_AudioAttributesTags(const char* legacy) {
+ std::string legacyTags = VALUE_OR_RETURN(legacy2aidl_string(
+ legacy, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE));
+ return filterOutNonVendorTags(splitString(legacyTags, AUDIO_ATTRIBUTES_TAGS_SEPARATOR));
+}
+
+ConversionResult<playback_track_metadata_v7>
+aidl2legacy_PlaybackTrackMetadata_playback_track_metadata_v7(const PlaybackTrackMetadata& aidl) {
+ playback_track_metadata_v7 legacy;
+ legacy.base.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
+ legacy.base.content_type = VALUE_OR_RETURN(aidl2legacy_AudioContentType_audio_content_type_t(
+ aidl.contentType));
+ legacy.base.gain = aidl.gain;
+ legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ aidl.channelMask, false /*isInput*/));
+ RETURN_IF_ERROR(aidl2legacy_AudioAttributesTags(aidl.tags, legacy.tags));
+ return legacy;
+}
+
+ConversionResult<PlaybackTrackMetadata>
+legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata(
+ const playback_track_metadata_v7& legacy) {
+ PlaybackTrackMetadata aidl;
+ aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.base.usage));
+ aidl.contentType = VALUE_OR_RETURN(legacy2aidl_audio_content_type_t_AudioContentType(
+ legacy.base.content_type));
+ aidl.gain = legacy.base.gain;
+ aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+ legacy.channel_mask, false /*isInput*/));
+ aidl.tags = VALUE_OR_RETURN(legacy2aidl_AudioAttributesTags(legacy.tags));
+ return aidl;
+}
+
+ConversionResult<record_track_metadata_v7>
+aidl2legacy_RecordTrackMetadata_record_track_metadata_v7(const RecordTrackMetadata& aidl) {
+ record_track_metadata_v7 legacy;
+ legacy.base.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(aidl.source));
+ legacy.base.gain = aidl.gain;
+ if (aidl.destinationDevice.has_value()) {
+ RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(aidl.destinationDevice.value(),
+ &legacy.base.dest_device, legacy.base.dest_device_address));
+ } else {
+ legacy.base.dest_device = AUDIO_DEVICE_NONE;
+ }
+ legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ aidl.channelMask, true /*isInput*/));
+ RETURN_IF_ERROR(aidl2legacy_AudioAttributesTags(aidl.tags, legacy.tags));
+ return legacy;
+}
+
+ConversionResult<RecordTrackMetadata>
+legacy2aidl_record_track_metadata_v7_RecordTrackMetadata(const record_track_metadata_v7& legacy) {
+ RecordTrackMetadata aidl;
+ aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.base.source));
+ aidl.gain = legacy.base.gain;
+ if (legacy.base.dest_device != AUDIO_DEVICE_NONE) {
+ aidl.destinationDevice = VALUE_OR_RETURN(legacy2aidl_audio_device_AudioDevice(
+ legacy.base.dest_device, legacy.base.dest_device_address));
+ }
+ aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+ legacy.channel_mask, true /*isInput*/));
+ aidl.tags = VALUE_OR_RETURN(legacy2aidl_AudioAttributesTags(legacy.tags));
+ return aidl;
+}
+
+} // namespace android
+} // aidl
diff --git a/media/audioaidlconversion/Android.bp b/media/audioaidlconversion/Android.bp
new file mode 100644
index 0000000..bdb3a2c
--- /dev/null
+++ b/media/audioaidlconversion/Android.bp
@@ -0,0 +1,183 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_defaults {
+ name: "audio_aidl_conversion_common_util_default",
+ host_supported: true,
+ vendor_available: true,
+ double_loadable: true,
+ min_sdk_version: "29",
+ export_include_dirs: [
+ "include",
+ ],
+ header_libs: [
+ "libbase_headers",
+ "liberror_headers",
+ ],
+ export_header_lib_headers: [
+ "libbase_headers",
+ "liberror_headers",
+ ],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.btservices",
+ "com.android.media",
+ "com.android.media.swcodec",
+ ],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
+
+// This is intended for clients needing to include AidlConversionUtil.h, without extra dependencies.
+cc_library_headers {
+ name: "libaudio_aidl_conversion_common_util_cpp",
+ defaults: [
+ "audio_aidl_conversion_common_util_default",
+ ],
+}
+
+cc_library_headers {
+ name: "libaudio_aidl_conversion_common_util_ndk",
+ defaults: [
+ "audio_aidl_conversion_common_util_default",
+ ],
+ cflags: [
+ "-DBACKEND_NDK",
+ ],
+}
+
+cc_defaults {
+ name: "audio_aidl_conversion_common_default",
+ export_include_dirs: ["include"],
+ host_supported: true,
+ vendor_available: true,
+ double_loadable: true,
+ header_libs: [
+ "libaudio_system_headers",
+ "libhardware_headers",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libshmemcompat",
+ "libstagefright_foundation",
+ "libutils",
+ "shared-file-region-aidl-cpp",
+ "framework-permission-aidl-cpp",
+ ],
+ export_shared_lib_headers: [
+ "libbase",
+ "shared-file-region-aidl-cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-error=deprecated-declarations",
+ ],
+ sanitize: {
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ },
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
+
+/**
+ * Only AIDL CPP backend conversion supported.
+ */
+cc_library {
+ name: "libaudio_aidl_conversion_common_cpp",
+ srcs: [
+ "AidlConversionCppNdk.cpp",
+ ],
+ header_libs: [
+ "libaudio_aidl_conversion_common_util_cpp",
+ ],
+ export_header_lib_headers: [
+ "libaudio_aidl_conversion_common_util_cpp",
+ ],
+ defaults: [
+ "audio_aidl_conversion_common_default",
+ "latest_android_media_audio_common_types_cpp_export_shared",
+ ],
+ min_sdk_version: "29",
+}
+
+/**
+ * Only AIDL NDK backend conversion supported.
+ */
+cc_library {
+ name: "libaudio_aidl_conversion_common_ndk",
+ srcs: [
+ "AidlConversionCppNdk.cpp",
+ "AidlConversionNdk.cpp",
+ ],
+ header_libs: [
+ "libaudio_aidl_conversion_common_util_ndk",
+ ],
+ export_header_lib_headers: [
+ "libaudio_aidl_conversion_common_util_ndk",
+ ],
+ defaults: [
+ "audio_aidl_conversion_common_default",
+ "latest_android_hardware_audio_common_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libbase",
+ ],
+ static_libs: [
+ "libaudioaidlcommon",
+ ],
+ cflags: [
+ "-DBACKEND_NDK",
+ ],
+ min_sdk_version: "31", //AParcelableHolder has been introduced in 31
+}
+
+/**
+ * Only including AIDL effect HAL conversion.
+ */
+cc_library {
+ name: "libaudio_aidl_conversion_effect_ndk",
+ srcs: [
+ "AidlConversionEffect.cpp",
+ ],
+ header_libs: [
+ "libaudio_aidl_conversion_common_util_ndk",
+ ],
+ export_header_lib_headers: [
+ "libaudio_aidl_conversion_common_util_ndk",
+ ],
+ defaults: [
+ "audio_aidl_conversion_common_default",
+ "latest_android_hardware_audio_common_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ shared_libs: [
+ "libaudio_aidl_conversion_common_ndk",
+ "libbinder_ndk",
+ "libbase",
+ ],
+ cflags: [
+ "-DBACKEND_NDK",
+ ],
+ min_sdk_version: "31", //AParcelableHolder has been introduced in 31
+}
diff --git a/media/audioaidlconversion/TEST_MAPPING b/media/audioaidlconversion/TEST_MAPPING
new file mode 100644
index 0000000..a0c9759
--- /dev/null
+++ b/media/audioaidlconversion/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "audio_aidl_ndk_conversion_tests"
+ }
+ ]
+}
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
new file mode 100644
index 0000000..9100892
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+// WARNING: This file is intended for multiple inclusion.
+// Do not include directly, use 'AidlConversionCppNdk.h'.
+#if (defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_CPP_NDK_NDK)) || \
+ (!defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_CPP_NDK_CPP))
+#if defined(BACKEND_NDK_IMPL)
+#define AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_CPP_NDK_NDK
+#else
+#define AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_CPP_NDK_CPP
+#endif // BACKEND_NDK_IMPL
+
+#include <limits>
+#include <type_traits>
+
+/**
+ * Can handle conversion between AIDL (both CPP and NDK backend) and legacy type.
+ * Controlled by the cflags preprocessor in Android.bp.
+ */
+#if defined(BACKEND_NDK_IMPL)
+#define PREFIX(f) <aidl/f>
+#else
+#define PREFIX(f) <f>
+#endif
+
+#include PREFIX(android/media/audio/common/AudioChannelLayout.h)
+#include PREFIX(android/media/audio/common/AudioConfig.h)
+#include PREFIX(android/media/audio/common/AudioConfigBase.h)
+#include PREFIX(android/media/audio/common/AudioContentType.h)
+#include PREFIX(android/media/audio/common/AudioDeviceDescription.h)
+#include PREFIX(android/media/audio/common/AudioDualMonoMode.h)
+#include PREFIX(android/media/audio/common/AudioEncapsulationMetadataType.h)
+#include PREFIX(android/media/audio/common/AudioEncapsulationMode.h)
+#include PREFIX(android/media/audio/common/AudioEncapsulationType.h)
+#include PREFIX(android/media/audio/common/AudioFormatDescription.h)
+#include PREFIX(android/media/audio/common/AudioGain.h)
+#include PREFIX(android/media/audio/common/AudioGainConfig.h)
+#include PREFIX(android/media/audio/common/AudioGainMode.h)
+#include PREFIX(android/media/audio/common/AudioInputFlags.h)
+#include PREFIX(android/media/audio/common/AudioIoFlags.h)
+#include PREFIX(android/media/audio/common/AudioLatencyMode.h)
+#include PREFIX(android/media/audio/common/AudioMode.h)
+#include PREFIX(android/media/audio/common/AudioOffloadInfo.h)
+#include PREFIX(android/media/audio/common/AudioOutputFlags.h)
+#include PREFIX(android/media/audio/common/AudioPort.h)
+#include PREFIX(android/media/audio/common/AudioPortConfig.h)
+#include PREFIX(android/media/audio/common/AudioPortExt.h)
+#include PREFIX(android/media/audio/common/AudioPortMixExt.h)
+#include PREFIX(android/media/audio/common/AudioPlaybackRate.h)
+#include PREFIX(android/media/audio/common/AudioProfile.h)
+#include PREFIX(android/media/audio/common/AudioSource.h)
+#include PREFIX(android/media/audio/common/AudioStandard.h)
+#include PREFIX(android/media/audio/common/AudioUsage.h)
+#include PREFIX(android/media/audio/common/AudioUuid.h)
+#include PREFIX(android/media/audio/common/ExtraAudioDescriptor.h)
+#include PREFIX(android/media/audio/common/Int.h)
+#include PREFIX(android/media/audio/common/MicrophoneDynamicInfo.h)
+#include PREFIX(android/media/audio/common/MicrophoneInfo.h)
+#undef PREFIX
+
+#include <system/audio.h>
+#include <system/audio_effect.h>
+
+#if defined(BACKEND_NDK_IMPL)
+namespace aidl {
+#endif
+
+namespace android {
+
+// maxSize is the size of the C-string buffer (including the 0-terminator), NOT the max length of
+// the string.
+::android::status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize);
+ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize);
+
+ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy);
+
+ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy);
+
+ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy);
+
+ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy);
+
+ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy);
+
+ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy);
+
+ConversionResult<unsigned int> aidl2legacy_int32_t_config_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_config_mask_int32_t(unsigned int legacy);
+
+ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy);
+
+ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy);
+
+ConversionResult<::android::String8> aidl2legacy_string_view_String8(std::string_view aidl);
+ConversionResult<std::string> legacy2aidl_String8_string(const ::android::String8& legacy);
+
+ConversionResult<::android::String16> aidl2legacy_string_view_String16(std::string_view aidl);
+ConversionResult<std::string> legacy2aidl_String16_string(const ::android::String16& legacy);
+
+ConversionResult<std::optional<::android::String16>>
+aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl);
+ConversionResult<std::optional<std::string_view>>
+legacy2aidl_optional_String16_optional_string(std::optional<::android::String16> legacy);
+
+ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ const media::audio::common::AudioChannelLayout& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioChannelLayout>
+legacy2aidl_audio_channel_mask_t_AudioChannelLayout(audio_channel_mask_t legacy, bool isInput);
+
+audio_channel_mask_t aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+ int aidlLayout, bool isInput);
+int legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
+ audio_channel_mask_t legacy, bool isInput);
+
+enum class AudioPortDirection {
+ INPUT, OUTPUT
+};
+ConversionResult<AudioPortDirection> portDirection(audio_port_role_t role, audio_port_type_t type);
+ConversionResult<audio_port_role_t> portRole(AudioPortDirection direction, audio_port_type_t type);
+
+ConversionResult<audio_config_t>
+aidl2legacy_AudioConfig_audio_config_t(const media::audio::common::AudioConfig& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioConfig>
+legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput);
+
+ConversionResult<audio_config_base_t>
+aidl2legacy_AudioConfigBase_audio_config_base_t(
+ const media::audio::common::AudioConfigBase& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioConfigBase>
+legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput);
+
+ConversionResult<audio_input_flags_t>
+aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
+ConversionResult<media::audio::common::AudioInputFlags>
+legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
+
+ConversionResult<audio_output_flags_t>
+aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
+ConversionResult<media::audio::common::AudioOutputFlags>
+legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
+
+ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
+ int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
+ audio_input_flags_t legacy);
+
+ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
+ int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
+ audio_output_flags_t legacy);
+
+ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
+ const media::audio::common::AudioIoFlags& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
+ const audio_io_flags& legacy, bool isInput);
+
+ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy);
+
+ConversionResult<audio_content_type_t>
+aidl2legacy_AudioContentType_audio_content_type_t(
+ media::audio::common::AudioContentType aidl);
+ConversionResult<media::audio::common::AudioContentType>
+legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy);
+
+ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
+ const media::audio::common::AudioDeviceDescription& aidl);
+ConversionResult<media::audio::common::AudioDeviceDescription>
+legacy2aidl_audio_devices_t_AudioDeviceDescription(audio_devices_t legacy);
+
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+ const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
+ char* legacyAddress);
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+ const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
+ ::android::String8* legacyAddress);
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+ const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
+ std::string* legacyAddress);
+
+ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
+ audio_devices_t legacyType, const char* legacyAddress);
+ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
+ audio_devices_t legacyType, const ::android::String8& legacyAddress);
+
+ConversionResult<audio_extra_audio_descriptor>
+aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
+ const media::audio::common::ExtraAudioDescriptor& aidl);
+
+ConversionResult<media::audio::common::ExtraAudioDescriptor>
+legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
+ const audio_extra_audio_descriptor& legacy);
+
+ConversionResult<audio_encapsulation_metadata_type_t>
+aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
+ media::audio::common::AudioEncapsulationMetadataType aidl);
+ConversionResult<media::audio::common::AudioEncapsulationMetadataType>
+legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
+ audio_encapsulation_metadata_type_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy);
+
+ConversionResult<audio_encapsulation_mode_t>
+aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(
+ media::audio::common::AudioEncapsulationMode aidl);
+ConversionResult<media::audio::common::AudioEncapsulationMode>
+legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy);
+
+ConversionResult<audio_encapsulation_type_t>
+aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
+ const media::audio::common::AudioEncapsulationType& aidl);
+ConversionResult<media::audio::common::AudioEncapsulationType>
+legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+ const audio_encapsulation_type_t& legacy);
+
+ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
+ const media::audio::common::AudioFormatDescription& aidl);
+ConversionResult<media::audio::common::AudioFormatDescription>
+legacy2aidl_audio_format_t_AudioFormatDescription(audio_format_t legacy);
+
+ConversionResult<audio_gain_mode_t>
+aidl2legacy_AudioGainMode_audio_gain_mode_t(media::audio::common::AudioGainMode aidl);
+ConversionResult<media::audio::common::AudioGainMode>
+legacy2aidl_audio_gain_mode_t_AudioGainMode(audio_gain_mode_t legacy);
+
+ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy);
+
+ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
+ const media::audio::common::AudioGainConfig& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioGainConfig>
+legacy2aidl_audio_gain_config_AudioGainConfig(const audio_gain_config& legacy, bool isInput);
+
+ConversionResult<audio_gain>
+aidl2legacy_AudioGain_audio_gain(const media::audio::common::AudioGain& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioGain>
+legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput);
+
+ConversionResult<audio_input_flags_t>
+aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
+ConversionResult<media::audio::common::AudioInputFlags>
+legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
+
+ConversionResult<audio_mode_t>
+aidl2legacy_AudioMode_audio_mode_t(media::audio::common::AudioMode aidl);
+ConversionResult<media::audio::common::AudioMode>
+legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy);
+
+ConversionResult<audio_offload_info_t>
+aidl2legacy_AudioOffloadInfo_audio_offload_info_t(
+ const media::audio::common::AudioOffloadInfo& aidl);
+ConversionResult<media::audio::common::AudioOffloadInfo>
+legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy);
+
+ConversionResult<audio_output_flags_t>
+aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
+ConversionResult<media::audio::common::AudioOutputFlags>
+legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
+
+// This type is unnamed in the original definition, thus we name it here.
+using audio_port_config_mix_ext_usecase = decltype(audio_port_config_mix_ext::usecase);
+ConversionResult<audio_port_config_mix_ext_usecase>
+aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+ const media::audio::common::AudioPortMixExtUseCase& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioPortMixExtUseCase>
+legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+ const audio_port_config_mix_ext_usecase& legacy, bool isInput);
+
+ConversionResult<audio_port_config_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
+ const media::audio::common::AudioPortDeviceExt& aidl);
+ConversionResult<media::audio::common::AudioPortDeviceExt>
+ legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
+ const audio_port_config_device_ext& legacy);
+
+::android::status_t aidl2legacy_AudioPortConfig_audio_port_config(
+ const media::audio::common::AudioPortConfig& aidl, bool isInput,
+ audio_port_config* legacy, int32_t* portId);
+ConversionResult<media::audio::common::AudioPortConfig>
+legacy2aidl_audio_port_config_AudioPortConfig(
+ const audio_port_config& legacy, bool isInput, int32_t portId);
+
+ConversionResult<audio_port_mix_ext> aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
+ const media::audio::common::AudioPortMixExt& aidl);
+ConversionResult<media::audio::common::AudioPortMixExt>
+legacy2aidl_audio_port_mix_ext_AudioPortMixExt(
+ const audio_port_mix_ext& legacy);
+
+ConversionResult<audio_port_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
+ const media::audio::common::AudioPortDeviceExt& aidl);
+ConversionResult<media::audio::common::AudioPortDeviceExt>
+legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
+ const audio_port_device_ext& legacy);
+
+ConversionResult<audio_port_v7>
+aidl2legacy_AudioPort_audio_port_v7(
+ const media::audio::common::AudioPort& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioPort>
+legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy, bool isInput);
+
+ConversionResult<audio_profile> aidl2legacy_AudioProfile_audio_profile(
+ const media::audio::common::AudioProfile& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioProfile> legacy2aidl_audio_profile_AudioProfile(
+ const audio_profile& legacy, bool isInput);
+
+ConversionResult<audio_standard_t> aidl2legacy_AudioStandard_audio_standard_t(
+ media::audio::common::AudioStandard aidl);
+ConversionResult<media::audio::common::AudioStandard> legacy2aidl_audio_standard_t_AudioStandard(
+ audio_standard_t legacy);
+
+ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
+ media::audio::common::AudioSource aidl);
+ConversionResult<media::audio::common::AudioSource> legacy2aidl_audio_source_t_AudioSource(
+ audio_source_t legacy);
+
+ConversionResult<audio_usage_t> aidl2legacy_AudioUsage_audio_usage_t(
+ media::audio::common::AudioUsage aidl);
+ConversionResult<media::audio::common::AudioUsage> legacy2aidl_audio_usage_t_AudioUsage(
+ audio_usage_t legacy);
+
+ConversionResult<audio_uuid_t> aidl2legacy_AudioUuid_audio_uuid_t(
+ const media::audio::common::AudioUuid &aidl);
+ConversionResult<media::audio::common::AudioUuid> legacy2aidl_audio_uuid_t_AudioUuid(
+ const audio_uuid_t& legacy);
+
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::audio::common::AudioDualMonoMode aidl);
+ConversionResult<media::audio::common::AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+ media::audio::common::AudioPlaybackRate::TimestretchFallbackMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+ audio_timestretch_fallback_mode_t legacy);
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+ media::audio::common::AudioPlaybackRate::TimestretchMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+ audio_timestretch_stretch_mode_t legacy);
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(
+ const media::audio::common::AudioPlaybackRate& aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(media::audio::common::AudioLatencyMode aidl);
+ConversionResult<media::audio::common::AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy);
+
+ConversionResult<audio_microphone_location_t>
+aidl2legacy_MicrophoneInfoLocation_audio_microphone_location_t(
+ media::audio::common::MicrophoneInfo::Location aidl);
+ConversionResult<media::audio::common::MicrophoneInfo::Location>
+legacy2aidl_audio_microphone_location_t_MicrophoneInfoLocation(audio_microphone_location_t legacy);
+
+ConversionResult<audio_microphone_group_t> aidl2legacy_int32_t_audio_microphone_group_t(
+ int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_microphone_group_t_int32_t(
+ audio_microphone_group_t legacy);
+
+ConversionResult<audio_microphone_directionality_t>
+aidl2legacy_MicrophoneInfoDirectionality_audio_microphone_directionality_t(
+ media::audio::common::MicrophoneInfo::Directionality aidl);
+ConversionResult<media::audio::common::MicrophoneInfo::Directionality>
+legacy2aidl_audio_microphone_directionality_t_MicrophoneInfoDirectionality(
+ audio_microphone_directionality_t legacy);
+
+ConversionResult<audio_microphone_coordinate>
+aidl2legacy_MicrophoneInfoCoordinate_audio_microphone_coordinate(
+ const media::audio::common::MicrophoneInfo::Coordinate& aidl);
+ConversionResult<media::audio::common::MicrophoneInfo::Coordinate>
+legacy2aidl_audio_microphone_coordinate_MicrophoneInfoCoordinate(
+ const audio_microphone_coordinate& legacy);
+
+ConversionResult<audio_microphone_channel_mapping_t>
+aidl2legacy_MicrophoneDynamicInfoChannelMapping_audio_microphone_channel_mapping_t(
+ media::audio::common::MicrophoneDynamicInfo::ChannelMapping aidl);
+ConversionResult<media::audio::common::MicrophoneDynamicInfo::ChannelMapping>
+legacy2aidl_audio_microphone_channel_mapping_t_MicrophoneDynamicInfoChannelMapping(
+ audio_microphone_channel_mapping_t legacy);
+
+ConversionResult<audio_microphone_characteristic_t>
+aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t(
+ const media::audio::common::MicrophoneInfo& aidlInfo,
+ const media::audio::common::MicrophoneDynamicInfo& aidlDynamic);
+::android::status_t
+legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfos(
+ const audio_microphone_characteristic_t& legacy,
+ media::audio::common::MicrophoneInfo* aidlInfo,
+ media::audio::common::MicrophoneDynamicInfo* aidlDynamic);
+
+} // namespace android
+
+#if defined(BACKEND_NDK_IMPL)
+} // aidl
+#endif
+
+// (defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_CPP_NDK_NDK)) || \
+// (!defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_CPP_NDK_CPP))
+#endif
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
new file mode 100644
index 0000000..ea168a4
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 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
+
+// Since conversion functions use ConversionResult, pull it in here.
+#include <media/AidlConversionUtil.h>
+
+// Include 'AidlConversionCppNdk.h' once if 'BACKEND_NDK' is defined,
+// or no 'BACKEND_*' is defined (C++ backend). Include twice if
+// 'BACKEND_CPP_NDK' is defined: once with 'BACKEND_NDK_IMPL', once w/o defines.
+
+#if defined(BACKEND_CPP_NDK) || defined(BACKEND_NDK)
+#define BACKEND_NDK_IMPL
+#include <media/AidlConversionCppNdk-impl.h>
+#undef BACKEND_NDK_IMPL
+#endif
+
+#if defined(BACKEND_CPP_NDK) || !defined(BACKEND_NDK)
+#include <media/AidlConversionCppNdk-impl.h>
+#endif
diff --git a/media/audioaidlconversion/include/media/AidlConversionEffect.h b/media/audioaidlconversion/include/media/AidlConversionEffect.h
new file mode 100644
index 0000000..5e245a7
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionEffect.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2023 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 <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+/**
+ * Can only handle conversion between AIDL (NDK backend) and legacy type.
+ */
+#include <hardware/audio_effect.h>
+#include <media/AidlConversionUtil.h>
+#include <system/audio_effect.h>
+#include <system/audio_effects/audio_effects_utils.h>
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+
+namespace aidl {
+namespace android {
+
+template <typename P, typename T, typename P::Specific::Tag tag>
+ConversionResult<T> getParameterSpecific(const P& u) {
+ const auto& spec = VALUE_OR_RETURN(UNION_GET(u, specific));
+ return unionGetField<typename P::Specific, tag>(spec);
+}
+
+template <typename P, typename T, typename P::Specific::Tag tag, typename T::Tag field, typename F>
+ConversionResult<F> getParameterSpecificField(const P& u) {
+ const auto& spec =
+ VALUE_OR_RETURN((getParameterSpecific<std::decay_t<decltype(u)>, T, tag>(u)));
+ return VALUE_OR_RETURN((unionGetField<T, field>(spec)));
+}
+
+#define GET_PARAMETER_SPECIFIC_FIELD(_u, _effect, _tag, _field, _fieldType) \
+ getParameterSpecificField<std::decay_t<decltype(_u)>, _effect, \
+ aidl::android::hardware::audio::effect::Parameter::Specific::_tag, \
+ _effect::_field, _fieldType>(_u)
+
+#define MAKE_SPECIFIC_PARAMETER(_spec, _tag, _field, _value) \
+ UNION_MAKE(aidl::android::hardware::audio::effect::Parameter, specific, \
+ UNION_MAKE(aidl::android::hardware::audio::effect::Parameter::Specific, _tag, \
+ UNION_MAKE(_spec, _field, _value)))
+
+#define MAKE_SPECIFIC_PARAMETER_ID(_spec, _tag, _field) \
+ UNION_MAKE(aidl::android::hardware::audio::effect::Parameter::Id, _tag, \
+ UNION_MAKE(_spec::Id, commonTag, _field))
+
+#define MAKE_EXTENSION_PARAMETER_ID(_effect, _tag, _field) \
+ UNION_MAKE(aidl::android::hardware::audio::effect::Parameter::Id, _tag, \
+ UNION_MAKE(_effect::Id, vendorExtensionTag, _field))
+
+#define VENDOR_EXTENSION_GET_AND_RETURN(_effect, _tag, _param) \
+ { \
+ aidl::android::hardware::audio::effect::VendorExtension _extId = VALUE_OR_RETURN_STATUS( \
+ aidl::android::legacy2aidl_EffectParameterReader_Param_VendorExtension(_param)); \
+ aidl::android::hardware::audio::effect::Parameter::Id _id = \
+ MAKE_EXTENSION_PARAMETER_ID(_effect, _tag##Tag, _extId); \
+ aidl::android::hardware::audio::effect::Parameter _aidlParam; \
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(_id, &_aidlParam))); \
+ aidl::android::hardware::audio::effect::VendorExtension _ext = \
+ VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD( \
+ _aidlParam, _effect, _tag, _effect::vendor, VendorExtension)); \
+ return VALUE_OR_RETURN_STATUS( \
+ aidl::android::aidl2legacy_ParameterExtension_EffectParameterWriter(_aidlParam, \
+ _param)); \
+ }
+
+ConversionResult<uint32_t> aidl2legacy_Flags_Type_uint32(
+ ::aidl::android::hardware::audio::effect::Flags::Type type);
+ConversionResult<uint32_t> aidl2legacy_Flags_Insert_uint32(
+ ::aidl::android::hardware::audio::effect::Flags::Insert insert);
+ConversionResult<uint32_t> aidl2legacy_Flags_Volume_uint32(
+ ::aidl::android::hardware::audio::effect::Flags::Volume volume);
+ConversionResult<uint32_t> aidl2legacy_Flags_HardwareAccelerator_uint32(
+ ::aidl::android::hardware::audio::effect::Flags::HardwareAccelerator hwAcceleratorMode);
+ConversionResult<uint32_t> aidl2legacy_Flags_uint32(
+ const ::aidl::android::hardware::audio::effect::Flags aidl);
+
+ConversionResult<::aidl::android::hardware::audio::effect::Flags::Type>
+legacy2aidl_uint32_Flags_Type(uint32_t legacy);
+ConversionResult<::aidl::android::hardware::audio::effect::Flags::Insert>
+legacy2aidl_uint32_Flags_Insert(uint32_t legacy);
+ConversionResult<::aidl::android::hardware::audio::effect::Flags::Volume>
+legacy2aidl_uint32_Flags_Volume(uint32_t legacy);
+ConversionResult<::aidl::android::hardware::audio::effect::Flags::HardwareAccelerator>
+legacy2aidl_uint32_Flags_HardwareAccelerator(uint32_t legacy);
+ConversionResult<::aidl::android::hardware::audio::effect::Flags> legacy2aidl_uint32_Flags(
+ uint32_t hal);
+
+ConversionResult<effect_descriptor_t> aidl2legacy_Descriptor_effect_descriptor(
+ const ::aidl::android::hardware::audio::effect::Descriptor& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Descriptor>
+legacy2aidl_effect_descriptor_Descriptor(const effect_descriptor_t& hal);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_echoDelay(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_echoDelay_Parameter_aec(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_mobileMode(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_mobileMode_Parameter_aec(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_fixedDigitalGain_Parameter_agc(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_levelEstimator(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_levelEstimator_Parameter_agc(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_saturationMargin(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_saturationMargin_Parameter_agc(uint32_t legacy);
+
+ConversionResult<uint16_t> aidl2legacy_Parameter_BassBoost_uint16_strengthPm(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint16_strengthPm_Parameter_BassBoost(uint16_t legacy);
+
+ConversionResult<int16_t> aidl2legacy_Parameter_Downmix_int16_type(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_int16_type_Parameter_Downmix(int16_t legacy);
+
+ConversionResult<::aidl::android::hardware::audio::effect::DynamicsProcessing::ResolutionPreference>
+legacy2aidl_int32_DynamicsProcessing_ResolutionPreference(int32_t legacy);
+ConversionResult<int32_t> aidl2legacy_DynamicsProcessing_ResolutionPreference_int32(
+ ::aidl::android::hardware::audio::effect::DynamicsProcessing::ResolutionPreference aidl);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_ScalingMode_uint32(
+ ::aidl::android::hardware::audio::effect::Visualizer::ScalingMode aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Visualizer::ScalingMode>
+legacy2aidl_Parameter_Visualizer_uint32_ScalingMode(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_MeasurementMode_uint32(
+ ::aidl::android::hardware::audio::effect::Visualizer::MeasurementMode aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Visualizer::MeasurementMode>
+legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(uint32_t legacy);
+
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_EffectParameterReader_ParameterExtension(
+ ::android::effect::utils::EffectParamReader& param);
+ConversionResult<::android::status_t> aidl2legacy_ParameterExtension_EffectParameterWriter(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl,
+ ::android::effect::utils::EffectParamWriter& legacy);
+
+ConversionResult<::aidl::android::hardware::audio::effect::VendorExtension>
+legacy2aidl_EffectParameterReader_Param_VendorExtension(
+ ::android::effect::utils::EffectParamReader& param);
+ConversionResult<::aidl::android::hardware::audio::effect::VendorExtension>
+legacy2aidl_EffectParameterReader_Data_VendorExtension(
+ ::android::effect::utils::EffectParamReader& param);
+
+ConversionResult<::android::status_t> aidl2legacy_VendorExtension_EffectParameterWriter_Data(
+ ::android::effect::utils::EffectParamWriter& param,
+ ::aidl::android::hardware::audio::effect::VendorExtension ext);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_EffectParameterReader_ParameterExtension(
+ ::android::effect::utils::EffectParamReader& param);
+
+} // namespace android
+} // namespace aidl
diff --git a/media/audioaidlconversion/include/media/AidlConversionNdk.h b/media/audioaidlconversion/include/media/AidlConversionNdk.h
new file mode 100644
index 0000000..e92f1a9
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionNdk.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 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
+
+/**
+ * Can only handle conversion between AIDL (NDK backend) and legacy types.
+ */
+
+#include <string>
+#include <vector>
+
+#include <hardware/audio_effect.h>
+#include <system/audio_effect.h>
+
+#include <aidl/android/hardware/audio/common/PlaybackTrackMetadata.h>
+#include <aidl/android/hardware/audio/common/RecordTrackMetadata.h>
+#include <aidl/android/media/audio/common/AudioConfig.h>
+#include <media/AidlConversionUtil.h>
+
+namespace aidl {
+namespace android {
+
+ConversionResult<buffer_config_t> aidl2legacy_AudioConfigBase_buffer_config_t(
+ const media::audio::common::AudioConfigBase& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioConfigBase> legacy2aidl_buffer_config_t_AudioConfigBase(
+ const buffer_config_t& legacy, bool isInput);
+
+::android::status_t aidl2legacy_AudioAttributesTags(
+ const std::vector<std::string>& aidl, char* legacy);
+ConversionResult<std::vector<std::string>> legacy2aidl_AudioAttributesTags(const char* legacy);
+
+ConversionResult<playback_track_metadata_v7>
+aidl2legacy_PlaybackTrackMetadata_playback_track_metadata_v7(
+ const hardware::audio::common::PlaybackTrackMetadata& aidl);
+ConversionResult<hardware::audio::common::PlaybackTrackMetadata>
+legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata(
+ const playback_track_metadata_v7& legacy);
+
+ConversionResult<record_track_metadata_v7>
+aidl2legacy_RecordTrackMetadata_record_track_metadata_v7(
+ const hardware::audio::common::RecordTrackMetadata& aidl);
+ConversionResult<hardware::audio::common::RecordTrackMetadata>
+legacy2aidl_record_track_metadata_v7_RecordTrackMetadata(const record_track_metadata_v7& legacy);
+
+} // namespace android
+} // namespace aidl
diff --git a/media/libaudioclient/include/media/AidlConversionUtil.h b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
similarity index 70%
rename from media/libaudioclient/include/media/AidlConversionUtil.h
rename to media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
index 8817c35..ed91e2c 100644
--- a/media/libaudioclient/include/media/AidlConversionUtil.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -14,20 +14,41 @@
* limitations under the License.
*/
-#pragma once
+// WARNING: This file is intended for multiple inclusion, one time
+// with BACKEND_NDK_IMPL defined, one time without it.
+// Do not include directly, use 'AidlConversionUtil.h'.
+#if (defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_UTIL_NDK)) || \
+ (!defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_UTIL_CPP))
+#if defined(BACKEND_NDK_IMPL)
+#define AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_UTIL_NDK
+#else
+#define AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_UTIL_CPP
+#endif // BACKEND_NDK_IMPL
#include <limits>
#include <type_traits>
#include <utility>
-#include <binder/Enums.h>
+#include <android-base/expected.h>
#include <binder/Status.h>
-#include <error/Result.h>
+#if defined(BACKEND_NDK_IMPL)
+#include <android/binder_auto_utils.h>
+#include <android/binder_enums.h>
+#include <android/binder_status.h>
+
+namespace aidl {
+#else
+#include <binder/Enums.h>
+#endif // BACKEND_NDK_IMPL
namespace android {
+#if defined(BACKEND_NDK_IMPL)
+// This adds `::aidl::android::ConversionResult` for convenience.
+// Otherwise, it would be required to write `::android::ConversionResult` everywhere.
template <typename T>
-using ConversionResult = error::Result<T>;
+using ConversionResult = ::android::ConversionResult<T>;
+#endif // BACKEND_NDK_IMPL
/**
* A generic template to safely cast between integral types, respecting limits of the destination
@@ -39,15 +60,15 @@
// have the signed converted to unsigned and produce wrong results.
if (std::is_signed_v<From> && !std::is_signed_v<To>) {
if (from < 0 || from > std::numeric_limits<To>::max()) {
- return base::unexpected(BAD_VALUE);
+ return ::android::base::unexpected(::android::BAD_VALUE);
}
} else if (std::is_signed_v<To> && !std::is_signed_v<From>) {
if (from > std::numeric_limits<To>::max()) {
- return base::unexpected(BAD_VALUE);
+ return ::android::base::unexpected(::android::BAD_VALUE);
}
} else {
if (from < std::numeric_limits<To>::min() || from > std::numeric_limits<To>::max()) {
- return base::unexpected(BAD_VALUE);
+ return ::android::base::unexpected(::android::BAD_VALUE);
}
}
return static_cast<To>(from);
@@ -67,14 +88,14 @@
* A generic template that helps convert containers of convertible types, using iterators.
*/
template<typename InputIterator, typename OutputIterator, typename Func>
-status_t convertRange(InputIterator start,
+::android::status_t convertRange(InputIterator start,
InputIterator end,
OutputIterator out,
const Func& itemConversion) {
for (InputIterator iter = start; iter != end; ++iter, ++out) {
*out = VALUE_OR_RETURN_STATUS(itemConversion(*iter));
}
- return OK;
+ return ::android::OK;
}
/**
@@ -82,7 +103,7 @@
* Uses a limit as maximum conversion items.
*/
template<typename InputIterator, typename OutputIterator, typename Func>
-status_t convertRangeWithLimit(InputIterator start,
+::android::status_t convertRangeWithLimit(InputIterator start,
InputIterator end,
OutputIterator out,
const Func& itemConversion,
@@ -94,7 +115,7 @@
for (InputIterator iter = start; (iter != last); ++iter, ++out) {
*out = VALUE_OR_RETURN_STATUS(itemConversion(*iter));
}
- return OK;
+ return ::android::OK;
}
/**
@@ -140,7 +161,7 @@
OutputContainer output;
auto ins = std::inserter(output, output.begin());
for (const auto& item1 : input1) {
- RETURN_IF_ERROR(iter2 != input2.end() ? OK : BAD_VALUE);
+ RETURN_IF_ERROR(iter2 != input2.end() ? ::android::OK : ::android::BAD_VALUE);
*ins = VALUE_OR_RETURN(itemConversion(item1, *iter2++));
}
return output;
@@ -248,7 +269,8 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// Utilities for working with AIDL unions.
// UNION_GET(obj, fieldname) returns a ConversionResult<T> containing either the strongly-typed
-// value of the respective field, or BAD_VALUE if the union is not set to the requested field.
+// value of the respective field, or ::android::BAD_VALUE if the union is not set to the requested
+// field.
// UNION_SET(obj, fieldname, value) sets the requested field to the given value.
template<typename T, typename T::Tag tag>
@@ -257,7 +279,7 @@
template<typename T, typename T::Tag tag>
ConversionResult<UnionFieldType<T, tag>> unionGetField(const T& u) {
if (u.getTag() != tag) {
- return base::unexpected(BAD_VALUE);
+ return ::android::base::unexpected(::android::BAD_VALUE);
}
return u.template get<tag>();
}
@@ -268,6 +290,8 @@
#define UNION_SET(u, field, value) \
(u).set<std::decay_t<decltype(u)>::Tag::field>(value)
+#define UNION_MAKE(u, field, value) u::make<u::Tag::field>(value)
+
namespace aidl_utils {
/**
@@ -275,7 +299,11 @@
*/
template <typename T>
bool isValidEnum(T value) {
- constexpr android::enum_range<T> er{};
+#if defined(BACKEND_NDK_IMPL)
+ constexpr ndk::enum_range<T> er{};
+#else
+ constexpr ::android::enum_range<T> er{};
+#endif
return std::find(er.begin(), er.end(), value) != er.end();
}
@@ -294,7 +322,7 @@
}
/**
- * Return the equivalent Android status_t from a binder exception code.
+ * Return the equivalent Android ::android::status_t from a binder exception code.
*
* Generally one should use statusTFromBinderStatus() instead.
*
@@ -304,33 +332,33 @@
* Note: for EX_TRANSACTION_FAILED and EX_SERVICE_SPECIFIC a more detailed error code
* can be found from transactionError() or serviceSpecificErrorCode().
*/
-static inline status_t statusTFromExceptionCode(int32_t exceptionCode) {
+static inline ::android::status_t statusTFromExceptionCode(int32_t exceptionCode) {
using namespace ::android::binder;
switch (exceptionCode) {
case Status::EX_NONE:
- return OK;
- case Status::EX_SECURITY: // Java SecurityException, rethrows locally in Java
- return PERMISSION_DENIED;
- case Status::EX_BAD_PARCELABLE: // Java BadParcelableException, rethrows in Java
- case Status::EX_ILLEGAL_ARGUMENT: // Java IllegalArgumentException, rethrows in Java
- case Status::EX_NULL_POINTER: // Java NullPointerException, rethrows in Java
- return BAD_VALUE;
- case Status::EX_ILLEGAL_STATE: // Java IllegalStateException, rethrows in Java
- case Status::EX_UNSUPPORTED_OPERATION: // Java UnsupportedOperationException, rethrows
- return INVALID_OPERATION;
+ return ::android::OK;
+ case Status::EX_SECURITY: // Java SecurityException, rethrows locally in Java
+ return ::android::PERMISSION_DENIED;
+ case Status::EX_BAD_PARCELABLE: // Java BadParcelableException, rethrows in Java
+ case Status::EX_ILLEGAL_ARGUMENT: // Java IllegalArgumentException, rethrows in Java
+ case Status::EX_NULL_POINTER: // Java NullPointerException, rethrows in Java
+ return ::android::BAD_VALUE;
+ case Status::EX_ILLEGAL_STATE: // Java IllegalStateException, rethrows in Java
+ case Status::EX_UNSUPPORTED_OPERATION: // Java UnsupportedOperationException, rethrows
+ return ::android::INVALID_OPERATION;
case Status::EX_HAS_REPLY_HEADER: // Native strictmode violation
- case Status::EX_PARCELABLE: // Java bootclass loader (not standard exception), rethrows
- case Status::EX_NETWORK_MAIN_THREAD: // Java NetworkOnMainThreadException, rethrows
+ case Status::EX_PARCELABLE: // Java bootclass loader (not standard exception), rethrows
+ case Status::EX_NETWORK_MAIN_THREAD: // Java NetworkOnMainThreadException, rethrows
case Status::EX_TRANSACTION_FAILED: // Native - see error code
- case Status::EX_SERVICE_SPECIFIC: // Java ServiceSpecificException,
- // rethrows in Java with integer error code
- return UNKNOWN_ERROR;
+ case Status::EX_SERVICE_SPECIFIC: // Java ServiceSpecificException,
+ // rethrows in Java with integer error code
+ return ::android::UNKNOWN_ERROR;
}
- return UNKNOWN_ERROR;
+ return ::android::UNKNOWN_ERROR;
}
/**
- * Return the equivalent Android status_t from a binder status.
+ * Return the equivalent Android ::android::status_t from a binder status.
*
* Used to handle errors from a AIDL method declaration
*
@@ -340,8 +368,8 @@
*
* return_type method(type0 param0, ...)
*/
-static inline status_t statusTFromBinderStatus(const ::android::binder::Status &status) {
- return status.isOk() ? OK // check OK,
+static inline ::android::status_t statusTFromBinderStatus(const ::android::binder::Status &status) {
+ return status.isOk() ? ::android::OK // check ::android::OK,
: status.serviceSpecificErrorCode() // service-side error, not standard Java exception
// (fromServiceSpecificError)
?: status.transactionError() // a native binder transaction error (fromStatusT)
@@ -349,6 +377,20 @@
// standard Java exception (fromExceptionCode)
}
+#if defined(BACKEND_NDK_IMPL)
+static inline ::android::status_t statusTFromBinderStatus(const ::ndk::ScopedAStatus &status) {
+ // What we want to do is to 'return statusTFromBinderStatus(status.get()->get())'
+ // However, since the definition of AStatus is not exposed, we have to do the same
+ // via methods of ScopedAStatus:
+ return status.isOk() ? ::android::OK // check ::android::OK,
+ : status.getServiceSpecificError() // service-side error, not standard Java exception
+ // (fromServiceSpecificError)
+ ?: status.getStatus() // a native binder transaction error (fromStatusT)
+ ?: statusTFromExceptionCode(status.getExceptionCode()); // a service-side error with a
+ // standard Java exception (fromExceptionCode)
+}
+#endif
+
/**
* Return a binder::Status from native service status.
*
@@ -356,23 +398,23 @@
* where Java callers expect an exception, not an integer return value.
*/
static inline ::android::binder::Status binderStatusFromStatusT(
- status_t status, const char *optionalMessage = nullptr) {
+ ::android::status_t status, const char *optionalMessage = nullptr) {
const char * const emptyIfNull = optionalMessage == nullptr ? "" : optionalMessage;
// From binder::Status instructions:
// Prefer a generic exception code when possible, then a service specific
- // code, and finally a status_t for low level failures or legacy support.
+ // code, and finally a ::android::status_t for low level failures or legacy support.
// Exception codes and service specific errors map to nicer exceptions for
// Java clients.
using namespace ::android::binder;
switch (status) {
- case OK:
+ case ::android::OK:
return Status::ok();
- case PERMISSION_DENIED: // throw SecurityException on Java side
+ case ::android::PERMISSION_DENIED: // throw SecurityException on Java side
return Status::fromExceptionCode(Status::EX_SECURITY, emptyIfNull);
- case BAD_VALUE: // throw IllegalArgumentException on Java side
+ case ::android::BAD_VALUE: // throw IllegalArgumentException on Java side
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, emptyIfNull);
- case INVALID_OPERATION: // throw IllegalStateException on Java side
+ case ::android::INVALID_OPERATION: // throw IllegalStateException on Java side
return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, emptyIfNull);
}
@@ -383,7 +425,14 @@
return Status::fromServiceSpecificError(status, emptyIfNull);
}
-
} // namespace aidl_utils
} // namespace android
+
+#if defined(BACKEND_NDK_IMPL)
+} // namespace aidl
+#endif
+
+// (defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_UTIL_NDK)) || \
+// (!defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_UTIL_CPP))
+#endif
diff --git a/media/audioaidlconversion/include/media/AidlConversionUtil.h b/media/audioaidlconversion/include/media/AidlConversionUtil.h
new file mode 100644
index 0000000..b846436
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 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 <error/Result.h>
+
+namespace android {
+// `ConversionResult` is always defined in the `::android` namespace,
+// so that it can be found from any nested namespace.
+// See below for the convenience alias specific to the NDK backend.
+template <typename T>
+using ConversionResult = ::android::error::Result<T>;
+} // namespace android
+
+// Include 'AidlConversionUtil.h' once if 'BACKEND_NDK' is defined,
+// or no 'BACKEND_*' is defined (C++ backend). Include twice if
+// 'BACKEND_CPP_NDK' is defined: once with 'BACKEND_NDK_IMPL', once w/o defines.
+
+#if defined(BACKEND_CPP_NDK) || defined(BACKEND_NDK)
+#define BACKEND_NDK_IMPL
+#include <media/AidlConversionUtil-impl.h>
+#undef BACKEND_NDK_IMPL
+#endif
+
+#if defined(BACKEND_CPP_NDK) || !defined(BACKEND_NDK)
+#include <media/AidlConversionUtil-impl.h>
+#endif
diff --git a/media/audioaidlconversion/tests/Android.bp b/media/audioaidlconversion/tests/Android.bp
new file mode 100644
index 0000000..de7c8a2
--- /dev/null
+++ b/media/audioaidlconversion/tests/Android.bp
@@ -0,0 +1,46 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_defaults {
+ name: "libaudio_aidl_conversion_tests_defaults",
+ test_suites: ["device-tests"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ sanitize: {
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ },
+}
+
+cc_test {
+ name: "audio_aidl_ndk_conversion_tests",
+
+ defaults: [
+ "latest_android_media_audio_common_types_ndk_static",
+ "latest_android_hardware_audio_common_ndk_static",
+ "libaudio_aidl_conversion_tests_defaults",
+ ],
+ srcs: ["audio_aidl_ndk_conversion_tests.cpp"],
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "libutils",
+ ],
+ static_libs: [
+ "libaudio_aidl_conversion_common_ndk",
+ ],
+ cflags: [
+ "-DBACKEND_NDK",
+ ],
+}
diff --git a/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
new file mode 100644
index 0000000..c505e60
--- /dev/null
+++ b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2023 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 <iostream>
+#include <type_traits>
+
+#include <gtest/gtest.h>
+
+#include <media/AidlConversionNdk.h>
+
+namespace {
+template<typename> struct mf_traits {};
+template<class T, class U> struct mf_traits<U T::*> {
+ using member_type = U;
+};
+} // namespace
+
+// Provide value printers for types generated from AIDL
+// They need to be in the same namespace as the types we intend to print
+namespace aidl::android::hardware::audio::common {
+ template <typename P>
+ std::enable_if_t<std::is_function_v<typename mf_traits<decltype(&P::toString)>::member_type>,
+ std::ostream&> operator<<(std::ostream& os, const P& p) {
+ return os << p.toString();
+ }
+ template <typename E>
+ std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) {
+ return os << toString(e);
+ }
+} // namespace aidl::android::hardware::audio::common
+
+using aidl::android::hardware::audio::common::PlaybackTrackMetadata;
+using aidl::android::hardware::audio::common::RecordTrackMetadata;
+using aidl::android::media::audio::common::AudioSource;
+using aidl::android::media::audio::common::AudioUsage;
+using namespace aidl::android; // for conversion functions
+
+TEST(AudioPlaybackTrackMetadata, Aidl2Legacy2Aidl) {
+ const PlaybackTrackMetadata initial{ .usage = AudioUsage::UNKNOWN };
+ auto conv = aidl2legacy_PlaybackTrackMetadata_playback_track_metadata_v7(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+
+TEST(AudioPlaybackTrackMetadata, NonVendorTags) {
+ PlaybackTrackMetadata initial{ .usage = AudioUsage::UNKNOWN };
+ initial.tags.emplace_back("random string"); // Must be filtered out.
+ initial.tags.emplace_back("VX_GOOGLE_42");
+ auto conv = aidl2legacy_PlaybackTrackMetadata_playback_track_metadata_v7(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ ASSERT_EQ(1, convBack.value().tags.size());
+ EXPECT_EQ(initial.tags[1], convBack.value().tags[0]);
+}
+
+TEST(AudioRecordTrackMetadata, Aidl2Legacy2Aidl) {
+ const RecordTrackMetadata initial{ .source = AudioSource::DEFAULT };
+ auto conv = aidl2legacy_RecordTrackMetadata_record_track_metadata_v7(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_record_track_metadata_v7_RecordTrackMetadata(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+
+TEST(AudioRecordTrackMetadata, NonVendorTags) {
+ RecordTrackMetadata initial{ .source = AudioSource::DEFAULT };
+ initial.tags.emplace_back("random string"); // Must be filtered out.
+ initial.tags.emplace_back("VX_GOOGLE_42");
+ auto conv = aidl2legacy_RecordTrackMetadata_record_track_metadata_v7(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_record_track_metadata_v7_RecordTrackMetadata(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ ASSERT_EQ(1, convBack.value().tags.size());
+ EXPECT_EQ(initial.tags[1], convBack.value().tags[0]);
+}
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index c4a6601..d62dd91 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -7,11 +7,10 @@
ioprio rt 4
task_profiles ProcessCapacityHigh HighPerformance
onrestart restart vendor.audio-hal
+ onrestart restart vendor.audio-hal-aidl
+ onrestart restart vendor.audio-effect-hal-aidl
onrestart restart vendor.audio-hal-4-0-msd
onrestart restart audio_proxy_service
- # Keep the original service names for backward compatibility
- onrestart restart vendor.audio-hal-2-0
- onrestart restart audio-hal-2-0
on property:vts.native_server.on=1
stop audioserver
@@ -20,42 +19,39 @@
on property:init.svc.audioserver=stopped
stop vendor.audio-hal
+ stop vendor.audio-hal-aidl
+ stop vendor.audio-effect-hal-aidl
stop vendor.audio-hal-4-0-msd
stop audio_proxy_service
- # Keep the original service names for backward compatibility
- stop vendor.audio-hal-2-0
- stop audio-hal-2-0
# See b/155364397. Need to have HAL service running for VTS.
# Can't use 'restart' because then HAL service would restart
# audioserver bringing it back into running state.
start vendor.audio-hal
+ start vendor.audio-hal-aidl
+ start vendor.audio-effect-hal-aidl
start vendor.audio-hal-4-0-msd
start audio_proxy_service
- # Keep the original service names for backward compatibility
- start vendor.audio-hal-2-0
- start audio-hal-2-0
on property:init.svc.audioserver=running
start vendor.audio-hal
+ start vendor.audio-hal-aidl
+ start vendor.audio-effect-hal-aidl
start vendor.audio-hal-4-0-msd
start audio_proxy_service
- # Keep the original service names for backward compatibility
- start vendor.audio-hal-2-0
- start audio-hal-2-0
on property:sys.audio.restart.hal=1
# See b/159966243. Avoid restart loop between audioserver and HAL.
# Keep the original service names for backward compatibility
stop vendor.audio-hal
+ stop vendor.audio-hal-aidl
+ stop vendor.audio-effect-hal-aidl
stop vendor.audio-hal-4-0-msd
stop audio_proxy_service
- stop vendor.audio-hal-2-0
- stop audio-hal-2-0
start vendor.audio-hal
+ start vendor.audio-hal-aidl
+ start vendor.audio-effect-hal-aidl
start vendor.audio-hal-4-0-msd
start audio_proxy_service
- start vendor.audio-hal-2-0
- start audio-hal-2-0
# reset the property
setprop sys.audio.restart.hal 0
diff --git a/media/codec2/TEST_MAPPING b/media/codec2/TEST_MAPPING
index 90bb054..8a894f3 100644
--- a/media/codec2/TEST_MAPPING
+++ b/media/codec2/TEST_MAPPING
@@ -8,17 +8,6 @@
],
"presubmit-large": [
{
- "name": "CtsMediaMiscTestCases",
- "options": [
- {
- "include-annotation": "android.platform.test.annotations.Presubmit"
- },
- {
- "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
- }
- ]
- },
- {
"name": "CtsMediaAudioTestCases",
"options": [
{
@@ -35,50 +24,6 @@
"exclude-filter": "android.media.audio.cts.AudioRecordTest"
}
]
- },
- {
- "name": "CtsMediaDecoderTestCases",
- "options": [
- {
- "include-annotation": "android.platform.test.annotations.Presubmit"
- },
- {
- "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
- }
- ]
- },
- {
- "name": "CtsMediaEncoderTestCases",
- "options": [
- {
- "include-annotation": "android.platform.test.annotations.Presubmit"
- },
- {
- "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
- }
- ]
- },
- {
- "name": "CtsMediaCodecTestCases",
- "options": [
- {
- "include-annotation": "android.platform.test.annotations.Presubmit"
- },
- {
- "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
- }
- ]
- },
- {
- "name": "CtsMediaPlayerTestCases",
- "options": [
- {
- "include-annotation": "android.platform.test.annotations.Presubmit"
- },
- {
- "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
- }
- ]
}
]
}
diff --git a/media/codec2/components/aac/C2SoftAacDec.cpp b/media/codec2/components/aac/C2SoftAacDec.cpp
index 4e4a9a1..d1b08bd 100644
--- a/media/codec2/components/aac/C2SoftAacDec.cpp
+++ b/media/codec2/components/aac/C2SoftAacDec.cpp
@@ -275,7 +275,8 @@
mStreamInfo(nullptr),
mSignalledError(false),
mOutputPortDelay(kDefaultOutputPortDelay),
- mOutputDelayRingBuffer(nullptr) {
+ mOutputDelayRingBuffer(nullptr),
+ mDeviceApiLevel(android_get_device_api_level()) {
}
C2SoftAacDec::~C2SoftAacDec() {
@@ -891,7 +892,7 @@
work->worklets.front()->output.configUpdate.push_back(
C2Param::Copy(currentBoostFactor));
- if (android_get_device_api_level() < __ANDROID_API_S__) {
+ if (mDeviceApiLevel < __ANDROID_API_S__) {
// We used to report DRC compression mode in the output format
// in Q and R, but stopped doing that in S
C2StreamDrcCompressionModeTuning::input currentCompressMode(0u,
diff --git a/media/codec2/components/aac/C2SoftAacDec.h b/media/codec2/components/aac/C2SoftAacDec.h
index b45f148..f85d45f 100644
--- a/media/codec2/components/aac/C2SoftAacDec.h
+++ b/media/codec2/components/aac/C2SoftAacDec.h
@@ -97,6 +97,7 @@
int32_t mOutputDelayRingBufferWritePos;
int32_t mOutputDelayRingBufferReadPos;
int32_t mOutputDelayRingBufferFilled;
+ int mDeviceApiLevel;
bool outputDelayRingBufferPutSamples(INT_PCM *samples, int numSamples);
int32_t outputDelayRingBufferGetSamples(INT_PCM *samples, int numSamples);
int32_t outputDelayRingBufferSamplesAvailable();
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index 953afc5..96a4c4a 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -671,6 +671,9 @@
void C2SoftAvcDec::resetPlugin() {
mSignalledOutputEos = false;
mTimeStart = mTimeEnd = systemTime();
+ if (mOutBlock) {
+ mOutBlock.reset();
+ }
}
status_t C2SoftAvcDec::deleteDecoder() {
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index 8b46d3f..5d2856a 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -392,9 +392,9 @@
static C2R PictureQuantizationSetter(bool mayBlock,
C2P<C2StreamPictureQuantizationTuning::output> &me) {
(void)mayBlock;
- (void)me;
- // TODO: refactor with same algorithm in the SetQp()
+ // these are the ones we're going to set, so want them to default
+ // to the DEFAULT values for the codec
int32_t iMin = DEFAULT_I_QP_MIN, pMin = DEFAULT_P_QP_MIN, bMin = DEFAULT_B_QP_MIN;
int32_t iMax = DEFAULT_I_QP_MAX, pMax = DEFAULT_P_QP_MAX, bMax = DEFAULT_B_QP_MAX;
@@ -419,13 +419,14 @@
ALOGV("PictureQuantizationSetter(entry): i %d-%d p %d-%d b %d-%d",
iMin, iMax, pMin, pMax, bMin, bMax);
- // ensure we have legal values
- iMax = std::clamp(iMax, CODEC_QP_MIN, CODEC_QP_MAX);
- iMin = std::clamp(iMin, CODEC_QP_MIN, CODEC_QP_MAX);
- pMax = std::clamp(pMax, CODEC_QP_MIN, CODEC_QP_MAX);
- pMin = std::clamp(pMin, CODEC_QP_MIN, CODEC_QP_MAX);
- bMax = std::clamp(bMax, CODEC_QP_MIN, CODEC_QP_MAX);
- bMin = std::clamp(bMin, CODEC_QP_MIN, CODEC_QP_MAX);
+ // min is clamped to [AVC_QP_MIN, max] to avoid error
+ // cases where layer.min > layer.max
+ iMax = std::clamp(iMax, AVC_QP_MIN, AVC_QP_MAX);
+ iMin = std::clamp(iMin, AVC_QP_MIN, iMax);
+ pMax = std::clamp(pMax, AVC_QP_MIN, AVC_QP_MAX);
+ pMin = std::clamp(pMin, AVC_QP_MIN, pMax);
+ bMax = std::clamp(bMax, AVC_QP_MIN, AVC_QP_MAX);
+ bMin = std::clamp(bMin, AVC_QP_MIN, bMax);
// put them back into the structure
for (size_t i = 0; i < me.v.flexCount(); ++i) {
@@ -819,7 +820,8 @@
s_qp_ip.e_cmd = IVE_CMD_VIDEO_CTL;
s_qp_ip.e_sub_cmd = IVE_CMD_CTL_SET_QP;
- // TODO: refactor with same algorithm in the PictureQuantizationSetter()
+ // we resolved out-of-bound and unspecified values in PictureQuantizationSetter()
+ // so we can start with defaults that are overridden as needed.
int32_t iMin = DEFAULT_I_QP_MIN, pMin = DEFAULT_P_QP_MIN, bMin = DEFAULT_B_QP_MIN;
int32_t iMax = DEFAULT_I_QP_MAX, pMax = DEFAULT_P_QP_MAX, bMax = DEFAULT_B_QP_MAX;
@@ -1766,17 +1768,20 @@
// }
// }
// }
- std::shared_ptr<const C2GraphicView> view;
+ std::shared_ptr<C2GraphicView> view;
std::shared_ptr<C2Buffer> inputBuffer;
if (!work->input.buffers.empty()) {
inputBuffer = work->input.buffers[0];
- view = std::make_shared<const C2GraphicView>(
+ view = std::make_shared<C2GraphicView>(
inputBuffer->data().graphicBlocks().front().map().get());
if (view->error() != C2_OK) {
ALOGE("graphic view map err = %d", view->error());
work->workletsProcessed = 1u;
return;
}
+ //(b/232396154)
+ //workaround for incorrect crop size in view when using surface mode
+ view->setCrop_be(C2Rect(mSize->width, mSize->height));
}
do {
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.h b/media/codec2/components/avc/C2SoftAvcEnc.h
index 293867d..cde6604 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.h
+++ b/media/codec2/components/avc/C2SoftAvcEnc.h
@@ -103,8 +103,8 @@
/** limits as specified by h264
* (QP_MIN==4 is actually a limitation of this SW codec, not the H.264 standard)
**/
-#define CODEC_QP_MIN 4
-#define CODEC_QP_MAX 51
+#define AVC_QP_MIN 4
+#define AVC_QP_MAX 51
#define MIN(a, b) ((a) < (b))? (a) : (b)
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index 9d4f049..199875d 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -190,7 +190,7 @@
// matrix conversion coefficients
// (see media/libstagefright/colorconverter/ColorConverter.cpp for more details)
struct Coeffs {
- int32_t _y, _b_u, _g_u, _g_v, _r_v, _c16;
+ int32_t _y, _r_v, _g_u, _g_v, _b_u, _c16;
};
static const struct Coeffs GetCoeffsForAspects(const C2ColorAspectsStruct &aspects) {
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index 4dec57f..d234f21 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -102,6 +102,29 @@
.withSetter(Hdr10PlusInfoOutputSetter)
.build());
+ // default static info
+ C2HdrStaticMetadataStruct defaultStaticInfo{};
+ helper->addStructDescriptors<C2MasteringDisplayColorVolumeStruct, C2ColorXyStruct>();
+ addParameter(
+ DefineParam(mHdrStaticInfo, C2_PARAMKEY_HDR_STATIC_INFO)
+ .withDefault(new C2StreamHdrStaticInfo::output(0u, defaultStaticInfo))
+ .withFields({
+ C2F(mHdrStaticInfo, mastering.red.x).inRange(0, 1),
+ C2F(mHdrStaticInfo, mastering.red.y).inRange(0, 1),
+ C2F(mHdrStaticInfo, mastering.green.x).inRange(0, 1),
+ C2F(mHdrStaticInfo, mastering.green.y).inRange(0, 1),
+ C2F(mHdrStaticInfo, mastering.blue.x).inRange(0, 1),
+ C2F(mHdrStaticInfo, mastering.blue.y).inRange(0, 1),
+ C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
+ C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
+ C2F(mHdrStaticInfo, mastering.maxLuminance).inRange(0, 65535),
+ C2F(mHdrStaticInfo, mastering.minLuminance).inRange(0, 6.5535),
+ C2F(mHdrStaticInfo, maxCll).inRange(0, 0XFFFF),
+ C2F(mHdrStaticInfo, maxFall).inRange(0, 0XFFFF)
+ })
+ .withSetter(HdrStaticInfoSetter)
+ .build());
+
addParameter(
DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
.withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240))
@@ -331,6 +354,47 @@
// unsafe getters
std::shared_ptr<C2StreamPixelFormatInfo::output> getPixelFormat_l() const { return mPixelFormat; }
+ static C2R HdrStaticInfoSetter(bool mayBlock, C2P<C2StreamHdrStaticInfo::output> &me) {
+ (void)mayBlock;
+ if (me.v.mastering.red.x > 1) {
+ me.set().mastering.red.x = 1;
+ }
+ if (me.v.mastering.red.y > 1) {
+ me.set().mastering.red.y = 1;
+ }
+ if (me.v.mastering.green.x > 1) {
+ me.set().mastering.green.x = 1;
+ }
+ if (me.v.mastering.green.y > 1) {
+ me.set().mastering.green.y = 1;
+ }
+ if (me.v.mastering.blue.x > 1) {
+ me.set().mastering.blue.x = 1;
+ }
+ if (me.v.mastering.blue.y > 1) {
+ me.set().mastering.blue.y = 1;
+ }
+ if (me.v.mastering.white.x > 1) {
+ me.set().mastering.white.x = 1;
+ }
+ if (me.v.mastering.white.y > 1) {
+ me.set().mastering.white.y = 1;
+ }
+ if (me.v.mastering.maxLuminance > 65535.0) {
+ me.set().mastering.maxLuminance = 65535.0;
+ }
+ if (me.v.mastering.minLuminance > 6.5535) {
+ me.set().mastering.minLuminance = 6.5535;
+ }
+ if (me.v.maxCll > 65535.0) {
+ me.set().maxCll = 65535.0;
+ }
+ if (me.v.maxFall > 65535.0) {
+ me.set().maxFall = 65535.0;
+ }
+ return C2R::Ok();
+ }
+
private:
std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
@@ -343,6 +407,7 @@
std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput;
std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput;
+ std::shared_ptr<C2StreamHdrStaticInfo::output> mHdrStaticInfo;
};
C2SoftGav1Dec::C2SoftGav1Dec(const char *name, c2_node_id_t id,
@@ -558,6 +623,76 @@
}
}
+void C2SoftGav1Dec::getHDRStaticParams(const libgav1::DecoderBuffer *buffer,
+ const std::unique_ptr<C2Work> &work) {
+ C2StreamHdrStaticMetadataInfo::output hdrStaticMetadataInfo{};
+ bool infoPresent = false;
+ if (buffer->has_hdr_mdcv) {
+ // hdr_mdcv.primary_chromaticity_* values are in 0.16 fixed-point format.
+ hdrStaticMetadataInfo.mastering.red.x = buffer->hdr_mdcv.primary_chromaticity_x[0] / 65536.0;
+ hdrStaticMetadataInfo.mastering.red.y = buffer->hdr_mdcv.primary_chromaticity_y[0] / 65536.0;
+
+ hdrStaticMetadataInfo.mastering.green.x = buffer->hdr_mdcv.primary_chromaticity_x[1] / 65536.0;
+ hdrStaticMetadataInfo.mastering.green.y = buffer->hdr_mdcv.primary_chromaticity_y[1] / 65536.0;
+
+ hdrStaticMetadataInfo.mastering.blue.x = buffer->hdr_mdcv.primary_chromaticity_x[2] / 65536.0;
+ hdrStaticMetadataInfo.mastering.blue.y = buffer->hdr_mdcv.primary_chromaticity_y[2] / 65536.0;
+
+ // hdr_mdcv.white_point_chromaticity_* values are in 0.16 fixed-point format.
+ hdrStaticMetadataInfo.mastering.white.x = buffer->hdr_mdcv.white_point_chromaticity_x / 65536.0;
+ hdrStaticMetadataInfo.mastering.white.y = buffer->hdr_mdcv.white_point_chromaticity_y / 65536.0;
+
+ // hdr_mdcv.luminance_max is in 24.8 fixed-point format.
+ hdrStaticMetadataInfo.mastering.maxLuminance = buffer->hdr_mdcv.luminance_max / 256.0;
+ // hdr_mdcv.luminance_min is in 18.14 format.
+ hdrStaticMetadataInfo.mastering.minLuminance = buffer->hdr_mdcv.luminance_min / 16384.0;
+ infoPresent = true;
+ }
+
+ if (buffer->has_hdr_cll) {
+ hdrStaticMetadataInfo.maxCll = buffer->hdr_cll.max_cll;
+ hdrStaticMetadataInfo.maxFall = buffer->hdr_cll.max_fall;
+ infoPresent = true;
+ }
+ // config if static info has changed
+ if (infoPresent && !(hdrStaticMetadataInfo == mHdrStaticMetadataInfo)) {
+ mHdrStaticMetadataInfo = hdrStaticMetadataInfo;
+ work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(mHdrStaticMetadataInfo));
+ }
+}
+
+void C2SoftGav1Dec::getHDR10PlusInfoData(const libgav1::DecoderBuffer *buffer,
+ const std::unique_ptr<C2Work> &work) {
+ if (buffer->has_itut_t35) {
+ std::vector<uint8_t> payload;
+ size_t payloadSize = buffer->itut_t35.payload_size;
+ if (payloadSize > 0) {
+ payload.push_back(buffer->itut_t35.country_code);
+ if (buffer->itut_t35.country_code == 0xFF) {
+ payload.push_back(buffer->itut_t35.country_code_extension_byte);
+ }
+ payload.insert(payload.end(), buffer->itut_t35.payload_bytes,
+ buffer->itut_t35.payload_bytes + buffer->itut_t35.payload_size);
+ }
+
+ std::unique_ptr<C2StreamHdr10PlusInfo::output> hdr10PlusInfo =
+ C2StreamHdr10PlusInfo::output::AllocUnique(payload.size());
+ if (!hdr10PlusInfo) {
+ ALOGE("Hdr10PlusInfo allocation failed");
+ mSignalledError = true;
+ work->result = C2_NO_MEMORY;
+ return;
+ }
+ memcpy(hdr10PlusInfo->m.value, payload.data(), payload.size());
+
+ // config if hdr10Plus info has changed
+ if (nullptr == mHdr10PlusInfo || !(*hdr10PlusInfo == *mHdr10PlusInfo)) {
+ mHdr10PlusInfo = std::move(hdr10PlusInfo);
+ work->worklets.front()->output.configUpdate.push_back(std::move(mHdr10PlusInfo));
+ }
+ }
+}
+
void C2SoftGav1Dec::getVuiParams(const libgav1::DecoderBuffer *buffer) {
VuiColorAspects vuiColorAspects;
vuiColorAspects.primaries = buffer->color_primary;
@@ -633,6 +768,9 @@
}
getVuiParams(buffer);
+ getHDRStaticParams(buffer, work);
+ getHDR10PlusInfoData(buffer, work);
+
if (!(buffer->image_format == libgav1::kImageFormatYuv420 ||
buffer->image_format == libgav1::kImageFormatMonochrome400)) {
ALOGE("image_format %d not supported", buffer->image_format);
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h
index 3d4db55..f0e14d7 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.h
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.h
@@ -23,8 +23,8 @@
#include <SimpleC2Component.h>
#include <C2Config.h>
-#include "libgav1/src/gav1/decoder.h"
-#include "libgav1/src/gav1/decoder_settings.h"
+#include <gav1/decoder.h>
+#include <gav1/decoder_settings.h>
namespace android {
@@ -61,6 +61,9 @@
bool mSignalledOutputEos;
bool mSignalledError;
+ C2StreamHdrStaticMetadataInfo::output mHdrStaticMetadataInfo;
+ std::unique_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfo = nullptr;
+
// Color aspects. These are ISO values and are meant to detect changes in aspects to avoid
// converting them to C2 values for each frame
struct VuiColorAspects {
@@ -86,6 +89,10 @@
nsecs_t mTimeEnd = 0; // Time at the end of decode()
bool initDecoder();
+ void getHDRStaticParams(const libgav1::DecoderBuffer *buffer,
+ const std::unique_ptr<C2Work> &work);
+ void getHDR10PlusInfoData(const libgav1::DecoderBuffer *buffer,
+ const std::unique_ptr<C2Work> &work);
void getVuiParams(const libgav1::DecoderBuffer *buffer);
void destroyDecoder();
void finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index 5a660c5..15d6dcd 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -664,6 +664,9 @@
void C2SoftHevcDec::resetPlugin() {
mSignalledOutputEos = false;
mTimeStart = mTimeEnd = systemTime();
+ if (mOutBlock) {
+ mOutBlock.reset();
+ }
}
status_t C2SoftHevcDec::deleteDecoder() {
@@ -917,7 +920,8 @@
if (0 < ps_decode_op->u4_pic_wd && 0 < ps_decode_op->u4_pic_ht) {
if (mHeaderDecoded == false) {
mHeaderDecoded = true;
- setParams(ALIGN128(ps_decode_op->u4_pic_wd), IVD_DECODE_FRAME);
+ mStride = ALIGN128(ps_decode_op->u4_pic_wd);
+ setParams(mStride, IVD_DECODE_FRAME);
}
if (ps_decode_op->u4_pic_wd != mWidth || ps_decode_op->u4_pic_ht != mHeight) {
mWidth = ps_decode_op->u4_pic_wd;
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index 60d5875..9c26c02 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -1109,14 +1109,14 @@
}
}
- std::shared_ptr<const C2GraphicView> view;
+ std::shared_ptr<C2GraphicView> view;
std::shared_ptr<C2Buffer> inputBuffer = nullptr;
bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
if (eos) mSignalledEos = true;
if (!work->input.buffers.empty()) {
inputBuffer = work->input.buffers[0];
- view = std::make_shared<const C2GraphicView>(
+ view = std::make_shared<C2GraphicView>(
inputBuffer->data().graphicBlocks().front().map().get());
if (view->error() != C2_OK) {
ALOGE("graphic view map err = %d", view->error());
@@ -1125,6 +1125,9 @@
work->workletsProcessed = 1u;
return;
}
+ //(b/232396154)
+ //workaround for incorrect crop size in view when using surface mode
+ view->setCrop_be(C2Rect(mSize->width, mSize->height));
}
IHEVCE_PLUGIN_STATUS_T err = IHEVCE_EOK;
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index 9a41910..439323c 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -732,6 +732,9 @@
void C2SoftMpeg2Dec::resetPlugin() {
mSignalledOutputEos = false;
mTimeStart = mTimeEnd = systemTime();
+ if (mOutBlock) {
+ mOutBlock.reset();
+ }
}
status_t C2SoftMpeg2Dec::deleteDecoder() {
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
index 54a1d0e..3bf9c48 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
@@ -256,7 +256,9 @@
mFramesConfigured = false;
mSignalledOutputEos = false;
mSignalledError = false;
-
+ if (mOutBlock) {
+ mOutBlock.reset();
+ }
return C2_OK;
}
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
index 3bfec66..d5e8c56 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
@@ -464,18 +464,21 @@
}
}
- std::shared_ptr<const C2GraphicView> rView;
+ std::shared_ptr<C2GraphicView> rView;
std::shared_ptr<C2Buffer> inputBuffer;
bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
if (!work->input.buffers.empty()) {
inputBuffer = work->input.buffers[0];
- rView = std::make_shared<const C2GraphicView>(
+ rView = std::make_shared<C2GraphicView>(
inputBuffer->data().graphicBlocks().front().map().get());
if (rView->error() != C2_OK) {
ALOGE("graphic view map err = %d", rView->error());
work->result = rView->error();
return;
}
+ //(b/232396154)
+ //workaround for incorrect crop size in view when using surface mode
+ rView->setCrop_be(C2Rect(mSize->width, mSize->height));
} else {
fillEmptyWork(work);
if (eos) {
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.cpp b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
index f99ee24..5700e5d 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
@@ -59,7 +59,7 @@
addParameter(
DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
- .withDefault(new C2StreamPictureSizeInfo::input(0u, 320, 240))
+ .withDefault(new C2StreamPictureSizeInfo::input(0u, 64, 64))
.withFields({
C2F(mSize, width).inRange(2, 2048, 2),
C2F(mSize, height).inRange(2, 2048, 2),
@@ -81,7 +81,7 @@
addParameter(
DefineParam(mFrameRate, C2_PARAMKEY_FRAME_RATE)
- .withDefault(new C2StreamFrameRateInfo::output(0u, 30.))
+ .withDefault(new C2StreamFrameRateInfo::output(0u, 1.))
// TODO: More restriction?
.withFields({C2F(mFrameRate, value).greaterThan(0.)})
.withSetter(
@@ -127,10 +127,18 @@
C2F(mProfileLevel, profile).equalTo(
PROFILE_VP9_0
),
- C2F(mProfileLevel, level).equalTo(
- LEVEL_VP9_4_1),
+ C2F(mProfileLevel, level).oneOf({
+ C2Config::LEVEL_VP9_1,
+ C2Config::LEVEL_VP9_1_1,
+ C2Config::LEVEL_VP9_2,
+ C2Config::LEVEL_VP9_2_1,
+ C2Config::LEVEL_VP9_3,
+ C2Config::LEVEL_VP9_3_1,
+ C2Config::LEVEL_VP9_4,
+ C2Config::LEVEL_VP9_4_1,
+ }),
})
- .withSetter(ProfileLevelSetter)
+ .withSetter(ProfileLevelSetter, mSize, mFrameRate, mBitrate)
.build());
#else
addParameter(
@@ -144,7 +152,7 @@
C2F(mProfileLevel, level).equalTo(
LEVEL_UNUSED),
})
- .withSetter(ProfileLevelSetter)
+ .withSetter(ProfileLevelSetter, mSize, mFrameRate, mBitrate)
.build());
#endif
addParameter(
@@ -217,14 +225,81 @@
}
C2R C2SoftVpxEnc::IntfImpl::ProfileLevelSetter(bool mayBlock,
- C2P<C2StreamProfileLevelInfo::output>& me) {
+ C2P<C2StreamProfileLevelInfo::output>& me,
+ const C2P<C2StreamPictureSizeInfo::input>& size,
+ const C2P<C2StreamFrameRateInfo::output>& frameRate,
+ const C2P<C2StreamBitrateInfo::output>& bitrate) {
(void)mayBlock;
+#ifdef VP9
if (!me.F(me.v.profile).supportsAtAll(me.v.profile)) {
me.set().profile = PROFILE_VP9_0;
}
- if (!me.F(me.v.level).supportsAtAll(me.v.level)) {
+ struct LevelLimits {
+ C2Config::level_t level;
+ float samplesPerSec;
+ uint64_t samples;
+ uint32_t bitrate;
+ size_t dimension;
+ };
+ constexpr LevelLimits kLimits[] = {
+ {LEVEL_VP9_1, 829440, 36864, 200000, 512},
+ {LEVEL_VP9_1_1, 2764800, 73728, 800000, 768},
+ {LEVEL_VP9_2, 4608000, 122880, 1800000, 960},
+ {LEVEL_VP9_2_1, 9216000, 245760, 3600000, 1344},
+ {LEVEL_VP9_3, 20736000, 552960, 7200000, 2048},
+ {LEVEL_VP9_3_1, 36864000, 983040, 12000000, 2752},
+ {LEVEL_VP9_4, 83558400, 2228224, 18000000, 4160},
+ {LEVEL_VP9_4_1, 160432128, 2228224, 30000000, 4160},
+ };
+
+ uint64_t samples = size.v.width * size.v.height;
+ float samplesPerSec = float(samples) * frameRate.v.value;
+ size_t dimension = std::max(size.v.width, size.v.height);
+
+ // Check if the supplied level meets the samples / bitrate requirements.
+ // If not, update the level with the lowest level meeting the requirements.
+ bool found = false;
+
+ // By default needsUpdate = false in case the supplied level does meet
+ // the requirements.
+ bool needsUpdate = false;
+ for (const LevelLimits& limit : kLimits) {
+ if (samples <= limit.samples && samplesPerSec <= limit.samplesPerSec &&
+ bitrate.v.value <= limit.bitrate && dimension <= limit.dimension) {
+ // This is the lowest level that meets the requirements, and if
+ // we haven't seen the supplied level yet, that means we don't
+ // need the update.
+ if (needsUpdate) {
+ ALOGD("Given level %x does not cover current configuration: "
+ "adjusting to %x",
+ me.v.level, limit.level);
+ me.set().level = limit.level;
+ }
+ found = true;
+ break;
+ }
+ if (me.v.level == limit.level) {
+ // We break out of the loop when the lowest feasible level is
+ // found. The fact that we're here means that our level doesn't
+ // meet the requirement and needs to be updated.
+ needsUpdate = true;
+ }
+ }
+ if (!found) {
+ // We set to the highest supported level.
me.set().level = LEVEL_VP9_4_1;
}
+#else
+ (void)size;
+ (void)frameRate;
+ (void)bitrate;
+ if (!me.F(me.v.profile).supportsAtAll(me.v.profile)) {
+ me.set().profile = PROFILE_VP8_0;
+ }
+ if (!me.F(me.v.level).supportsAtAll(me.v.level)) {
+ me.set().level = LEVEL_UNUSED;
+ }
+#endif
return C2R::Ok();
}
@@ -683,17 +758,20 @@
return;
}
- std::shared_ptr<const C2GraphicView> rView;
+ std::shared_ptr<C2GraphicView> rView;
std::shared_ptr<C2Buffer> inputBuffer;
if (!work->input.buffers.empty()) {
inputBuffer = work->input.buffers[0];
- rView = std::make_shared<const C2GraphicView>(
+ rView = std::make_shared<C2GraphicView>(
inputBuffer->data().graphicBlocks().front().map().get());
if (rView->error() != C2_OK) {
ALOGE("graphic view map err = %d", rView->error());
work->result = C2_CORRUPTED;
return;
}
+ //(b/232396154)
+ //workaround for incorrect crop size in view when using surface mode
+ rView->setCrop_be(C2Rect(mSize->width, mSize->height));
} else {
ALOGV("Empty input Buffer");
uint32_t flags = 0;
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.h b/media/codec2/components/vpx/C2SoftVpxEnc.h
index 714fadb..bfb4444 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.h
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.h
@@ -243,9 +243,10 @@
static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::input> &oldMe,
C2P<C2StreamPictureSizeInfo::input> &me);
- static C2R ProfileLevelSetter(
- bool mayBlock,
- C2P<C2StreamProfileLevelInfo::output> &me);
+ static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::output>& me,
+ const C2P<C2StreamPictureSizeInfo::input>& size,
+ const C2P<C2StreamFrameRateInfo::output>& frameRate,
+ const C2P<C2StreamBitrateInfo::output>& bitrate);
static C2R LayeringSetter(bool mayBlock, C2P<C2StreamTemporalLayeringTuning::output>& me);
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 6ff3dbc..417b261 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -2503,7 +2503,8 @@
* Note: This parameter allows a decoder to ignore the video peek machinery and
* to revert to its preferred behavior.
*/
-typedef C2StreamParam<C2Tuning, C2EasyEnum<C2PlatformConfig::tunnel_peek_mode_t>,
+typedef C2StreamParam<C2Tuning,
+ C2SimpleValueStruct<C2EasyEnum<C2PlatformConfig::tunnel_peek_mode_t>>,
kParamIndexTunnelPeekMode> C2StreamTunnelPeekModeTuning;
constexpr char C2_PARAMKEY_TUNNEL_PEEK_MODE[] =
"output.tunnel-peek-mode";
diff --git a/media/codec2/fuzzer/C2Fuzzer.cpp b/media/codec2/fuzzer/C2Fuzzer.cpp
index e469d8b..d6793e0 100644
--- a/media/codec2/fuzzer/C2Fuzzer.cpp
+++ b/media/codec2/fuzzer/C2Fuzzer.cpp
@@ -246,7 +246,8 @@
bufferSource->parse();
c2_status_t status = C2_OK;
size_t numFrames = 0;
- while (!bufferSource->isEos()) {
+ int32_t iterationCount = 0;
+ while (!bufferSource->isEos() && ++iterationCount <= kMaxIterations) {
uint8_t* frame = nullptr;
size_t frameSize = 0;
FrameData frameData = bufferSource->getFrame();
diff --git a/media/codec2/fuzzer/C2Fuzzer.h b/media/codec2/fuzzer/C2Fuzzer.h
index da76885..4e3e3ea 100644
--- a/media/codec2/fuzzer/C2Fuzzer.h
+++ b/media/codec2/fuzzer/C2Fuzzer.h
@@ -37,6 +37,7 @@
#define C2FUZZER_ALIGN(_sz, _align) (((_sz) + ((_align)-1)) & ~((_align)-1))
constexpr std::chrono::milliseconds kC2FuzzerTimeOut = 5000ms;
+constexpr int32_t kMaxIterations = 100;
constexpr int32_t kNumberOfC2WorkItems = 8;
constexpr uint32_t kWidthOfVideo = 3840;
constexpr uint32_t kHeightOfVideo = 2160;
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
index bd7ec0d..327717b 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
@@ -372,9 +372,8 @@
ULock l(queueLock);
flushedIndices.emplace_back(frameID);
}
- char* data = (char*)malloc(bytesCount);
- ASSERT_NE(data, nullptr);
- eleStream.read(data, bytesCount);
+ std::vector<char> eleData(bytesCount);
+ eleStream.read(eleData.data(), bytesCount);
// if we have reached at the end of input stream, signal eos
if (eleStream.gcount() < bytesCount) {
bytesCount = eleStream.gcount();
@@ -396,12 +395,11 @@
ASSERT_EQ(0u, view.offset());
ASSERT_EQ((size_t)bytesCount, view.size());
- memcpy(view.base(), data, bytesCount);
+ memcpy(view.base(), eleData.data(), bytesCount);
work->input.buffers.clear();
work->input.buffers.emplace_back(new LinearBuffer(block));
work->worklets.clear();
work->worklets.emplace_back(new C2Worklet);
- free(data);
std::list<std::unique_ptr<C2Work>> items;
items.push_back(std::move(work));
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 67873fa..117d9ca 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -214,10 +214,8 @@
calc_md5_cksum(uPlane, uvStride, cropWidth / 2, cropHeight / 2, au1_u_chksum);
calc_md5_cksum(vPlane, uvStride, cropWidth / 2, cropHeight / 2, au1_v_chksum);
} else if (bitDepth == 8 && layoutType == C2PlanarLayout::TYPE_YUV && colInc == 2) {
- uint8_t* cbPlane = (uint8_t*)malloc(cropWidth * cropHeight / 4);
- uint8_t* crPlane = (uint8_t*)malloc(cropWidth * cropHeight / 4);
- ASSERT_NE(cbPlane, nullptr);
- ASSERT_NE(crPlane, nullptr);
+ std::vector<uint8_t> cbPlane(cropWidth * cropHeight / 4);
+ std::vector<uint8_t> crPlane(cropWidth * cropHeight / 4);
size_t count = 0;
for (size_t k = 0; k < (cropHeight / 2); k++) {
for (size_t l = 0; l < (cropWidth); l = l + 2) {
@@ -227,10 +225,10 @@
}
}
calc_md5_cksum(yPlane, yStride, cropWidth, cropHeight, au1_y_chksum);
- calc_md5_cksum(cbPlane, cropWidth / 2, cropWidth / 2, cropHeight / 2, au1_u_chksum);
- calc_md5_cksum(crPlane, cropWidth / 2, cropWidth / 2, cropHeight / 2, au1_v_chksum);
- free(cbPlane);
- free(crPlane);
+ calc_md5_cksum(cbPlane.data(), cropWidth / 2, cropWidth / 2, cropHeight / 2,
+ au1_u_chksum);
+ calc_md5_cksum(crPlane.data(), cropWidth / 2, cropWidth / 2, cropHeight / 2,
+ au1_v_chksum);
} else {
mMd5Enable = false;
ALOGV("Disabling MD5 chksm flag");
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 0acf7d7..9359e29 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -1582,6 +1582,10 @@
return mOutputBufferQueue->outputBuffer(block, input, output);
}
+void Codec2Client::Component::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
+ mOutputBufferQueue->pollForRenderedFrames(delta);
+}
+
void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
int maxDequeueCount) {
mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index 49d9b28..2fdca29 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -23,6 +23,7 @@
#include <C2Param.h>
#include <C2.h>
+#include <gui/FrameTimestamps.h>
#include <gui/IGraphicBufferProducer.h>
#include <hidl/HidlSupport.h>
#include <utils/StrongPointer.h>
@@ -408,6 +409,9 @@
const QueueBufferInput& input,
QueueBufferOutput* output);
+ // Retrieve frame event history from the output surface.
+ void pollForRenderedFrames(FrameEventHistoryDelta* delta);
+
// Set max dequeue count for output surface.
void setOutputSurfaceMaxDequeueCount(int maxDequeueCount);
diff --git a/media/codec2/hidl/client/include/codec2/hidl/output.h b/media/codec2/hidl/client/include/codec2/hidl/output.h
index a13edf3..35a0224 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/output.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/output.h
@@ -17,6 +17,7 @@
#ifndef CODEC2_HIDL_V1_0_UTILS_OUTPUT_BUFFER_QUEUE
#define CODEC2_HIDL_V1_0_UTILS_OUTPUT_BUFFER_QUEUE
+#include <gui/FrameTimestamps.h>
#include <gui/IGraphicBufferProducer.h>
#include <codec2/hidl/1.0/types.h>
#include <codec2/hidl/1.2/types.h>
@@ -60,6 +61,9 @@
const BnGraphicBufferProducer::QueueBufferInput& input,
BnGraphicBufferProducer::QueueBufferOutput* output);
+ // Retrieve frame event history from the output surface.
+ void pollForRenderedFrames(FrameEventHistoryDelta* delta);
+
// Call holdBufferQueueBlock() on output blocks in the given workList.
// The OutputBufferQueue will take the ownership of output blocks.
//
diff --git a/media/codec2/hidl/client/output.cpp b/media/codec2/hidl/client/output.cpp
index f789030..dd10691 100644
--- a/media/codec2/hidl/client/output.cpp
+++ b/media/codec2/hidl/client/output.cpp
@@ -476,6 +476,12 @@
return OK;
}
+void OutputBufferQueue::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
+ if (mIgbp) {
+ mIgbp->getFrameTimestamps(delta);
+ }
+}
+
void OutputBufferQueue::holdBufferQueueBlocks(
const std::list<std::unique_ptr<C2Work>>& workList) {
forEachBlock(workList,
diff --git a/media/codec2/hidl/plugin/samples/Android.bp b/media/codec2/hidl/plugin/samples/Android.bp
index 32b760d..e0f8280 100644
--- a/media/codec2/hidl/plugin/samples/Android.bp
+++ b/media/codec2/hidl/plugin/samples/Android.bp
@@ -28,6 +28,7 @@
"libGLESv1_CM",
"libGLESv2",
"libGLESv3",
+ "libvulkan",
"libbase",
"libcodec2",
"libcutils",
diff --git a/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp b/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp
index 5c13b0e..c8997bb 100644
--- a/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp
+++ b/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp
@@ -417,6 +417,7 @@
}
std::unique_lock lock(mQueueMutex);
mQueue.splice(mQueue.end(), *items);
+ mQueueCondition.notify_all();
return C2_OK;
}
@@ -665,6 +666,7 @@
grallocHandle, GraphicBuffer::CLONE_HANDLE,
width, height, format, 1, usage, stride);
+ native_handle_delete(grallocHandle);
std::shared_ptr<C2GraphicBlock> dstBlock;
C2BlockPool::local_id_t poolId = mIntf->getPoolId();
std::shared_ptr<C2BlockPool> pool;
@@ -683,6 +685,7 @@
grallocHandle, GraphicBuffer::CLONE_HANDLE,
width, height, format, 1, usage, stride);
+ native_handle_delete(grallocHandle);
Rect sourceCrop(0, 0, width, height);
renderengine::DisplaySettings clientCompositionDisplay;
diff --git a/media/codec2/hidl/services/Android.bp b/media/codec2/hidl/services/Android.bp
index b36e80a..524519c 100644
--- a/media/codec2/hidl/services/Android.bp
+++ b/media/codec2/hidl/services/Android.bp
@@ -85,6 +85,9 @@
arm64: {
src: "seccomp_policy/android.hardware.media.c2@1.2-default-arm64.policy",
},
+ riscv64: {
+ src: "seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy",
+ },
x86: {
src: "seccomp_policy/android.hardware.media.c2@1.2-default-x86.policy",
},
@@ -96,3 +99,4 @@
// This may be removed.
required: ["crash_dump.policy"],
}
+
diff --git a/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy
new file mode 100644
index 0000000..27f0b95
--- /dev/null
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy
@@ -0,0 +1,75 @@
+# Copyright (C) 2019 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.
+
+futex: 1
+# ioctl calls are filtered via the selinux policy.
+ioctl: 1
+sched_yield: 1
+close: 1
+dup: 1
+ppoll: 1
+mprotect: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+mmap: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+getuid: 1
+getrlimit: 1
+fstat: 1
+newfstatat: 1
+fstatfs: 1
+memfd_create: 1
+ftruncate: 1
+
+mremap: arg3 == 3 || arg3 == MREMAP_MAYMOVE
+munmap: 1
+prctl: 1
+writev: 1
+sigaltstack: 1
+clone: 1
+exit: 1
+lseek: 1
+rt_sigprocmask: 1
+openat: 1
+write: 1
+nanosleep: 1
+setpriority: 1
+set_tid_address: 1
+getdents64: 1
+readlinkat: 1
+read: 1
+pread64: 1
+gettimeofday: 1
+faccessat: 1
+exit_group: 1
+restart_syscall: 1
+rt_sigreturn: 1
+getrandom: 1
+madvise: 1
+
+# crash dump policy additions
+clock_gettime: 1
+getpid: 1
+gettid: 1
+pipe2: 1
+recvmsg: 1
+process_vm_readv: 1
+tgkill: 1
+rt_sigaction: 1
+rt_tgsigqueueinfo: 1
+#mprotect: arg2 in 0x1|0x2
+munmap: 1
+#mmap: arg2 in 0x1|0x2
+geteuid: 1
+getgid: 1
+getegid: 1
+getgroups: 1
+
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index 5a652a3..ecd5463 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -44,7 +44,7 @@
],
static_libs: [
- "SurfaceFlingerProperties",
+ "libSurfaceFlingerProperties",
],
shared_libs: [
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index feb0876..6e183e9 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1024,7 +1024,7 @@
C2StoreFlexiblePixelFormatDescriptorsInfo *pixelFormatInfo = nullptr;
int vendorSdkVersion = base::GetIntProperty(
"ro.vendor.build.version.sdk", android_get_device_api_level());
- if (vendorSdkVersion >= __ANDROID_API_S__ && mClient->query(
+ if (mClient->query(
{},
{C2StoreFlexiblePixelFormatDescriptorsInfo::PARAM_TYPE},
C2_MAY_BLOCK,
@@ -1085,8 +1085,7 @@
} else {
if ((config->mDomain & Config::IS_ENCODER) || !surface) {
if (vendorSdkVersion < __ANDROID_API_S__ &&
- (format == COLOR_FormatYUV420Flexible ||
- format == COLOR_FormatYUV420Planar ||
+ (format == COLOR_FormatYUV420Planar ||
format == COLOR_FormatYUV420PackedPlanar ||
format == COLOR_FormatYUV420SemiPlanar ||
format == COLOR_FormatYUV420PackedSemiPlanar)) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index c7ab360..36b2b3f 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -899,7 +899,7 @@
}
// TODO: revisit this after C2Fence implementation.
- android::IGraphicBufferProducer::QueueBufferInput qbi(
+ IGraphicBufferProducer::QueueBufferInput qbi(
timestampNs,
false, // droppable
dataSpace,
@@ -963,9 +963,9 @@
}
SetMetadataToGralloc4Handle(dataSpace, hdrStaticInfo, hdrDynamicInfo, block.handle());
- // we don't have dirty regions
- qbi.setSurfaceDamage(Region::INVALID_REGION);
- android::IGraphicBufferProducer::QueueBufferOutput qbo;
+ qbi.setSurfaceDamage(Region::INVALID_REGION); // we don't have dirty regions
+ qbi.getFrameTimestamps = true; // we need to know when a frame is rendered
+ IGraphicBufferProducer::QueueBufferOutput qbo;
status_t result = mComponent->queueToOutputSurface(block, qbi, &qbo);
if (result != OK) {
ALOGI("[%s] queueBuffer failed: %d", mName, result);
@@ -983,11 +983,107 @@
int64_t mediaTimeUs = 0;
(void)buffer->meta()->findInt64("timeUs", &mediaTimeUs);
- mCCodecCallback->onOutputFramesRendered(mediaTimeUs, timestampNs);
+ trackReleasedFrame(qbo, mediaTimeUs, timestampNs);
+ processRenderedFrames(qbo.frameTimestamps);
return OK;
}
+void CCodecBufferChannel::initializeFrameTrackingFor(ANativeWindow * window) {
+ int hasPresentFenceTimes = 0;
+ window->query(window, NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &hasPresentFenceTimes);
+ mHasPresentFenceTimes = hasPresentFenceTimes == 1;
+ if (mHasPresentFenceTimes) {
+ ALOGI("Using latch times for frame rendered signals - present fences not supported");
+ }
+ mTrackedFrames.clear();
+}
+
+void CCodecBufferChannel::trackReleasedFrame(const IGraphicBufferProducer::QueueBufferOutput& qbo,
+ int64_t mediaTimeUs, int64_t desiredRenderTimeNs) {
+ // If the render time is earlier than now, then we're suggesting it should be rendered ASAP,
+ // so track the frame as if the desired render time is now.
+ int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
+ if (desiredRenderTimeNs < nowNs) {
+ desiredRenderTimeNs = nowNs;
+ }
+ // We've just queued a frame to the surface, so keep track of it and later check to see if it is
+ // actually rendered.
+ TrackedFrame frame;
+ frame.number = qbo.nextFrameNumber - 1;
+ frame.mediaTimeUs = mediaTimeUs;
+ frame.desiredRenderTimeNs = desiredRenderTimeNs;
+ frame.latchTime = -1;
+ frame.presentFence = nullptr;
+ mTrackedFrames.push_back(frame);
+}
+
+void CCodecBufferChannel::processRenderedFrames(const FrameEventHistoryDelta& deltas) {
+ // Grab the latch times and present fences from the frame event deltas
+ for (const auto& delta : deltas) {
+ for (auto& frame : mTrackedFrames) {
+ if (delta.getFrameNumber() == frame.number) {
+ delta.getLatchTime(&frame.latchTime);
+ delta.getDisplayPresentFence(&frame.presentFence);
+ }
+ }
+ }
+
+ // Scan all frames and check to see if the frames that SHOULD have been rendered by now, have,
+ // in fact, been rendered.
+ int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
+ while (!mTrackedFrames.empty()) {
+ TrackedFrame & frame = mTrackedFrames.front();
+ // Frames that should have been rendered at least 100ms in the past are checked
+ if (frame.desiredRenderTimeNs > nowNs - 100*1000*1000LL) {
+ break;
+ }
+
+ // If we don't have a render time by now, then consider the frame as dropped
+ int64_t renderTimeNs = getRenderTimeNs(frame);
+ if (renderTimeNs != -1) {
+ mCCodecCallback->onOutputFramesRendered(frame.mediaTimeUs, renderTimeNs);
+ }
+ mTrackedFrames.pop_front();
+ }
+}
+
+int64_t CCodecBufferChannel::getRenderTimeNs(const TrackedFrame& frame) {
+ // If the device doesn't have accurate present fence times, then use the latch time as a proxy
+ if (!mHasPresentFenceTimes) {
+ if (frame.latchTime == -1) {
+ ALOGD("no latch time for frame %d", (int) frame.number);
+ return -1;
+ }
+ return frame.latchTime;
+ }
+
+ if (frame.presentFence == nullptr) {
+ ALOGW("no present fence for frame %d", (int) frame.number);
+ return -1;
+ }
+
+ nsecs_t actualRenderTimeNs = frame.presentFence->getSignalTime();
+
+ if (actualRenderTimeNs == Fence::SIGNAL_TIME_INVALID) {
+ ALOGW("invalid signal time for frame %d", (int) frame.number);
+ return -1;
+ }
+
+ if (actualRenderTimeNs == Fence::SIGNAL_TIME_PENDING) {
+ ALOGD("present fence has not fired for frame %d", (int) frame.number);
+ return -1;
+ }
+
+ return actualRenderTimeNs;
+}
+
+void CCodecBufferChannel::pollForRenderedBuffers() {
+ FrameEventHistoryDelta delta;
+ mComponent->pollForRenderedFrames(&delta);
+ processRenderedFrames(delta);
+}
+
status_t CCodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {
ALOGV("[%s] discardBuffer: %p", mName, buffer.get());
bool released = false;
@@ -1612,6 +1708,8 @@
Mutexed<Output>::Locked output(mOutput);
output->buffers.reset();
}
+ // reset the frames that are being tracked for onFrameRendered callbacks
+ mTrackedFrames.clear();
}
void CCodecBufferChannel::release() {
@@ -1680,6 +1778,8 @@
output->buffers->flushStash();
}
}
+ // reset the frames that are being tracked for onFrameRendered callbacks
+ mTrackedFrames.clear();
}
void CCodecBufferChannel::onWorkDone(
@@ -2153,6 +2253,7 @@
Mutexed<OutputSurface>::Locked output(mOutputSurface);
output->surface = newSurface;
output->generation = generation;
+ initializeFrameTrackingFor(static_cast<ANativeWindow *>(newSurface.get()));
}
if (oldSurface && pushBlankBuffer) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index a52d4dc..e2e55b9 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -18,6 +18,7 @@
#define CCODEC_BUFFER_CHANNEL_H_
+#include <deque>
#include <map>
#include <memory>
#include <vector>
@@ -88,6 +89,7 @@
const sp<MediaCodecBuffer> &buffer) override;
virtual status_t renderOutputBuffer(
const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
+ virtual void pollForRenderedBuffers() override;
virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
@@ -260,6 +262,14 @@
bool mRunning;
};
+ struct TrackedFrame {
+ uint64_t number;
+ int64_t mediaTimeUs;
+ int64_t desiredRenderTimeNs;
+ nsecs_t latchTime;
+ sp<Fence> presentFence;
+ };
+
void feedInputBufferIfAvailable();
void feedInputBufferIfAvailableInternal();
status_t queueInputBufferInternal(sp<MediaCodecBuffer> buffer,
@@ -272,6 +282,12 @@
void ensureDecryptDestination(size_t size);
int32_t getHeapSeqNum(const sp<hardware::HidlMemory> &memory);
+ void initializeFrameTrackingFor(ANativeWindow * window);
+ void trackReleasedFrame(const IGraphicBufferProducer::QueueBufferOutput& qbo,
+ int64_t mediaTimeUs, int64_t desiredRenderTimeNs);
+ void processRenderedFrames(const FrameEventHistoryDelta& delta);
+ int64_t getRenderTimeNs(const TrackedFrame& frame);
+
QueueSync mSync;
sp<MemoryDealer> mDealer;
sp<IMemory> mDecryptDestination;
@@ -313,6 +329,9 @@
sp<MemoryDealer> makeMemoryDealer(size_t heapSize);
+ std::deque<TrackedFrame> mTrackedFrames;
+ bool mHasPresentFenceTimes;
+
struct OutputSurface {
sp<Surface> surface;
uint32_t generation;
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index c8e9930..6335f13 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -72,7 +72,7 @@
virtual void getArray(Vector<sp<MediaCodecBuffer>> *) const {}
/**
- * Return number of buffers the client owns.
+ * Return number of buffers owned by the client or the component.
*/
virtual size_t numActiveSlots() const = 0;
@@ -595,8 +595,7 @@
void flush();
/**
- * Return the number of buffers that are sent to the client but not released
- * yet.
+ * Return the number of buffers that are sent to the client or the component.
*/
size_t numActiveSlots() const;
@@ -716,8 +715,7 @@
void grow(size_t newSize, std::function<sp<Codec2Buffer>()> alloc);
/**
- * Return the number of buffers that are sent to the client but not released
- * yet.
+ * Return the number of buffers that are sent to the client or the component.
*/
size_t numActiveSlots() const;
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 5208be6..0253815 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -389,7 +389,7 @@
// read back always as int
float value;
if (v.get(&value)) {
- return (int32_t)value;
+ return (int32_t) (value + 0.5);
}
return C2Value();
}));
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 55e0c45..8f0f1c9 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -22,6 +22,7 @@
#include <aidl/android/hardware/graphics/common/Cta861_3.h>
#include <aidl/android/hardware/graphics/common/Smpte2086.h>
+#include <android-base/no_destructor.h>
#include <android-base/properties.h>
#include <android/hardware/cas/native/1.0/types.h>
#include <android/hardware/drm/1.0/types.h>
@@ -533,7 +534,7 @@
* align(mHeight, 64) / plane.rowSampling;
}
- if (minPtr == mView.data()[0] && (maxPtr - minPtr + 1) <= planeSize) {
+ if (minPtr == mView.data()[0] && (maxPtr - minPtr) <= planeSize) {
// FIXME: this is risky as reading/writing data out of bound results
// in an undefined behavior, but gralloc does assume a
// contiguous mapping
@@ -545,8 +546,7 @@
mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
}
- mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
- maxPtr - minPtr + 1);
+ mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr);
ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity());
}
}
@@ -843,6 +843,10 @@
}
}
sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * bpp / 8));
+ if (aBuffer == nullptr) {
+ ALOGD("%s: failed to allocate buffer", __func__);
+ return nullptr;
+ }
return new ConstGraphicBlockBuffer(
format,
aBuffer,
@@ -1015,8 +1019,8 @@
namespace {
sp<IMapper4> GetMapper4() {
- static sp<IMapper4> sMapper = IMapper4::getService();
- return sMapper;
+ static ::android::base::NoDestructor<sp<IMapper4>> sMapper(IMapper4::getService());
+ return *sMapper;
}
class Gralloc4Buffer {
diff --git a/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp b/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
index ef5800d..332d3ac 100644
--- a/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
@@ -38,7 +38,7 @@
!strcmp(deviceCodeName, "Tiramisu");
}
-bool isVendorApiOrFirstApiAtLeastT() {
+static bool isP010Allowed() {
// The first SDK the device shipped with.
static const int32_t kProductFirstApiLevel =
base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
@@ -47,6 +47,17 @@
// to signal which VSR requirements they conform to even if the first device SDK was higher.
static const int32_t kBoardFirstApiLevel =
base::GetIntProperty<int32_t>("ro.board.first_api_level", 0);
+
+ // Some devices that launched prior to Android S may not support P010 correctly, even
+ // though they may advertise it as supported.
+ if (kProductFirstApiLevel != 0 && kProductFirstApiLevel < __ANDROID_API_S__) {
+ return false;
+ }
+
+ if (kBoardFirstApiLevel != 0 && kBoardFirstApiLevel < __ANDROID_API_S__) {
+ return false;
+ }
+
static const int32_t kBoardApiLevel =
base::GetIntProperty<int32_t>("ro.board.api_level", 0);
@@ -67,7 +78,7 @@
// API alone. For now limit P010 to devices that launched with Android T or known to conform
// to Android T VSR (as opposed to simply limiting to a T vendor image).
if (format == (AHardwareBuffer_Format)HAL_PIXEL_FORMAT_YCBCR_P010 &&
- !isVendorApiOrFirstApiAtLeastT()) {
+ !isP010Allowed()) {
return false;
}
diff --git a/media/codec2/tests/Android.bp b/media/codec2/tests/Android.bp
index 9c3ba4d..2217235 100644
--- a/media/codec2/tests/Android.bp
+++ b/media/codec2/tests/Android.bp
@@ -36,6 +36,8 @@
cc_test {
name: "codec2_vndk_test",
test_suites: ["device-tests"],
+ // This test doesn't seem to support isolated with current assumption
+ isolated: false,
srcs: [
"C2_test.cpp",
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index bc4053d..f272499 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -54,6 +54,10 @@
static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
} // unnamed
+static bool isAtLeastT() {
+ return android_get_device_api_level() >= __ANDROID_API_T__;
+}
+
C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) {
// gralloc does not support WRITE_PROTECTED
return C2MemoryUsage(
@@ -702,6 +706,14 @@
}
case static_cast<uint32_t>(PixelFormat4::YCBCR_P010): {
+ // In Android T, P010 is relaxed to allow arbitrary stride for the Y and UV planes,
+ // try locking with the gralloc4 mapper first.
+ c2_status_t status = Gralloc4Mapper_lock(
+ const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, layout, addr);
+ if (status == C2_OK) {
+ break;
+ }
+
void *pointer = nullptr;
status_t err = GraphicBufferMapper::get().lock(
const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
@@ -760,10 +772,12 @@
default: {
// We don't know what it is, let's try to lock it with gralloc4
android_ycbcr ycbcrLayout;
- c2_status_t status = Gralloc4Mapper_lock(
- const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, layout, addr);
- if (status == C2_OK) {
- break;
+ if (isAtLeastT()) {
+ c2_status_t status = Gralloc4Mapper_lock(
+ const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, layout, addr);
+ if (status == C2_OK) {
+ break;
+ }
}
// fallback to lockYCbCr
diff --git a/media/codec2/vndk/C2Fence.cpp b/media/codec2/vndk/C2Fence.cpp
index 0b556aa..aa908a8 100644
--- a/media/codec2/vndk/C2Fence.cpp
+++ b/media/codec2/vndk/C2Fence.cpp
@@ -186,7 +186,7 @@
class _C2FenceFactory::SyncFenceImpl : public C2Fence::Impl {
public:
virtual c2_status_t wait(c2_nsecs_t timeoutNs) {
- c2_nsecs_t timeoutMs = timeoutNs / 1000;
+ int64_t timeoutMs = timeoutNs / 1000000;
if (timeoutMs > INT_MAX) {
timeoutMs = INT_MAX;
}
diff --git a/media/codec2/vndk/internal/C2BlockInternal.h b/media/codec2/vndk/internal/C2BlockInternal.h
index c510fca..6bcad4a 100644
--- a/media/codec2/vndk/internal/C2BlockInternal.h
+++ b/media/codec2/vndk/internal/C2BlockInternal.h
@@ -238,7 +238,7 @@
* - Local migration on blockpool side will be done automatically by
* blockpool.
* - Before attachBuffer(), BeginAttachBlockToBufferQueue() should be called
- * to test eligiblity.
+ * to test eligibility.
* - After attachBuffer() is called, EndAttachBlockToBufferQueue() should
* be called. This will set "held" status to true. If it returned
* false, cancelBuffer() should be called.
diff --git a/media/janitors/avic_OWNERS b/media/janitors/avic_OWNERS
new file mode 100644
index 0000000..eca9978
--- /dev/null
+++ b/media/janitors/avic_OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 1344
+# gerrit owner/approvers in the AVIC team
+arifdikici@google.com
+dichenzhang@google.com
+kyslov@google.com
+richardxie@google.com
diff --git a/media/libaaudio/Android.bp b/media/libaaudio/Android.bp
index add28e0..4b417a7 100644
--- a/media/libaaudio/Android.bp
+++ b/media/libaaudio/Android.bp
@@ -36,6 +36,9 @@
symbol_file: "src/libaaudio.map.txt",
first_version: "26",
unversioned_until: "current",
+ export_header_libs: [
+ "libAAudio_headers",
+ ],
}
cc_library_headers {
diff --git a/media/libaaudio/examples/loopback/src/loopback.cpp b/media/libaaudio/examples/loopback/src/loopback.cpp
index 6fff568..4affaed 100644
--- a/media/libaaudio/examples/loopback/src/loopback.cpp
+++ b/media/libaaudio/examples/loopback/src/loopback.cpp
@@ -108,7 +108,7 @@
aaudio_result_t outputError = AAUDIO_OK;
GlitchAnalyzer sineAnalyzer;
- PulseLatencyAnalyzer echoAnalyzer;
+ WhiteNoiseLatencyAnalyzer echoAnalyzer;
AudioRecording audioRecording;
LoopbackProcessor *loopbackProcessor;
diff --git a/media/libaaudio/fuzzer/Android.bp b/media/libaaudio/fuzzer/Android.bp
index 2a12191..3393930 100644
--- a/media/libaaudio/fuzzer/Android.bp
+++ b/media/libaaudio/fuzzer/Android.bp
@@ -25,6 +25,9 @@
cc_fuzz {
name: "libaaudio_fuzzer",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_static",
+ ],
srcs: [
"libaaudio_fuzzer.cpp",
],
@@ -36,10 +39,10 @@
"libaudiomanager",
"libaudiopolicy",
"libaudioclient_aidl_conversion",
+ "libaudio_aidl_conversion_common_cpp",
"libutils",
],
static_libs: [
- "android.media.audio.common.types-V1-cpp",
"liblog",
"libcutils",
"libaaudio",
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 2ff9f5a..0c4a8f7 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -40,7 +40,7 @@
/**
* This is used to represent a value that has not been specified.
* For example, an application could use {@link #AAUDIO_UNSPECIFIED} to indicate
- * that is did not not care what the specific value of a parameter was
+ * that it did not care what the specific value of a parameter was
* and would accept whatever it was given.
*/
#define AAUDIO_UNSPECIFIED 0
diff --git a/media/libaaudio/src/Android.bp b/media/libaaudio/src/Android.bp
index 363d219..4c5fc71 100644
--- a/media/libaaudio/src/Android.bp
+++ b/media/libaaudio/src/Android.bp
@@ -134,6 +134,10 @@
cc_library {
name: "libaaudio_internal",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+
local_include_dirs: [
"binding",
"client",
@@ -167,7 +171,6 @@
"libbinder",
"framework-permission-aidl-cpp",
"aaudio-aidl-cpp",
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
"libaudioclient_aidl_conversion",
],
@@ -260,7 +263,7 @@
"binding/aidl/aaudio/IAAudioService.aidl",
],
imports: [
- "android.media.audio.common.types-V1",
+ "android.media.audio.common.types-V2",
"audioclient-types-aidl",
"shared-file-region-aidl",
"framework-permission-aidl",
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
index 1efccb1..f5cc2be 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
@@ -25,6 +25,7 @@
#include "client/AudioStreamInternalCapture.h"
#include "utility/AudioClock.h"
+#undef ATRACE_TAG
#define ATRACE_TAG ATRACE_TAG_AUDIO
#include <utils/Trace.h>
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 90ff4a5..938079b 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -566,9 +566,7 @@
int64_t *timeNanoseconds)
{
AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
- if (framePosition == nullptr) {
- return AAUDIO_ERROR_NULL;
- } else if (timeNanoseconds == nullptr) {
+ if (framePosition == nullptr || timeNanoseconds == nullptr) {
return AAUDIO_ERROR_NULL;
} else if (clockid != CLOCK_MONOTONIC && clockid != CLOCK_BOOTTIME) {
return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index 8b7b75e..31fd011 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -83,7 +83,6 @@
switch (mSessionId) {
case AAUDIO_SESSION_ID_NONE:
case AAUDIO_SESSION_ID_ALLOCATE:
- break;
default:
break;
}
diff --git a/media/libaaudio/tests/test_attributes.cpp b/media/libaaudio/tests/test_attributes.cpp
index b88d562..e5676a7 100644
--- a/media/libaaudio/tests/test_attributes.cpp
+++ b/media/libaaudio/tests/test_attributes.cpp
@@ -20,6 +20,7 @@
// "test_aaudio_attributes.cpp". That other file is more current.
// So these tests could be deleted.
+#include <memory>
#include <stdio.h>
#include <unistd.h>
@@ -40,7 +41,7 @@
int privacyMode = DONT_SET,
aaudio_direction_t direction = AAUDIO_DIRECTION_OUTPUT) {
- float *buffer = new float[kNumFrames * kChannelCount];
+ std::unique_ptr<float[]> buffer(new float[kNumFrames * kChannelCount]);
AAudioStreamBuilder *aaudioBuilder = nullptr;
AAudioStream *aaudioStream = nullptr;
@@ -109,16 +110,15 @@
if (direction == AAUDIO_DIRECTION_INPUT) {
EXPECT_EQ(kNumFrames,
- AAudioStream_read(aaudioStream, buffer, kNumFrames, kNanosPerSecond));
+ AAudioStream_read(aaudioStream, buffer.get(), kNumFrames, kNanosPerSecond));
} else {
EXPECT_EQ(kNumFrames,
- AAudioStream_write(aaudioStream, buffer, kNumFrames, kNanosPerSecond));
+ AAudioStream_write(aaudioStream, buffer.get(), kNumFrames, kNanosPerSecond));
}
EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
- delete[] buffer;
}
static const aaudio_usage_t sUsages[] = {
diff --git a/media/libaaudio/tests/test_recovery.cpp b/media/libaaudio/tests/test_recovery.cpp
index 6e89f83..11331af 100644
--- a/media/libaaudio/tests/test_recovery.cpp
+++ b/media/libaaudio/tests/test_recovery.cpp
@@ -16,6 +16,7 @@
// Play silence and recover from dead servers or disconnected devices.
+#include <memory>
#include <stdio.h>
#include <aaudio/AAudio.h>
@@ -32,7 +33,6 @@
int32_t triesLeft = 3;
int32_t bufferCapacity;
int32_t framesPerBurst = 0;
- float *buffer = nullptr;
int32_t actualChannelCount = 0;
int32_t actualSampleRate = 0;
@@ -83,7 +83,7 @@
bufferCapacity, framesPerBurst);
int samplesPerBurst = framesPerBurst * actualChannelCount;
- buffer = new float[samplesPerBurst];
+ std::unique_ptr<float[]> buffer(new float[samplesPerBurst]);
result = AAudioStream_requestStart(aaudioStream);
if (result != AAUDIO_OK) {
@@ -98,7 +98,7 @@
int64_t printAt = actualSampleRate;
while (result == AAUDIO_OK && framesTotal < framesMax) {
int32_t framesWritten = AAudioStream_write(aaudioStream,
- buffer, framesPerBurst,
+ buffer.get(), framesPerBurst,
DEFAULT_TIMEOUT_NANOS);
if (framesWritten < 0) {
result = framesWritten;
@@ -134,6 +134,5 @@
AAudioStream_close(aaudioStream);
}
AAudioStreamBuilder_delete(aaudioBuilder);
- delete[] buffer;
printf(" result = %d = %s\n", result, AAudio_convertResultToText(result));
}
diff --git a/media/libaaudio/tests/test_session_id.cpp b/media/libaaudio/tests/test_session_id.cpp
index 3f7d4fc..5968b5d 100644
--- a/media/libaaudio/tests/test_session_id.cpp
+++ b/media/libaaudio/tests/test_session_id.cpp
@@ -16,6 +16,7 @@
// Test AAudio SessionId, which is used to associate Effects with a stream
+#include <memory>
#include <stdio.h>
#include <unistd.h>
@@ -29,7 +30,7 @@
// Test AAUDIO_SESSION_ID_NONE default
static void checkSessionIdNone(aaudio_performance_mode_t perfMode) {
- float *buffer = new float[kNumFrames * kChannelCount];
+ std::unique_ptr<float[]> buffer(new float[kNumFrames * kChannelCount]);
AAudioStreamBuilder *aaudioBuilder = nullptr;
@@ -51,12 +52,12 @@
ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream1));
- ASSERT_EQ(kNumFrames, AAudioStream_write(aaudioStream1, buffer, kNumFrames, kNanosPerSecond));
+ ASSERT_EQ(kNumFrames,
+ AAudioStream_write(aaudioStream1, buffer.get(), kNumFrames, kNanosPerSecond));
EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream1));
EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream1));
- delete[] buffer;
AAudioStreamBuilder_delete(aaudioBuilder);
}
@@ -72,7 +73,7 @@
static void checkSessionIdAllocate(aaudio_performance_mode_t perfMode,
aaudio_direction_t direction) {
- float *buffer = new float[kNumFrames * kChannelCount];
+ std::unique_ptr<float[]> buffer(new float[kNumFrames * kChannelCount]);
AAudioStreamBuilder *aaudioBuilder = nullptr;
@@ -106,10 +107,10 @@
if (direction == AAUDIO_DIRECTION_INPUT) {
ASSERT_EQ(kNumFrames, AAudioStream_read(aaudioStream1,
- buffer, kNumFrames, kNanosPerSecond));
+ buffer.get(), kNumFrames, kNanosPerSecond));
} else {
ASSERT_EQ(kNumFrames, AAudioStream_write(aaudioStream1,
- buffer, kNumFrames, kNanosPerSecond));
+ buffer.get(), kNumFrames, kNanosPerSecond));
}
EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream1));
@@ -135,10 +136,10 @@
if (otherDirection == AAUDIO_DIRECTION_INPUT) {
ASSERT_EQ(kNumFrames, AAudioStream_read(aaudioStream2,
- buffer, kNumFrames, kNanosPerSecond));
+ buffer.get(), kNumFrames, kNanosPerSecond));
} else {
ASSERT_EQ(kNumFrames, AAudioStream_write(aaudioStream2,
- buffer, kNumFrames, kNanosPerSecond));
+ buffer.get(), kNumFrames, kNanosPerSecond));
}
EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream2));
@@ -147,7 +148,6 @@
EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream1));
- delete[] buffer;
AAudioStreamBuilder_delete(aaudioBuilder);
}
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 4133bd0..b32667e 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -42,9 +42,6 @@
using media::audio::common::AudioDeviceAddress;
using media::audio::common::AudioDeviceDescription;
using media::audio::common::AudioDeviceType;
-using media::audio::common::AudioEncapsulationMetadataType;
-using media::audio::common::AudioEncapsulationMode;
-using media::audio::common::AudioEncapsulationType;
using media::audio::common::AudioFormatDescription;
using media::audio::common::AudioFormatType;
using media::audio::common::AudioGain;
@@ -69,246 +66,6 @@
using media::audio::common::Int;
using media::audio::common::PcmType;
-namespace {
-
-enum class Direction {
- INPUT, OUTPUT
-};
-
-ConversionResult<Direction> direction(media::AudioPortRole role, media::AudioPortType type) {
- switch (type) {
- case media::AudioPortType::NONE:
- case media::AudioPortType::SESSION:
- break; // must be listed -Werror,-Wswitch
- case media::AudioPortType::DEVICE:
- switch (role) {
- case media::AudioPortRole::NONE:
- break; // must be listed -Werror,-Wswitch
- case media::AudioPortRole::SOURCE:
- return Direction::INPUT;
- case media::AudioPortRole::SINK:
- return Direction::OUTPUT;
- }
- break;
- case media::AudioPortType::MIX:
- switch (role) {
- case media::AudioPortRole::NONE:
- break; // must be listed -Werror,-Wswitch
- case media::AudioPortRole::SOURCE:
- return Direction::OUTPUT;
- case media::AudioPortRole::SINK:
- return Direction::INPUT;
- }
- break;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<Direction> direction(audio_port_role_t role, audio_port_type_t type) {
- switch (type) {
- case AUDIO_PORT_TYPE_NONE:
- case AUDIO_PORT_TYPE_SESSION:
- break; // must be listed -Werror,-Wswitch
- case AUDIO_PORT_TYPE_DEVICE:
- switch (role) {
- case AUDIO_PORT_ROLE_NONE:
- break; // must be listed -Werror,-Wswitch
- case AUDIO_PORT_ROLE_SOURCE:
- return Direction::INPUT;
- case AUDIO_PORT_ROLE_SINK:
- return Direction::OUTPUT;
- }
- break;
- case AUDIO_PORT_TYPE_MIX:
- switch (role) {
- case AUDIO_PORT_ROLE_NONE:
- break; // must be listed -Werror,-Wswitch
- case AUDIO_PORT_ROLE_SOURCE:
- return Direction::OUTPUT;
- case AUDIO_PORT_ROLE_SINK:
- return Direction::INPUT;
- }
- break;
- }
- return unexpected(BAD_VALUE);
-}
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Converters
-
-status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize) {
- if (aidl.size() > maxSize - 1) {
- return BAD_VALUE;
- }
- aidl.copy(dest, aidl.size());
- dest[aidl.size()] = '\0';
- return OK;
-}
-
-ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize) {
- if (legacy == nullptr) {
- return unexpected(BAD_VALUE);
- }
- if (strnlen(legacy, maxSize) == maxSize) {
- // No null-terminator.
- return unexpected(BAD_VALUE);
- }
- return std::string(legacy);
-}
-
-ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl) {
- return convertReinterpret<audio_module_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl) {
- return convertReinterpret<audio_io_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl) {
- return convertReinterpret<audio_port_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl) {
- return convertReinterpret<audio_patch_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl) {
- return convertReinterpret<audio_unique_id_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl) {
- return convertReinterpret<audio_hw_sync_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl) {
- return convertReinterpret<pid_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl) {
- return convertReinterpret<uid_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl) {
- return String16(aidl.data(), aidl.size());
-}
-
-ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy) {
- return std::string(String8(legacy).c_str());
-}
-
-// TODO b/182392769: create an optional -> optional util
-ConversionResult<std::optional<String16>>
-aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl) {
- if (!aidl.has_value()) {
- return std::nullopt;
- }
- ConversionResult<String16> conversion =
- VALUE_OR_RETURN(aidl2legacy_string_view_String16(aidl.value()));
- return conversion.value();
-}
-
-ConversionResult<std::optional<std::string_view>>
-legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy) {
- if (!legacy.has_value()) {
- return std::nullopt;
- }
- ConversionResult<std::string> conversion =
- VALUE_OR_RETURN(legacy2aidl_String16_string(legacy.value()));
- return conversion.value();
-}
-
-ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl) {
- return String8(aidl.data(), aidl.size());
-}
-
-ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy) {
- return std::string(legacy.c_str());
-}
-
-ConversionResult<audio_io_config_event_t> aidl2legacy_AudioIoConfigEvent_audio_io_config_event_t(
- media::AudioIoConfigEvent aidl) {
- switch (aidl) {
- case media::AudioIoConfigEvent::OUTPUT_REGISTERED:
- return AUDIO_OUTPUT_REGISTERED;
- case media::AudioIoConfigEvent::OUTPUT_OPENED:
- return AUDIO_OUTPUT_OPENED;
- case media::AudioIoConfigEvent::OUTPUT_CLOSED:
- return AUDIO_OUTPUT_CLOSED;
- case media::AudioIoConfigEvent::OUTPUT_CONFIG_CHANGED:
- return AUDIO_OUTPUT_CONFIG_CHANGED;
- case media::AudioIoConfigEvent::INPUT_REGISTERED:
- return AUDIO_INPUT_REGISTERED;
- case media::AudioIoConfigEvent::INPUT_OPENED:
- return AUDIO_INPUT_OPENED;
- case media::AudioIoConfigEvent::INPUT_CLOSED:
- return AUDIO_INPUT_CLOSED;
- case media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED:
- return AUDIO_INPUT_CONFIG_CHANGED;
- case media::AudioIoConfigEvent::CLIENT_STARTED:
- return AUDIO_CLIENT_STARTED;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioIoConfigEvent> legacy2aidl_audio_io_config_event_t_AudioIoConfigEvent(
- audio_io_config_event_t legacy) {
- switch (legacy) {
- case AUDIO_OUTPUT_REGISTERED:
- return media::AudioIoConfigEvent::OUTPUT_REGISTERED;
- case AUDIO_OUTPUT_OPENED:
- return media::AudioIoConfigEvent::OUTPUT_OPENED;
- case AUDIO_OUTPUT_CLOSED:
- return media::AudioIoConfigEvent::OUTPUT_CLOSED;
- case AUDIO_OUTPUT_CONFIG_CHANGED:
- return media::AudioIoConfigEvent::OUTPUT_CONFIG_CHANGED;
- case AUDIO_INPUT_REGISTERED:
- return media::AudioIoConfigEvent::INPUT_REGISTERED;
- case AUDIO_INPUT_OPENED:
- return media::AudioIoConfigEvent::INPUT_OPENED;
- case AUDIO_INPUT_CLOSED:
- return media::AudioIoConfigEvent::INPUT_CLOSED;
- case AUDIO_INPUT_CONFIG_CHANGED:
- return media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED;
- case AUDIO_CLIENT_STARTED:
- return media::AudioIoConfigEvent::CLIENT_STARTED;
- }
- return unexpected(BAD_VALUE);
-}
-
ConversionResult<audio_port_role_t> aidl2legacy_AudioPortRole_audio_port_role_t(
media::AudioPortRole aidl) {
switch (aidl) {
@@ -365,1507 +122,97 @@
return unexpected(BAD_VALUE);
}
-namespace {
-
-namespace detail {
-using AudioChannelBitPair = std::pair<audio_channel_mask_t, int>;
-using AudioChannelBitPairs = std::vector<AudioChannelBitPair>;
-using AudioChannelPair = std::pair<audio_channel_mask_t, AudioChannelLayout>;
-using AudioChannelPairs = std::vector<AudioChannelPair>;
-using AudioDevicePair = std::pair<audio_devices_t, AudioDeviceDescription>;
-using AudioDevicePairs = std::vector<AudioDevicePair>;
-using AudioFormatPair = std::pair<audio_format_t, AudioFormatDescription>;
-using AudioFormatPairs = std::vector<AudioFormatPair>;
+ConversionResult<AudioPortDirection> portDirection(
+ media::AudioPortRole role, media::AudioPortType type) {
+ audio_port_role_t legacyRole = VALUE_OR_RETURN(
+ aidl2legacy_AudioPortRole_audio_port_role_t(role));
+ audio_port_type_t legacyType = VALUE_OR_RETURN(
+ aidl2legacy_AudioPortType_audio_port_type_t(type));
+ return portDirection(legacyRole, legacyType);
}
-const detail::AudioChannelBitPairs& getInAudioChannelBits() {
- static const detail::AudioChannelBitPairs pairs = {
- { AUDIO_CHANNEL_IN_LEFT, AudioChannelLayout::CHANNEL_FRONT_LEFT },
- { AUDIO_CHANNEL_IN_RIGHT, AudioChannelLayout::CHANNEL_FRONT_RIGHT },
- // AUDIO_CHANNEL_IN_FRONT is at the end
- { AUDIO_CHANNEL_IN_BACK, AudioChannelLayout::CHANNEL_BACK_CENTER },
- // AUDIO_CHANNEL_IN_*_PROCESSED not supported
- // AUDIO_CHANNEL_IN_PRESSURE not supported
- // AUDIO_CHANNEL_IN_*_AXIS not supported
- // AUDIO_CHANNEL_IN_VOICE_* not supported
- { AUDIO_CHANNEL_IN_BACK_LEFT, AudioChannelLayout::CHANNEL_BACK_LEFT },
- { AUDIO_CHANNEL_IN_BACK_RIGHT, AudioChannelLayout::CHANNEL_BACK_RIGHT },
- { AUDIO_CHANNEL_IN_CENTER, AudioChannelLayout::CHANNEL_FRONT_CENTER },
- { AUDIO_CHANNEL_IN_LOW_FREQUENCY, AudioChannelLayout::CHANNEL_LOW_FREQUENCY },
- { AUDIO_CHANNEL_IN_TOP_LEFT, AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT },
- { AUDIO_CHANNEL_IN_TOP_RIGHT, AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT },
- // When going from aidl to legacy, IN_CENTER is used
- { AUDIO_CHANNEL_IN_FRONT, AudioChannelLayout::CHANNEL_FRONT_CENTER }
- };
- return pairs;
-}
-
-const detail::AudioChannelPairs& getInAudioChannelPairs() {
- static const detail::AudioChannelPairs pairs = {
-#define DEFINE_INPUT_LAYOUT(n) \
- { \
- AUDIO_CHANNEL_IN_##n, \
- AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
- AudioChannelLayout::LAYOUT_##n) \
- }
-
- DEFINE_INPUT_LAYOUT(MONO),
- DEFINE_INPUT_LAYOUT(STEREO),
- DEFINE_INPUT_LAYOUT(FRONT_BACK),
- // AUDIO_CHANNEL_IN_6 not supported
- DEFINE_INPUT_LAYOUT(2POINT0POINT2),
- DEFINE_INPUT_LAYOUT(2POINT1POINT2),
- DEFINE_INPUT_LAYOUT(3POINT0POINT2),
- DEFINE_INPUT_LAYOUT(3POINT1POINT2),
- DEFINE_INPUT_LAYOUT(5POINT1)
-#undef DEFINE_INPUT_LAYOUT
- };
- return pairs;
-}
-
-const detail::AudioChannelBitPairs& getOutAudioChannelBits() {
- static const detail::AudioChannelBitPairs pairs = {
-#define DEFINE_OUTPUT_BITS(n) \
- { AUDIO_CHANNEL_OUT_##n, AudioChannelLayout::CHANNEL_##n }
-
- DEFINE_OUTPUT_BITS(FRONT_LEFT),
- DEFINE_OUTPUT_BITS(FRONT_RIGHT),
- DEFINE_OUTPUT_BITS(FRONT_CENTER),
- DEFINE_OUTPUT_BITS(LOW_FREQUENCY),
- DEFINE_OUTPUT_BITS(BACK_LEFT),
- DEFINE_OUTPUT_BITS(BACK_RIGHT),
- DEFINE_OUTPUT_BITS(FRONT_LEFT_OF_CENTER),
- DEFINE_OUTPUT_BITS(FRONT_RIGHT_OF_CENTER),
- DEFINE_OUTPUT_BITS(BACK_CENTER),
- DEFINE_OUTPUT_BITS(SIDE_LEFT),
- DEFINE_OUTPUT_BITS(SIDE_RIGHT),
- DEFINE_OUTPUT_BITS(TOP_CENTER),
- DEFINE_OUTPUT_BITS(TOP_FRONT_LEFT),
- DEFINE_OUTPUT_BITS(TOP_FRONT_CENTER),
- DEFINE_OUTPUT_BITS(TOP_FRONT_RIGHT),
- DEFINE_OUTPUT_BITS(TOP_BACK_LEFT),
- DEFINE_OUTPUT_BITS(TOP_BACK_CENTER),
- DEFINE_OUTPUT_BITS(TOP_BACK_RIGHT),
- DEFINE_OUTPUT_BITS(TOP_SIDE_LEFT),
- DEFINE_OUTPUT_BITS(TOP_SIDE_RIGHT),
- DEFINE_OUTPUT_BITS(BOTTOM_FRONT_LEFT),
- DEFINE_OUTPUT_BITS(BOTTOM_FRONT_CENTER),
- DEFINE_OUTPUT_BITS(BOTTOM_FRONT_RIGHT),
- DEFINE_OUTPUT_BITS(LOW_FREQUENCY_2),
- DEFINE_OUTPUT_BITS(FRONT_WIDE_LEFT),
- DEFINE_OUTPUT_BITS(FRONT_WIDE_RIGHT),
-#undef DEFINE_OUTPUT_BITS
- { AUDIO_CHANNEL_OUT_HAPTIC_A, AudioChannelLayout::CHANNEL_HAPTIC_A },
- { AUDIO_CHANNEL_OUT_HAPTIC_B, AudioChannelLayout::CHANNEL_HAPTIC_B }
- };
- return pairs;
-}
-
-const detail::AudioChannelPairs& getOutAudioChannelPairs() {
- static const detail::AudioChannelPairs pairs = {
-#define DEFINE_OUTPUT_LAYOUT(n) \
- { \
- AUDIO_CHANNEL_OUT_##n, \
- AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
- AudioChannelLayout::LAYOUT_##n) \
- }
-
- DEFINE_OUTPUT_LAYOUT(MONO),
- DEFINE_OUTPUT_LAYOUT(STEREO),
- DEFINE_OUTPUT_LAYOUT(2POINT1),
- DEFINE_OUTPUT_LAYOUT(TRI),
- DEFINE_OUTPUT_LAYOUT(TRI_BACK),
- DEFINE_OUTPUT_LAYOUT(3POINT1),
- DEFINE_OUTPUT_LAYOUT(2POINT0POINT2),
- DEFINE_OUTPUT_LAYOUT(2POINT1POINT2),
- DEFINE_OUTPUT_LAYOUT(3POINT0POINT2),
- DEFINE_OUTPUT_LAYOUT(3POINT1POINT2),
- DEFINE_OUTPUT_LAYOUT(QUAD),
- DEFINE_OUTPUT_LAYOUT(QUAD_SIDE),
- DEFINE_OUTPUT_LAYOUT(SURROUND),
- DEFINE_OUTPUT_LAYOUT(PENTA),
- DEFINE_OUTPUT_LAYOUT(5POINT1),
- DEFINE_OUTPUT_LAYOUT(5POINT1_SIDE),
- DEFINE_OUTPUT_LAYOUT(5POINT1POINT2),
- DEFINE_OUTPUT_LAYOUT(5POINT1POINT4),
- DEFINE_OUTPUT_LAYOUT(6POINT1),
- DEFINE_OUTPUT_LAYOUT(7POINT1),
- DEFINE_OUTPUT_LAYOUT(7POINT1POINT2),
- DEFINE_OUTPUT_LAYOUT(7POINT1POINT4),
- DEFINE_OUTPUT_LAYOUT(13POINT_360RA),
- DEFINE_OUTPUT_LAYOUT(22POINT2),
- DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_A),
- DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_A),
- DEFINE_OUTPUT_LAYOUT(HAPTIC_AB),
- DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_AB),
- DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_AB)
-#undef DEFINE_OUTPUT_LAYOUT
- };
- return pairs;
-}
-
-const detail::AudioChannelPairs& getVoiceAudioChannelPairs() {
- static const detail::AudioChannelPairs pairs = {
-#define DEFINE_VOICE_LAYOUT(n) \
- { \
- AUDIO_CHANNEL_IN_VOICE_##n, \
- AudioChannelLayout::make<AudioChannelLayout::Tag::voiceMask>( \
- AudioChannelLayout::VOICE_##n) \
- }
- DEFINE_VOICE_LAYOUT(UPLINK_MONO),
- DEFINE_VOICE_LAYOUT(DNLINK_MONO),
- DEFINE_VOICE_LAYOUT(CALL_MONO)
-#undef DEFINE_VOICE_LAYOUT
- };
- return pairs;
-}
-
-AudioDeviceDescription make_AudioDeviceDescription(AudioDeviceType type,
- const std::string& connection = "") {
- AudioDeviceDescription result;
- result.type = type;
- result.connection = connection;
- return result;
-}
-
-void append_AudioDeviceDescription(detail::AudioDevicePairs& pairs,
- audio_devices_t inputType, audio_devices_t outputType,
- AudioDeviceType inType, AudioDeviceType outType,
- const std::string& connection = "") {
- pairs.push_back(std::make_pair(inputType, make_AudioDeviceDescription(inType, connection)));
- pairs.push_back(std::make_pair(outputType, make_AudioDeviceDescription(outType, connection)));
-}
-
-const detail::AudioDevicePairs& getAudioDevicePairs() {
- static const detail::AudioDevicePairs pairs = []() {
- detail::AudioDevicePairs pairs = {{
- {
- AUDIO_DEVICE_NONE, AudioDeviceDescription{}
- },
- {
- AUDIO_DEVICE_OUT_EARPIECE, make_AudioDeviceDescription(
- AudioDeviceType::OUT_SPEAKER_EARPIECE)
- },
- {
- AUDIO_DEVICE_OUT_SPEAKER, make_AudioDeviceDescription(
- AudioDeviceType::OUT_SPEAKER)
- },
- {
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE, make_AudioDeviceDescription(
- AudioDeviceType::OUT_HEADPHONE,
- AudioDeviceDescription::CONNECTION_ANALOG())
- },
- {
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO, make_AudioDeviceDescription(
- AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_BT_SCO())
- },
- {
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, make_AudioDeviceDescription(
- AudioDeviceType::OUT_CARKIT,
- AudioDeviceDescription::CONNECTION_BT_SCO())
- },
- {
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, make_AudioDeviceDescription(
- AudioDeviceType::OUT_HEADPHONE,
- AudioDeviceDescription::CONNECTION_BT_A2DP())
- },
- {
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, make_AudioDeviceDescription(
- AudioDeviceType::OUT_SPEAKER,
- AudioDeviceDescription::CONNECTION_BT_A2DP())
- },
- {
- AUDIO_DEVICE_OUT_TELEPHONY_TX, make_AudioDeviceDescription(
- AudioDeviceType::OUT_TELEPHONY_TX)
- },
- {
- AUDIO_DEVICE_OUT_AUX_LINE, make_AudioDeviceDescription(
- AudioDeviceType::OUT_LINE_AUX)
- },
- {
- AUDIO_DEVICE_OUT_SPEAKER_SAFE, make_AudioDeviceDescription(
- AudioDeviceType::OUT_SPEAKER_SAFE)
- },
- {
- AUDIO_DEVICE_OUT_HEARING_AID, make_AudioDeviceDescription(
- AudioDeviceType::OUT_HEARING_AID,
- AudioDeviceDescription::CONNECTION_WIRELESS())
- },
- {
- AUDIO_DEVICE_OUT_ECHO_CANCELLER, make_AudioDeviceDescription(
- AudioDeviceType::OUT_ECHO_CANCELLER)
- },
- {
- AUDIO_DEVICE_OUT_BLE_SPEAKER, make_AudioDeviceDescription(
- AudioDeviceType::OUT_SPEAKER,
- AudioDeviceDescription::CONNECTION_BT_LE())
- },
- {
- AUDIO_DEVICE_OUT_BLE_BROADCAST, make_AudioDeviceDescription(
- AudioDeviceType::OUT_BROADCAST,
- AudioDeviceDescription::CONNECTION_BT_LE())
- },
- // AUDIO_DEVICE_IN_AMBIENT and IN_COMMUNICATION are removed since they were deprecated.
- {
- AUDIO_DEVICE_IN_BUILTIN_MIC, make_AudioDeviceDescription(
- AudioDeviceType::IN_MICROPHONE)
- },
- {
- AUDIO_DEVICE_IN_BACK_MIC, make_AudioDeviceDescription(
- AudioDeviceType::IN_MICROPHONE_BACK)
- },
- {
- AUDIO_DEVICE_IN_TELEPHONY_RX, make_AudioDeviceDescription(
- AudioDeviceType::IN_TELEPHONY_RX)
- },
- {
- AUDIO_DEVICE_IN_TV_TUNER, make_AudioDeviceDescription(
- AudioDeviceType::IN_TV_TUNER)
- },
- {
- AUDIO_DEVICE_IN_LOOPBACK, make_AudioDeviceDescription(
- AudioDeviceType::IN_LOOPBACK)
- },
- {
- AUDIO_DEVICE_IN_BLUETOOTH_BLE, make_AudioDeviceDescription(
- AudioDeviceType::IN_DEVICE,
- AudioDeviceDescription::CONNECTION_BT_LE())
- },
- {
- AUDIO_DEVICE_IN_ECHO_REFERENCE, make_AudioDeviceDescription(
- AudioDeviceType::IN_ECHO_REFERENCE)
- }
- }};
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT,
- AudioDeviceType::IN_DEFAULT, AudioDeviceType::OUT_DEFAULT);
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET,
- AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
- AudioDeviceDescription::CONNECTION_ANALOG());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
- AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
- AudioDeviceDescription::CONNECTION_BT_SCO());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_HDMI, AUDIO_DEVICE_OUT_HDMI,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_HDMI());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AudioDeviceType::IN_SUBMIX, AudioDeviceType::OUT_SUBMIX);
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET,
- AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
- AudioDeviceDescription::CONNECTION_ANALOG());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
- AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
- AudioDeviceDescription::CONNECTION_USB());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_ACCESSORY,
- AudioDeviceType::IN_ACCESSORY, AudioDeviceType::OUT_ACCESSORY,
- AudioDeviceDescription::CONNECTION_USB());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_OUT_USB_DEVICE,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_USB());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_FM_TUNER, AUDIO_DEVICE_OUT_FM,
- AudioDeviceType::IN_FM_TUNER, AudioDeviceType::OUT_FM);
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_LINE, AUDIO_DEVICE_OUT_LINE,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_ANALOG());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_SPDIF, AUDIO_DEVICE_OUT_SPDIF,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_SPDIF());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_BT_A2DP());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_IP, AUDIO_DEVICE_OUT_IP,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_IP_V4());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_BUS, AUDIO_DEVICE_OUT_BUS,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_BUS());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_PROXY, AUDIO_DEVICE_OUT_PROXY,
- AudioDeviceType::IN_AFE_PROXY, AudioDeviceType::OUT_AFE_PROXY);
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
- AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
- AudioDeviceDescription::CONNECTION_USB());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_HDMI_ARC, AUDIO_DEVICE_OUT_HDMI_ARC,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_HDMI_ARC());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_HDMI_EARC, AUDIO_DEVICE_OUT_HDMI_EARC,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_HDMI_EARC());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_OUT_BLE_HEADSET,
- AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
- AudioDeviceDescription::CONNECTION_BT_LE());
- return pairs;
- }();
- return pairs;
-}
-
-AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
- AudioFormatDescription result;
- result.type = type;
- return result;
-}
-
-AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
- auto result = make_AudioFormatDescription(AudioFormatType::PCM);
- result.pcm = pcm;
- return result;
-}
-
-AudioFormatDescription make_AudioFormatDescription(const std::string& encoding) {
- AudioFormatDescription result;
- result.encoding = encoding;
- return result;
-}
-
-AudioFormatDescription make_AudioFormatDescription(PcmType transport,
- const std::string& encoding) {
- auto result = make_AudioFormatDescription(encoding);
- result.pcm = transport;
- return result;
-}
-
-const detail::AudioFormatPairs& getAudioFormatPairs() {
- static const detail::AudioFormatPairs pairs = {{
- {
- AUDIO_FORMAT_INVALID,
- make_AudioFormatDescription(AudioFormatType::SYS_RESERVED_INVALID)
- },
- {
- AUDIO_FORMAT_DEFAULT, AudioFormatDescription{}
- },
- {
- AUDIO_FORMAT_PCM_16_BIT, make_AudioFormatDescription(PcmType::INT_16_BIT)
- },
- {
- AUDIO_FORMAT_PCM_8_BIT, make_AudioFormatDescription(PcmType::UINT_8_BIT)
- },
- {
- AUDIO_FORMAT_PCM_32_BIT, make_AudioFormatDescription(PcmType::INT_32_BIT)
- },
- {
- AUDIO_FORMAT_PCM_8_24_BIT, make_AudioFormatDescription(PcmType::FIXED_Q_8_24)
- },
- {
- AUDIO_FORMAT_PCM_FLOAT, make_AudioFormatDescription(PcmType::FLOAT_32_BIT)
- },
- {
- AUDIO_FORMAT_PCM_24_BIT_PACKED, make_AudioFormatDescription(PcmType::INT_24_BIT)
- },
- {
- AUDIO_FORMAT_MP3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEG)
- },
- {
- AUDIO_FORMAT_AMR_NB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_NB)
- },
- {
- AUDIO_FORMAT_AMR_WB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_WB)
- },
- {
- AUDIO_FORMAT_AAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_MP4)
- },
- {
- AUDIO_FORMAT_AAC_MAIN, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_MAIN)
- },
- {
- AUDIO_FORMAT_AAC_LC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LC)
- },
- {
- AUDIO_FORMAT_AAC_SSR, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_SSR)
- },
- {
- AUDIO_FORMAT_AAC_LTP, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LTP)
- },
- {
- AUDIO_FORMAT_AAC_HE_V1, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_HE_V1)
- },
- {
- AUDIO_FORMAT_AAC_SCALABLE,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_SCALABLE)
- },
- {
- AUDIO_FORMAT_AAC_ERLC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ERLC)
- },
- {
- AUDIO_FORMAT_AAC_LD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LD)
- },
- {
- AUDIO_FORMAT_AAC_HE_V2, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_HE_V2)
- },
- {
- AUDIO_FORMAT_AAC_ELD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ELD)
- },
- {
- AUDIO_FORMAT_AAC_XHE, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_XHE)
- },
- // AUDIO_FORMAT_HE_AAC_V1 and HE_AAC_V2 are removed since they were deprecated long time
- // ago.
- {
- AUDIO_FORMAT_VORBIS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_VORBIS)
- },
- {
- AUDIO_FORMAT_OPUS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_OPUS)
- },
- {
- AUDIO_FORMAT_AC3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AC3)
- },
- {
- AUDIO_FORMAT_E_AC3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EAC3)
- },
- {
- AUDIO_FORMAT_E_AC3_JOC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EAC3_JOC)
- },
- {
- AUDIO_FORMAT_DTS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS)
- },
- {
- AUDIO_FORMAT_DTS_HD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_HD)
- },
- // In the future, we would like to represent encapsulated bitstreams as
- // nested AudioFormatDescriptions. The legacy 'AUDIO_FORMAT_IEC61937' type doesn't
- // specify the format of the encapsulated bitstream.
- {
- AUDIO_FORMAT_IEC61937,
- make_AudioFormatDescription(PcmType::INT_16_BIT, MEDIA_MIMETYPE_AUDIO_IEC61937)
- },
- {
- AUDIO_FORMAT_DOLBY_TRUEHD,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD)
- },
- {
- AUDIO_FORMAT_EVRC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRC)
- },
- {
- AUDIO_FORMAT_EVRCB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCB)
- },
- {
- AUDIO_FORMAT_EVRCWB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCWB)
- },
- {
- AUDIO_FORMAT_EVRCNW, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCNW)
- },
- {
- AUDIO_FORMAT_AAC_ADIF, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADIF)
- },
- {
- AUDIO_FORMAT_WMA, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_WMA)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_WMA_PRO, make_AudioFormatDescription("audio/x-ms-wma.pro")
- },
- {
- AUDIO_FORMAT_AMR_WB_PLUS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)
- },
- {
- AUDIO_FORMAT_MP2, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II)
- },
- {
- AUDIO_FORMAT_QCELP, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_QCELP)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_DSD, make_AudioFormatDescription("audio/vnd.sony.dsd")
- },
- {
- AUDIO_FORMAT_FLAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_FLAC)
- },
- {
- AUDIO_FORMAT_ALAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_ALAC)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_APE, make_AudioFormatDescription("audio/x-ape")
- },
- {
- AUDIO_FORMAT_AAC_ADTS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_MAIN,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_MAIN)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_LC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LC)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_SSR,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SSR)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_LTP,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LTP)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_HE_V1,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V1)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_SCALABLE,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SCALABLE)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_ERLC,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ERLC)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_LD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LD)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_HE_V2,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V2)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_ELD,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ELD)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_XHE,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_XHE)
- },
- {
- // Note: not in the IANA registry. "vnd.octel.sbc" is not BT SBC.
- AUDIO_FORMAT_SBC, make_AudioFormatDescription("audio/x-sbc")
- },
- {
- AUDIO_FORMAT_APTX, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_APTX)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_APTX_HD, make_AudioFormatDescription("audio/vnd.qcom.aptx.hd")
- },
- {
- AUDIO_FORMAT_AC4, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AC4)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_LDAC, make_AudioFormatDescription("audio/vnd.sony.ldac")
- },
- {
- AUDIO_FORMAT_MAT, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_MAT_1_0,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT + std::string(".1.0"))
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_MAT_2_0,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT + std::string(".2.0"))
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_MAT_2_1,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT + std::string(".2.1"))
- },
- {
- AUDIO_FORMAT_AAC_LATM, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC)
- },
- {
- AUDIO_FORMAT_AAC_LATM_LC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LATM_LC)
- },
- {
- AUDIO_FORMAT_AAC_LATM_HE_V1,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V1)
- },
- {
- AUDIO_FORMAT_AAC_LATM_HE_V2,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V2)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_CELT, make_AudioFormatDescription("audio/x-celt")
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_APTX_ADAPTIVE, make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive")
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_LHDC, make_AudioFormatDescription("audio/vnd.savitech.lhdc")
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_LHDC_LL, make_AudioFormatDescription("audio/vnd.savitech.lhdc.ll")
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_APTX_TWSP, make_AudioFormatDescription("audio/vnd.qcom.aptx.twsp")
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_LC3, make_AudioFormatDescription("audio/x-lc3")
- },
- {
- AUDIO_FORMAT_MPEGH, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1)
- },
- {
- AUDIO_FORMAT_MPEGH_BL_L3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L3)
- },
- {
- AUDIO_FORMAT_MPEGH_BL_L4, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L4)
- },
- {
- AUDIO_FORMAT_MPEGH_LC_L3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L3)
- },
- {
- AUDIO_FORMAT_MPEGH_LC_L4, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L4)
- },
- {
- AUDIO_FORMAT_IEC60958,
- make_AudioFormatDescription(PcmType::INT_24_BIT, MEDIA_MIMETYPE_AUDIO_IEC60958)
- },
- {
- AUDIO_FORMAT_DTS_UHD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_UHD)
- },
- {
- AUDIO_FORMAT_DRA, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DRA)
- },
- }};
- return pairs;
-}
-
-template<typename S, typename T>
-std::unordered_map<S, T> make_DirectMap(const std::vector<std::pair<S, T>>& v) {
- std::unordered_map<S, T> result(v.begin(), v.end());
- LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
- return result;
-}
-
-template<typename S, typename T>
-std::unordered_map<S, T> make_DirectMap(
- const std::vector<std::pair<S, T>>& v1, const std::vector<std::pair<S, T>>& v2) {
- std::unordered_map<S, T> result(v1.begin(), v1.end());
- LOG_ALWAYS_FATAL_IF(result.size() != v1.size(), "Duplicate key elements detected in v1");
- result.insert(v2.begin(), v2.end());
- LOG_ALWAYS_FATAL_IF(result.size() != v1.size() + v2.size(),
- "Duplicate key elements detected in v1+v2");
- return result;
-}
-
-template<typename S, typename T>
-std::unordered_map<T, S> make_ReverseMap(const std::vector<std::pair<S, T>>& v) {
- std::unordered_map<T, S> result;
- std::transform(v.begin(), v.end(), std::inserter(result, result.begin()),
- [](const std::pair<S, T>& p) {
- return std::make_pair(p.second, p.first);
- });
- LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
- return result;
-}
-
-} // namespace
-
-audio_channel_mask_t aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
- int aidlLayout, bool isInput) {
- auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
- const int aidlLayoutInitial = aidlLayout; // for error message
- audio_channel_mask_t legacy = AUDIO_CHANNEL_NONE;
- for (const auto& bitPair : bitMapping) {
- if ((aidlLayout & bitPair.second) == bitPair.second) {
- legacy = static_cast<audio_channel_mask_t>(legacy | bitPair.first);
- aidlLayout &= ~bitPair.second;
- if (aidlLayout == 0) {
- return legacy;
- }
- }
- }
- ALOGE("%s: aidl layout 0x%x contains bits 0x%x that have no match to legacy %s bits",
- __func__, aidlLayoutInitial, aidlLayout, isInput ? "input" : "output");
- return AUDIO_CHANNEL_NONE;
-}
-
-ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
- const AudioChannelLayout& aidl, bool isInput) {
- using ReverseMap = std::unordered_map<AudioChannelLayout, audio_channel_mask_t>;
- using Tag = AudioChannelLayout::Tag;
- static const ReverseMap mIn = make_ReverseMap(getInAudioChannelPairs());
- static const ReverseMap mOut = make_ReverseMap(getOutAudioChannelPairs());
- static const ReverseMap mVoice = make_ReverseMap(getVoiceAudioChannelPairs());
-
- auto convert = [](const AudioChannelLayout& aidl, const ReverseMap& m,
- const char* func, const char* type) -> ConversionResult<audio_channel_mask_t> {
- if (auto it = m.find(aidl); it != m.end()) {
- return it->second;
- } else {
- ALOGW("%s: no legacy %s audio_channel_mask_t found for %s", func, type,
- aidl.toString().c_str());
- return unexpected(BAD_VALUE);
- }
- };
-
- switch (aidl.getTag()) {
- case Tag::none:
- return AUDIO_CHANNEL_NONE;
- case Tag::invalid:
- return AUDIO_CHANNEL_INVALID;
- case Tag::indexMask:
- // Index masks do not have pre-defined values.
- if (const int bits = aidl.get<Tag::indexMask>();
- __builtin_popcount(bits) != 0 &&
- __builtin_popcount(bits) <= AUDIO_CHANNEL_COUNT_MAX) {
- return audio_channel_mask_from_representation_and_bits(
- AUDIO_CHANNEL_REPRESENTATION_INDEX, bits);
- } else {
- ALOGE("%s: invalid indexMask value 0x%x in %s",
- __func__, bits, aidl.toString().c_str());
- return unexpected(BAD_VALUE);
- }
- case Tag::layoutMask:
- // The fast path is to find a direct match for some known layout mask.
- if (const auto layoutMatch = convert(aidl, isInput ? mIn : mOut, __func__,
- isInput ? "input" : "output");
- layoutMatch.ok()) {
- return layoutMatch;
- }
- // If a match for a predefined layout wasn't found, make a custom one from bits.
- if (audio_channel_mask_t bitMask =
- aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
- aidl.get<Tag::layoutMask>(), isInput);
- bitMask != AUDIO_CHANNEL_NONE) {
- return bitMask;
- }
- return unexpected(BAD_VALUE);
- case Tag::voiceMask:
- return convert(aidl, mVoice, __func__, "voice");
- }
- ALOGE("%s: unexpected tag value %d", __func__, aidl.getTag());
- return unexpected(BAD_VALUE);
-}
-
-int legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
- audio_channel_mask_t legacy, bool isInput) {
- auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
- const int legacyInitial = legacy; // for error message
- int aidlLayout = 0;
- for (const auto& bitPair : bitMapping) {
- if ((legacy & bitPair.first) == bitPair.first) {
- aidlLayout |= bitPair.second;
- legacy = static_cast<audio_channel_mask_t>(legacy & ~bitPair.first);
- if (legacy == 0) {
- return aidlLayout;
- }
- }
- }
- ALOGE("%s: legacy %s audio_channel_mask_t 0x%x contains unrecognized bits 0x%x",
- __func__, isInput ? "input" : "output", legacyInitial, legacy);
- return 0;
-}
-
-ConversionResult<AudioChannelLayout> legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
- audio_channel_mask_t legacy, bool isInput) {
- using DirectMap = std::unordered_map<audio_channel_mask_t, AudioChannelLayout>;
- using Tag = AudioChannelLayout::Tag;
- static const DirectMap mInAndVoice = make_DirectMap(
- getInAudioChannelPairs(), getVoiceAudioChannelPairs());
- static const DirectMap mOut = make_DirectMap(getOutAudioChannelPairs());
-
- auto convert = [](const audio_channel_mask_t legacy, const DirectMap& m,
- const char* func, const char* type) -> ConversionResult<AudioChannelLayout> {
- if (auto it = m.find(legacy); it != m.end()) {
- return it->second;
- } else {
- ALOGW("%s: no AudioChannelLayout found for legacy %s audio_channel_mask_t value 0x%x",
- func, type, legacy);
- return unexpected(BAD_VALUE);
- }
- };
-
- if (legacy == AUDIO_CHANNEL_NONE) {
- return AudioChannelLayout{};
- } else if (legacy == AUDIO_CHANNEL_INVALID) {
- return AudioChannelLayout::make<Tag::invalid>(0);
- }
-
- const audio_channel_representation_t repr = audio_channel_mask_get_representation(legacy);
- if (repr == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
- if (audio_channel_mask_is_valid(legacy)) {
- const int indexMask = VALUE_OR_RETURN(
- convertIntegral<int>(audio_channel_mask_get_bits(legacy)));
- return AudioChannelLayout::make<Tag::indexMask>(indexMask);
- } else {
- ALOGE("%s: legacy audio_channel_mask_t value 0x%x is invalid", __func__, legacy);
- return unexpected(BAD_VALUE);
- }
- } else if (repr == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
- // The fast path is to find a direct match for some known layout mask.
- if (const auto layoutMatch = convert(legacy, isInput ? mInAndVoice : mOut, __func__,
- isInput ? "input / voice" : "output");
- layoutMatch.ok()) {
- return layoutMatch;
- }
- // If a match for a predefined layout wasn't found, make a custom one from bits,
- // rejecting those with voice channel bits.
- if (!isInput ||
- (legacy & (AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK)) == 0) {
- if (int bitMaskLayout =
- legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
- legacy, isInput);
- bitMaskLayout != 0) {
- return AudioChannelLayout::make<Tag::layoutMask>(bitMaskLayout);
- }
- } else {
- ALOGE("%s: legacy audio_channel_mask_t value 0x%x contains voice bits",
- __func__, legacy);
- }
- return unexpected(BAD_VALUE);
- }
-
- ALOGE("%s: unknown representation %d in audio_channel_mask_t value 0x%x",
- __func__, repr, legacy);
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
- const AudioDeviceDescription& aidl) {
- static const std::unordered_map<AudioDeviceDescription, audio_devices_t> m =
- make_ReverseMap(getAudioDevicePairs());
- if (auto it = m.find(aidl); it != m.end()) {
- return it->second;
- } else {
- ALOGE("%s: no legacy audio_devices_t found for %s", __func__, aidl.toString().c_str());
- return unexpected(BAD_VALUE);
- }
-}
-
-ConversionResult<AudioDeviceDescription> legacy2aidl_audio_devices_t_AudioDeviceDescription(
- audio_devices_t legacy) {
- static const std::unordered_map<audio_devices_t, AudioDeviceDescription> m =
- make_DirectMap(getAudioDevicePairs());
- if (auto it = m.find(legacy); it != m.end()) {
- return it->second;
- } else {
- ALOGE("%s: no AudioDeviceDescription found for legacy audio_devices_t value 0x%x",
- __func__, legacy);
- return unexpected(BAD_VALUE);
- }
-}
-
-status_t aidl2legacy_AudioDevice_audio_device(
- const AudioDevice& aidl,
- audio_devices_t* legacyType, char* legacyAddress) {
- *legacyType = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
- return aidl2legacy_string(
- aidl.address.get<AudioDeviceAddress::id>(),
- legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN);
-}
-
-status_t aidl2legacy_AudioDevice_audio_device(
- const AudioDevice& aidl,
- audio_devices_t* legacyType, String8* legacyAddress) {
- *legacyType = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
- *legacyAddress = VALUE_OR_RETURN_STATUS(aidl2legacy_string_view_String8(
- aidl.address.get<AudioDeviceAddress::id>()));
- return OK;
-}
-
-status_t aidl2legacy_AudioDevice_audio_device(
- const AudioDevice& aidl,
- audio_devices_t* legacyType, std::string* legacyAddress) {
- *legacyType = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
- *legacyAddress = aidl.address.get<AudioDeviceAddress::id>();
- return OK;
-}
-
-ConversionResult<AudioDevice> legacy2aidl_audio_device_AudioDevice(
- audio_devices_t legacyType, const char* legacyAddress) {
- AudioDevice aidl;
- aidl.type = VALUE_OR_RETURN(
- legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
- const std::string aidl_id = VALUE_OR_RETURN(
- legacy2aidl_string(legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN));
- aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
- return aidl;
-}
-
-ConversionResult<AudioDevice>
-legacy2aidl_audio_device_AudioDevice(
- audio_devices_t legacyType, const String8& legacyAddress) {
- AudioDevice aidl;
- aidl.type = VALUE_OR_RETURN(
- legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
- const std::string aidl_id = VALUE_OR_RETURN(
- legacy2aidl_String8_string(legacyAddress));
- aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
- return aidl;
-}
-
-ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
- const AudioFormatDescription& aidl) {
- static const std::unordered_map<AudioFormatDescription, audio_format_t> m =
- make_ReverseMap(getAudioFormatPairs());
- if (auto it = m.find(aidl); it != m.end()) {
- return it->second;
- } else {
- ALOGE("%s: no legacy audio_format_t found for %s", __func__, aidl.toString().c_str());
- return unexpected(BAD_VALUE);
- }
-}
-
-ConversionResult<AudioFormatDescription> legacy2aidl_audio_format_t_AudioFormatDescription(
- audio_format_t legacy) {
- static const std::unordered_map<audio_format_t, AudioFormatDescription> m =
- make_DirectMap(getAudioFormatPairs());
- if (auto it = m.find(legacy); it != m.end()) {
- return it->second;
- } else {
- ALOGE("%s: no AudioFormatDescription found for legacy audio_format_t value 0x%x",
- __func__, legacy);
- return unexpected(BAD_VALUE);
- }
-}
-
-ConversionResult<audio_gain_mode_t> aidl2legacy_AudioGainMode_audio_gain_mode_t(
- AudioGainMode aidl) {
+ConversionResult<audio_io_config_event_t> aidl2legacy_AudioIoConfigEvent_audio_io_config_event_t(
+ media::AudioIoConfigEvent aidl) {
switch (aidl) {
- case AudioGainMode::JOINT:
- return AUDIO_GAIN_MODE_JOINT;
- case AudioGainMode::CHANNELS:
- return AUDIO_GAIN_MODE_CHANNELS;
- case AudioGainMode::RAMP:
- return AUDIO_GAIN_MODE_RAMP;
+ case media::AudioIoConfigEvent::OUTPUT_REGISTERED:
+ return AUDIO_OUTPUT_REGISTERED;
+ case media::AudioIoConfigEvent::OUTPUT_OPENED:
+ return AUDIO_OUTPUT_OPENED;
+ case media::AudioIoConfigEvent::OUTPUT_CLOSED:
+ return AUDIO_OUTPUT_CLOSED;
+ case media::AudioIoConfigEvent::OUTPUT_CONFIG_CHANGED:
+ return AUDIO_OUTPUT_CONFIG_CHANGED;
+ case media::AudioIoConfigEvent::INPUT_REGISTERED:
+ return AUDIO_INPUT_REGISTERED;
+ case media::AudioIoConfigEvent::INPUT_OPENED:
+ return AUDIO_INPUT_OPENED;
+ case media::AudioIoConfigEvent::INPUT_CLOSED:
+ return AUDIO_INPUT_CLOSED;
+ case media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED:
+ return AUDIO_INPUT_CONFIG_CHANGED;
+ case media::AudioIoConfigEvent::CLIENT_STARTED:
+ return AUDIO_CLIENT_STARTED;
}
return unexpected(BAD_VALUE);
}
-ConversionResult<AudioGainMode> legacy2aidl_audio_gain_mode_t_AudioGainMode(
- audio_gain_mode_t legacy) {
+ConversionResult<media::AudioIoConfigEvent> legacy2aidl_audio_io_config_event_t_AudioIoConfigEvent(
+ audio_io_config_event_t legacy) {
switch (legacy) {
- case AUDIO_GAIN_MODE_JOINT:
- return AudioGainMode::JOINT;
- case AUDIO_GAIN_MODE_CHANNELS:
- return AudioGainMode::CHANNELS;
- case AUDIO_GAIN_MODE_RAMP:
- return AudioGainMode::RAMP;
+ case AUDIO_OUTPUT_REGISTERED:
+ return media::AudioIoConfigEvent::OUTPUT_REGISTERED;
+ case AUDIO_OUTPUT_OPENED:
+ return media::AudioIoConfigEvent::OUTPUT_OPENED;
+ case AUDIO_OUTPUT_CLOSED:
+ return media::AudioIoConfigEvent::OUTPUT_CLOSED;
+ case AUDIO_OUTPUT_CONFIG_CHANGED:
+ return media::AudioIoConfigEvent::OUTPUT_CONFIG_CHANGED;
+ case AUDIO_INPUT_REGISTERED:
+ return media::AudioIoConfigEvent::INPUT_REGISTERED;
+ case AUDIO_INPUT_OPENED:
+ return media::AudioIoConfigEvent::INPUT_OPENED;
+ case AUDIO_INPUT_CLOSED:
+ return media::AudioIoConfigEvent::INPUT_CLOSED;
+ case AUDIO_INPUT_CONFIG_CHANGED:
+ return media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED;
+ case AUDIO_CLIENT_STARTED:
+ return media::AudioIoConfigEvent::CLIENT_STARTED;
}
return unexpected(BAD_VALUE);
}
-
-ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl) {
- return convertBitmask<audio_gain_mode_t, int32_t, audio_gain_mode_t, AudioGainMode>(
- aidl, aidl2legacy_AudioGainMode_audio_gain_mode_t,
- // AudioGainMode is index-based.
- indexToEnum_index<AudioGainMode>,
- // AUDIO_GAIN_MODE_* constants are mask-based.
- enumToMask_bitmask<audio_gain_mode_t, audio_gain_mode_t>);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy) {
- return convertBitmask<int32_t, audio_gain_mode_t, AudioGainMode, audio_gain_mode_t>(
- legacy, legacy2aidl_audio_gain_mode_t_AudioGainMode,
- // AUDIO_GAIN_MODE_* constants are mask-based.
- indexToEnum_bitmask<audio_gain_mode_t>,
- // AudioGainMode is index-based.
- enumToMask_index<int32_t, AudioGainMode>);
-}
-
-ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
- const AudioGainConfig& aidl, bool isInput) {
- audio_gain_config legacy;
- legacy.index = VALUE_OR_RETURN(convertIntegral<int>(aidl.index));
- legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
- legacy.channel_mask = VALUE_OR_RETURN(
- aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
- const bool isJoint = bitmaskIsSet(aidl.mode, AudioGainMode::JOINT);
- size_t numValues = isJoint ? 1
- : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
- : audio_channel_count_from_out_mask(legacy.channel_mask);
- if (aidl.values.size() != numValues || aidl.values.size() > std::size(legacy.values)) {
- return unexpected(BAD_VALUE);
- }
- for (size_t i = 0; i < numValues; ++i) {
- legacy.values[i] = VALUE_OR_RETURN(convertIntegral<int>(aidl.values[i]));
- }
- legacy.ramp_duration_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.rampDurationMs));
- return legacy;
-}
-
-ConversionResult<AudioGainConfig> legacy2aidl_audio_gain_config_AudioGainConfig(
- const audio_gain_config& legacy, bool isInput) {
- AudioGainConfig aidl;
- aidl.index = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.index));
- aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
- aidl.channelMask = VALUE_OR_RETURN(
- legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
- const bool isJoint = (legacy.mode & AUDIO_GAIN_MODE_JOINT) != 0;
- size_t numValues = isJoint ? 1
- : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
- : audio_channel_count_from_out_mask(legacy.channel_mask);
- aidl.values.resize(numValues);
- for (size_t i = 0; i < numValues; ++i) {
- aidl.values[i] = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.values[i]));
- }
- aidl.rampDurationMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.ramp_duration_ms));
- return aidl;
-}
-
-ConversionResult<audio_input_flags_t> aidl2legacy_AudioInputFlags_audio_input_flags_t(
- AudioInputFlags aidl) {
- switch (aidl) {
- case AudioInputFlags::FAST:
- return AUDIO_INPUT_FLAG_FAST;
- case AudioInputFlags::HW_HOTWORD:
- return AUDIO_INPUT_FLAG_HW_HOTWORD;
- case AudioInputFlags::RAW:
- return AUDIO_INPUT_FLAG_RAW;
- case AudioInputFlags::SYNC:
- return AUDIO_INPUT_FLAG_SYNC;
- case AudioInputFlags::MMAP_NOIRQ:
- return AUDIO_INPUT_FLAG_MMAP_NOIRQ;
- case AudioInputFlags::VOIP_TX:
- return AUDIO_INPUT_FLAG_VOIP_TX;
- case AudioInputFlags::HW_AV_SYNC:
- return AUDIO_INPUT_FLAG_HW_AV_SYNC;
- case AudioInputFlags::DIRECT:
- return AUDIO_INPUT_FLAG_DIRECT;
- case AudioInputFlags::ULTRASOUND:
- return AUDIO_INPUT_FLAG_ULTRASOUND;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
- audio_input_flags_t legacy) {
- switch (legacy) {
- case AUDIO_INPUT_FLAG_NONE:
- break; // shouldn't get here. must be listed -Werror,-Wswitch
- case AUDIO_INPUT_FLAG_FAST:
- return AudioInputFlags::FAST;
- case AUDIO_INPUT_FLAG_HW_HOTWORD:
- return AudioInputFlags::HW_HOTWORD;
- case AUDIO_INPUT_FLAG_RAW:
- return AudioInputFlags::RAW;
- case AUDIO_INPUT_FLAG_SYNC:
- return AudioInputFlags::SYNC;
- case AUDIO_INPUT_FLAG_MMAP_NOIRQ:
- return AudioInputFlags::MMAP_NOIRQ;
- case AUDIO_INPUT_FLAG_VOIP_TX:
- return AudioInputFlags::VOIP_TX;
- case AUDIO_INPUT_FLAG_HW_AV_SYNC:
- return AudioInputFlags::HW_AV_SYNC;
- case AUDIO_INPUT_FLAG_DIRECT:
- return AudioInputFlags::DIRECT;
- case AUDIO_INPUT_FLAG_ULTRASOUND:
- return AudioInputFlags::ULTRASOUND;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
- AudioOutputFlags aidl) {
- switch (aidl) {
- case AudioOutputFlags::DIRECT:
- return AUDIO_OUTPUT_FLAG_DIRECT;
- case AudioOutputFlags::PRIMARY:
- return AUDIO_OUTPUT_FLAG_PRIMARY;
- case AudioOutputFlags::FAST:
- return AUDIO_OUTPUT_FLAG_FAST;
- case AudioOutputFlags::DEEP_BUFFER:
- return AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
- case AudioOutputFlags::COMPRESS_OFFLOAD:
- return AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
- case AudioOutputFlags::NON_BLOCKING:
- return AUDIO_OUTPUT_FLAG_NON_BLOCKING;
- case AudioOutputFlags::HW_AV_SYNC:
- return AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
- case AudioOutputFlags::TTS:
- return AUDIO_OUTPUT_FLAG_TTS;
- case AudioOutputFlags::RAW:
- return AUDIO_OUTPUT_FLAG_RAW;
- case AudioOutputFlags::SYNC:
- return AUDIO_OUTPUT_FLAG_SYNC;
- case AudioOutputFlags::IEC958_NONAUDIO:
- return AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
- case AudioOutputFlags::DIRECT_PCM:
- return AUDIO_OUTPUT_FLAG_DIRECT_PCM;
- case AudioOutputFlags::MMAP_NOIRQ:
- return AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
- case AudioOutputFlags::VOIP_RX:
- return AUDIO_OUTPUT_FLAG_VOIP_RX;
- case AudioOutputFlags::INCALL_MUSIC:
- return AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
- case AudioOutputFlags::GAPLESS_OFFLOAD:
- return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
- case AudioOutputFlags::ULTRASOUND:
- return AUDIO_OUTPUT_FLAG_ULTRASOUND;
- case AudioOutputFlags::SPATIALIZER:
- return AUDIO_OUTPUT_FLAG_SPATIALIZER;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
- audio_output_flags_t legacy) {
- switch (legacy) {
- case AUDIO_OUTPUT_FLAG_NONE:
- break; // shouldn't get here. must be listed -Werror,-Wswitch
- case AUDIO_OUTPUT_FLAG_DIRECT:
- return AudioOutputFlags::DIRECT;
- case AUDIO_OUTPUT_FLAG_PRIMARY:
- return AudioOutputFlags::PRIMARY;
- case AUDIO_OUTPUT_FLAG_FAST:
- return AudioOutputFlags::FAST;
- case AUDIO_OUTPUT_FLAG_DEEP_BUFFER:
- return AudioOutputFlags::DEEP_BUFFER;
- case AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD:
- return AudioOutputFlags::COMPRESS_OFFLOAD;
- case AUDIO_OUTPUT_FLAG_NON_BLOCKING:
- return AudioOutputFlags::NON_BLOCKING;
- case AUDIO_OUTPUT_FLAG_HW_AV_SYNC:
- return AudioOutputFlags::HW_AV_SYNC;
- case AUDIO_OUTPUT_FLAG_TTS:
- return AudioOutputFlags::TTS;
- case AUDIO_OUTPUT_FLAG_RAW:
- return AudioOutputFlags::RAW;
- case AUDIO_OUTPUT_FLAG_SYNC:
- return AudioOutputFlags::SYNC;
- case AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO:
- return AudioOutputFlags::IEC958_NONAUDIO;
- case AUDIO_OUTPUT_FLAG_DIRECT_PCM:
- return AudioOutputFlags::DIRECT_PCM;
- case AUDIO_OUTPUT_FLAG_MMAP_NOIRQ:
- return AudioOutputFlags::MMAP_NOIRQ;
- case AUDIO_OUTPUT_FLAG_VOIP_RX:
- return AudioOutputFlags::VOIP_RX;
- case AUDIO_OUTPUT_FLAG_INCALL_MUSIC:
- return AudioOutputFlags::INCALL_MUSIC;
- case AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD:
- return AudioOutputFlags::GAPLESS_OFFLOAD;
- case AUDIO_OUTPUT_FLAG_ULTRASOUND:
- return AudioOutputFlags::ULTRASOUND;
- case AUDIO_OUTPUT_FLAG_SPATIALIZER:
- return AudioOutputFlags::SPATIALIZER;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
- int32_t aidl) {
- using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
-
- LegacyMask converted = VALUE_OR_RETURN(
- (convertBitmask<LegacyMask, int32_t, audio_input_flags_t, AudioInputFlags>(
- aidl, aidl2legacy_AudioInputFlags_audio_input_flags_t,
- indexToEnum_index<AudioInputFlags>,
- enumToMask_bitmask<LegacyMask, audio_input_flags_t>)));
- return static_cast<audio_input_flags_t>(converted);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
- audio_input_flags_t legacy) {
- using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
-
- LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
- return convertBitmask<int32_t, LegacyMask, AudioInputFlags, audio_input_flags_t>(
- legacyMask, legacy2aidl_audio_input_flags_t_AudioInputFlags,
- indexToEnum_bitmask<audio_input_flags_t>,
- enumToMask_index<int32_t, AudioInputFlags>);
-}
-
-ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
- int32_t aidl) {
- return convertBitmask<audio_output_flags_t,
- int32_t,
- audio_output_flags_t,
- AudioOutputFlags>(
- aidl, aidl2legacy_AudioOutputFlags_audio_output_flags_t,
- indexToEnum_index<AudioOutputFlags>,
- enumToMask_bitmask<audio_output_flags_t, audio_output_flags_t>);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
- audio_output_flags_t legacy) {
- using LegacyMask = std::underlying_type_t<audio_output_flags_t>;
-
- LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
- return convertBitmask<int32_t, LegacyMask, AudioOutputFlags, audio_output_flags_t>(
- legacyMask, legacy2aidl_audio_output_flags_t_AudioOutputFlags,
- indexToEnum_bitmask<audio_output_flags_t>,
- enumToMask_index<int32_t, AudioOutputFlags>);
-}
-
-ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
- const AudioIoFlags& aidl, bool isInput) {
- audio_io_flags legacy;
- if (isInput) {
- legacy.input = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_input_flags_t_mask(
- VALUE_OR_RETURN(UNION_GET(aidl, input))));
- } else {
- legacy.output = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_output_flags_t_mask(
- VALUE_OR_RETURN(UNION_GET(aidl, output))));
- }
- return legacy;
-}
-
-ConversionResult<AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
- const audio_io_flags& legacy, bool isInput) {
- AudioIoFlags aidl;
- if (isInput) {
- UNION_SET(aidl, input,
- VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(legacy.input)));
- } else {
- UNION_SET(aidl, output,
- VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(legacy.output)));
- }
- return aidl;
-}
-
-ConversionResult<audio_port_config_device_ext>
-aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
- const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlDeviceExt) {
- audio_port_config_device_ext legacy;
- legacy.hw_module = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_module_handle_t(aidlDeviceExt.hwModule));
- RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
- aidl.device, &legacy.type, legacy.address));
- return legacy;
-}
-
-status_t legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
- const audio_port_config_device_ext& legacy,
- AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
- aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
- aidl->device = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
- return OK;
-}
-
-ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
- AudioStreamType aidl) {
- switch (aidl) {
- case AudioStreamType::INVALID:
- break; // return error
- case AudioStreamType::SYS_RESERVED_DEFAULT:
- return AUDIO_STREAM_DEFAULT;
- case AudioStreamType::VOICE_CALL:
- return AUDIO_STREAM_VOICE_CALL;
- case AudioStreamType::SYSTEM:
- return AUDIO_STREAM_SYSTEM;
- case AudioStreamType::RING:
- return AUDIO_STREAM_RING;
- case AudioStreamType::MUSIC:
- return AUDIO_STREAM_MUSIC;
- case AudioStreamType::ALARM:
- return AUDIO_STREAM_ALARM;
- case AudioStreamType::NOTIFICATION:
- return AUDIO_STREAM_NOTIFICATION;
- case AudioStreamType::BLUETOOTH_SCO:
- return AUDIO_STREAM_BLUETOOTH_SCO;
- case AudioStreamType::ENFORCED_AUDIBLE:
- return AUDIO_STREAM_ENFORCED_AUDIBLE;
- case AudioStreamType::DTMF:
- return AUDIO_STREAM_DTMF;
- case AudioStreamType::TTS:
- return AUDIO_STREAM_TTS;
- case AudioStreamType::ACCESSIBILITY:
- return AUDIO_STREAM_ACCESSIBILITY;
- case AudioStreamType::ASSISTANT:
- return AUDIO_STREAM_ASSISTANT;
- case AudioStreamType::SYS_RESERVED_REROUTING:
- return AUDIO_STREAM_REROUTING;
- case AudioStreamType::SYS_RESERVED_PATCH:
- return AUDIO_STREAM_PATCH;
- case AudioStreamType::CALL_ASSISTANT:
- return AUDIO_STREAM_CALL_ASSISTANT;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioStreamType> legacy2aidl_audio_stream_type_t_AudioStreamType(
- audio_stream_type_t legacy) {
- switch (legacy) {
- case AUDIO_STREAM_DEFAULT:
- return AudioStreamType::SYS_RESERVED_DEFAULT;
- case AUDIO_STREAM_VOICE_CALL:
- return AudioStreamType::VOICE_CALL;
- case AUDIO_STREAM_SYSTEM:
- return AudioStreamType::SYSTEM;
- case AUDIO_STREAM_RING:
- return AudioStreamType::RING;
- case AUDIO_STREAM_MUSIC:
- return AudioStreamType::MUSIC;
- case AUDIO_STREAM_ALARM:
- return AudioStreamType::ALARM;
- case AUDIO_STREAM_NOTIFICATION:
- return AudioStreamType::NOTIFICATION;
- case AUDIO_STREAM_BLUETOOTH_SCO:
- return AudioStreamType::BLUETOOTH_SCO;
- case AUDIO_STREAM_ENFORCED_AUDIBLE:
- return AudioStreamType::ENFORCED_AUDIBLE;
- case AUDIO_STREAM_DTMF:
- return AudioStreamType::DTMF;
- case AUDIO_STREAM_TTS:
- return AudioStreamType::TTS;
- case AUDIO_STREAM_ACCESSIBILITY:
- return AudioStreamType::ACCESSIBILITY;
- case AUDIO_STREAM_ASSISTANT:
- return AudioStreamType::ASSISTANT;
- case AUDIO_STREAM_REROUTING:
- return AudioStreamType::SYS_RESERVED_REROUTING;
- case AUDIO_STREAM_PATCH:
- return AudioStreamType::SYS_RESERVED_PATCH;
- case AUDIO_STREAM_CALL_ASSISTANT:
- return AudioStreamType::CALL_ASSISTANT;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
- AudioSource aidl) {
- switch (aidl) {
- case AudioSource::SYS_RESERVED_INVALID:
- return AUDIO_SOURCE_INVALID;
- case AudioSource::DEFAULT:
- return AUDIO_SOURCE_DEFAULT;
- case AudioSource::MIC:
- return AUDIO_SOURCE_MIC;
- case AudioSource::VOICE_UPLINK:
- return AUDIO_SOURCE_VOICE_UPLINK;
- case AudioSource::VOICE_DOWNLINK:
- return AUDIO_SOURCE_VOICE_DOWNLINK;
- case AudioSource::VOICE_CALL:
- return AUDIO_SOURCE_VOICE_CALL;
- case AudioSource::CAMCORDER:
- return AUDIO_SOURCE_CAMCORDER;
- case AudioSource::VOICE_RECOGNITION:
- return AUDIO_SOURCE_VOICE_RECOGNITION;
- case AudioSource::VOICE_COMMUNICATION:
- return AUDIO_SOURCE_VOICE_COMMUNICATION;
- case AudioSource::REMOTE_SUBMIX:
- return AUDIO_SOURCE_REMOTE_SUBMIX;
- case AudioSource::UNPROCESSED:
- return AUDIO_SOURCE_UNPROCESSED;
- case AudioSource::VOICE_PERFORMANCE:
- return AUDIO_SOURCE_VOICE_PERFORMANCE;
- case AudioSource::ULTRASOUND:
- return AUDIO_SOURCE_ULTRASOUND;
- case AudioSource::ECHO_REFERENCE:
- return AUDIO_SOURCE_ECHO_REFERENCE;
- case AudioSource::FM_TUNER:
- return AUDIO_SOURCE_FM_TUNER;
- case AudioSource::HOTWORD:
- return AUDIO_SOURCE_HOTWORD;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioSource> legacy2aidl_audio_source_t_AudioSource(
- audio_source_t legacy) {
- switch (legacy) {
- case AUDIO_SOURCE_INVALID:
- return AudioSource::SYS_RESERVED_INVALID;
- case AUDIO_SOURCE_DEFAULT:
- return AudioSource::DEFAULT;
- case AUDIO_SOURCE_MIC:
- return AudioSource::MIC;
- case AUDIO_SOURCE_VOICE_UPLINK:
- return AudioSource::VOICE_UPLINK;
- case AUDIO_SOURCE_VOICE_DOWNLINK:
- return AudioSource::VOICE_DOWNLINK;
- case AUDIO_SOURCE_VOICE_CALL:
- return AudioSource::VOICE_CALL;
- case AUDIO_SOURCE_CAMCORDER:
- return AudioSource::CAMCORDER;
- case AUDIO_SOURCE_VOICE_RECOGNITION:
- return AudioSource::VOICE_RECOGNITION;
- case AUDIO_SOURCE_VOICE_COMMUNICATION:
- return AudioSource::VOICE_COMMUNICATION;
- case AUDIO_SOURCE_REMOTE_SUBMIX:
- return AudioSource::REMOTE_SUBMIX;
- case AUDIO_SOURCE_UNPROCESSED:
- return AudioSource::UNPROCESSED;
- case AUDIO_SOURCE_VOICE_PERFORMANCE:
- return AudioSource::VOICE_PERFORMANCE;
- case AUDIO_SOURCE_ULTRASOUND:
- return AudioSource::ULTRASOUND;
- case AUDIO_SOURCE_ECHO_REFERENCE:
- return AudioSource::ECHO_REFERENCE;
- case AUDIO_SOURCE_FM_TUNER:
- return AudioSource::FM_TUNER;
- case AUDIO_SOURCE_HOTWORD:
- return AudioSource::HOTWORD;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl) {
- return convertReinterpret<audio_session_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-// This type is unnamed in the original definition, thus we name it here.
-using audio_port_config_mix_ext_usecase = decltype(audio_port_config_mix_ext::usecase);
-
ConversionResult<audio_port_config_mix_ext_usecase> aidl2legacy_AudioPortMixExtUseCase(
const AudioPortMixExtUseCase& aidl, media::AudioPortRole role) {
- audio_port_config_mix_ext_usecase legacy;
-
switch (role) {
- case media::AudioPortRole::NONE:
+ case media::AudioPortRole::NONE: {
+ audio_port_config_mix_ext_usecase legacy;
// Just verify that the union is empty.
VALUE_OR_RETURN(UNION_GET(aidl, unspecified));
return legacy;
-
+ }
case media::AudioPortRole::SOURCE:
- // This is not a bug. A SOURCE role corresponds to the stream field.
- legacy.stream = VALUE_OR_RETURN(aidl2legacy_AudioStreamType_audio_stream_type_t(
- VALUE_OR_RETURN(UNION_GET(aidl, stream))));
- return legacy;
-
+ return aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+ aidl, false /*isInput*/);
case media::AudioPortRole::SINK:
- // This is not a bug. A SINK role corresponds to the source field.
- legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(
- VALUE_OR_RETURN(UNION_GET(aidl, source))));
- return legacy;
+ return aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+ aidl, true /*isInput*/);
}
LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
}
ConversionResult<AudioPortMixExtUseCase> legacy2aidl_AudioPortMixExtUseCase(
const audio_port_config_mix_ext_usecase& legacy, audio_port_role_t role) {
- AudioPortMixExtUseCase aidl;
-
switch (role) {
- case AUDIO_PORT_ROLE_NONE:
+ case AUDIO_PORT_ROLE_NONE: {
+ AudioPortMixExtUseCase aidl;
UNION_SET(aidl, unspecified, false);
return aidl;
+ }
case AUDIO_PORT_ROLE_SOURCE:
- // This is not a bug. A SOURCE role corresponds to the stream field.
- UNION_SET(aidl, stream, VALUE_OR_RETURN(
- legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream)));
- return aidl;
+ return legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+ legacy, false /*isInput*/);
case AUDIO_PORT_ROLE_SINK:
- // This is not a bug. A SINK role corresponds to the source field.
- UNION_SET(aidl, source,
- VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.source)));
- return aidl;
+ return legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+ legacy, true /*isInput*/);
}
LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
}
@@ -1873,6 +220,8 @@
ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortMixExt(
const AudioPortMixExt& aidl, media::AudioPortRole role,
const media::AudioPortMixExtSys& aidlMixExt) {
+ // Not using HAL-level 'aidl2legacy_AudioPortMixExt' as it does not support
+ // 'media::AudioPortRole::NONE'.
audio_port_config_mix_ext legacy;
legacy.hw_module = VALUE_OR_RETURN(
aidl2legacy_int32_t_audio_module_handle_t(aidlMixExt.hwModule));
@@ -1884,6 +233,8 @@
status_t legacy2aidl_AudioPortMixExt(
const audio_port_config_mix_ext& legacy, audio_port_role_t role,
AudioPortMixExt* aidl, media::AudioPortMixExtSys* aidlMixExt) {
+ // Not using HAL-level 'legacy2aidl_AudioPortMixExt' as it does not support
+ // 'AUDIO_PORT_ROLE_NONE'.
aidlMixExt->hwModule = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
aidl->handle = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
@@ -1905,12 +256,34 @@
return legacy2aidl_audio_session_t_int32_t(legacy.session);
}
+ConversionResult<audio_port_config_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
+ const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlDeviceExt) {
+ audio_port_config_device_ext legacy = VALUE_OR_RETURN(
+ aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(aidl));
+ legacy.hw_module = VALUE_OR_RETURN(
+ aidl2legacy_int32_t_audio_module_handle_t(aidlDeviceExt.hwModule));
+ return legacy;
+}
+
+status_t legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
+ const audio_port_config_device_ext& legacy,
+ AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
+ *aidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(legacy));
+ aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
+ return OK;
+}
+
// This type is unnamed in the original definition, thus we name it here.
using audio_port_config_ext = decltype(audio_port_config::ext);
ConversionResult<audio_port_config_ext> aidl2legacy_AudioPortExt_audio_port_config_ext(
const AudioPortExt& aidl, media::AudioPortType type,
media::AudioPortRole role, const media::AudioPortExtSys& aidlSys) {
+ // Not using HAL-level 'aidl2legacy_AudioPortExt_audio_port_config_ext' as it does not support
+ // 'media::AudioPortType::SESSION'.
audio_port_config_ext legacy;
switch (type) {
case media::AudioPortType::NONE:
@@ -1932,7 +305,7 @@
case media::AudioPortType::SESSION:
legacy.session = VALUE_OR_RETURN(
aidl2legacy_int32_t_audio_port_config_session_ext(
- VALUE_OR_RETURN(UNION_GET(aidl, session))));
+ VALUE_OR_RETURN(UNION_GET(aidlSys, session))));
return legacy;
}
@@ -1942,6 +315,8 @@
status_t legacy2aidl_AudioPortExt(
const audio_port_config_ext& legacy, audio_port_type_t type, audio_port_role_t role,
AudioPortExt* aidl, media::AudioPortExtSys* aidlSys) {
+ // Not using HAL-level 'aidl2legacy_AudioPortExt_audio_port_config_ext' as it does not support
+ // 'AUDIO_PORT_TYPE_SESSION'.
switch (type) {
case AUDIO_PORT_TYPE_NONE:
UNION_SET(*aidl, unspecified, false);
@@ -1966,91 +341,47 @@
return OK;
}
case AUDIO_PORT_TYPE_SESSION:
- UNION_SET(*aidl, session, VALUE_OR_RETURN_STATUS(
+ UNION_SET(*aidl, unspecified, false);
+ UNION_SET(*aidlSys, session, VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_port_config_session_ext_int32_t(legacy.session)));
- UNION_SET(*aidlSys, unspecified, false);
return OK;
}
LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
}
-ConversionResult<audio_port_config> aidl2legacy_AudioPortConfig_audio_port_config(
- const media::AudioPortConfig& aidl) {
- audio_port_config legacy{};
- legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.hal.id));
+ConversionResult<audio_port_config> aidl2legacy_AudioPortConfigFw_audio_port_config(
+ const media::AudioPortConfigFw& aidl, int32_t* aidlPortId) {
+ const bool isInput = VALUE_OR_RETURN(
+ portDirection(aidl.sys.role, aidl.sys.type)) == AudioPortDirection::INPUT;
+ audio_port_config legacy;
+ int32_t aidlPortIdHolder;
+ RETURN_IF_ERROR(aidl2legacy_AudioPortConfig_audio_port_config(
+ aidl.hal, isInput, &legacy, &aidlPortIdHolder));
+ if (aidlPortId != nullptr) *aidlPortId = aidlPortIdHolder;
legacy.role = VALUE_OR_RETURN(aidl2legacy_AudioPortRole_audio_port_role_t(aidl.sys.role));
legacy.type = VALUE_OR_RETURN(aidl2legacy_AudioPortType_audio_port_type_t(aidl.sys.type));
- const bool isInput =
- VALUE_OR_RETURN(direction(aidl.sys.role, aidl.sys.type)) == Direction::INPUT;
- if (aidl.hal.sampleRate.has_value()) {
- legacy.sample_rate = VALUE_OR_RETURN(
- convertIntegral<unsigned int>(aidl.hal.sampleRate.value().value));
- legacy.config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
- }
- if (aidl.hal.channelMask.has_value()) {
- legacy.channel_mask =
- VALUE_OR_RETURN(
- aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
- aidl.hal.channelMask.value(), isInput));
- legacy.config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
- }
- if (aidl.hal.format.has_value()) {
- legacy.format = VALUE_OR_RETURN(
- aidl2legacy_AudioFormatDescription_audio_format_t(aidl.hal.format.value()));
- legacy.config_mask |= AUDIO_PORT_CONFIG_FORMAT;
- }
- if (aidl.hal.gain.has_value()) {
- legacy.gain = VALUE_OR_RETURN(aidl2legacy_AudioGainConfig_audio_gain_config(
- aidl.hal.gain.value(), isInput));
- legacy.config_mask |= AUDIO_PORT_CONFIG_GAIN;
- }
- if (aidl.hal.flags.has_value()) {
- legacy.flags = VALUE_OR_RETURN(
- aidl2legacy_AudioIoFlags_audio_io_flags(aidl.hal.flags.value(), isInput));
- legacy.config_mask |= AUDIO_PORT_CONFIG_FLAGS;
- }
legacy.ext = VALUE_OR_RETURN(
aidl2legacy_AudioPortExt_audio_port_config_ext(
aidl.hal.ext, aidl.sys.type, aidl.sys.role, aidl.sys.ext));
return legacy;
}
-ConversionResult<media::AudioPortConfig> legacy2aidl_audio_port_config_AudioPortConfig(
- const audio_port_config& legacy) {
- media::AudioPortConfig aidl;
- aidl.hal.id = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+ConversionResult<media::AudioPortConfigFw> legacy2aidl_audio_port_config_AudioPortConfigFw(
+ const audio_port_config& legacy, int32_t portId) {
+ const bool isInput = VALUE_OR_RETURN(
+ portDirection(legacy.role, legacy.type)) == AudioPortDirection::INPUT;
+ media::AudioPortConfigFw aidl;
+ aidl.hal = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_config_AudioPortConfig(legacy, isInput, portId));
aidl.sys.role = VALUE_OR_RETURN(legacy2aidl_audio_port_role_t_AudioPortRole(legacy.role));
aidl.sys.type = VALUE_OR_RETURN(legacy2aidl_audio_port_type_t_AudioPortType(legacy.type));
- const bool isInput = VALUE_OR_RETURN(
- direction(legacy.role, legacy.type)) == Direction::INPUT;
- if (legacy.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
- Int aidl_sampleRate;
- aidl_sampleRate.value = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
- aidl.hal.sampleRate = aidl_sampleRate;
- }
- if (legacy.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
- aidl.hal.channelMask = VALUE_OR_RETURN(
- legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
- }
- if (legacy.config_mask & AUDIO_PORT_CONFIG_FORMAT) {
- aidl.hal.format = VALUE_OR_RETURN(
- legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
- }
- if (legacy.config_mask & AUDIO_PORT_CONFIG_GAIN) {
- aidl.hal.gain = VALUE_OR_RETURN(
- legacy2aidl_audio_gain_config_AudioGainConfig(legacy.gain, isInput));
- }
- if (legacy.config_mask & AUDIO_PORT_CONFIG_FLAGS) {
- aidl.hal.flags = VALUE_OR_RETURN(
- legacy2aidl_audio_io_flags_AudioIoFlags(legacy.flags, isInput));
- }
RETURN_IF_ERROR(legacy2aidl_AudioPortExt(legacy.ext, legacy.type, legacy.role,
&aidl.hal.ext, &aidl.sys.ext));
return aidl;
}
-ConversionResult<struct audio_patch> aidl2legacy_AudioPatch_audio_patch(
- const media::AudioPatch& aidl) {
+ConversionResult<struct audio_patch> aidl2legacy_AudioPatchFw_audio_patch(
+ const media::AudioPatchFw& aidl) {
struct audio_patch legacy;
legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_patch_handle_t(aidl.id));
legacy.num_sinks = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.sinks.size()));
@@ -2059,7 +390,7 @@
}
for (size_t i = 0; i < legacy.num_sinks; ++i) {
legacy.sinks[i] =
- VALUE_OR_RETURN(aidl2legacy_AudioPortConfig_audio_port_config(aidl.sinks[i]));
+ VALUE_OR_RETURN(aidl2legacy_AudioPortConfigFw_audio_port_config(aidl.sinks[i]));
}
legacy.num_sources = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.sources.size()));
if (legacy.num_sources > AUDIO_PATCH_PORTS_MAX) {
@@ -2067,14 +398,14 @@
}
for (size_t i = 0; i < legacy.num_sources; ++i) {
legacy.sources[i] =
- VALUE_OR_RETURN(aidl2legacy_AudioPortConfig_audio_port_config(aidl.sources[i]));
+ VALUE_OR_RETURN(aidl2legacy_AudioPortConfigFw_audio_port_config(aidl.sources[i]));
}
return legacy;
}
-ConversionResult<media::AudioPatch> legacy2aidl_audio_patch_AudioPatch(
+ConversionResult<media::AudioPatchFw> legacy2aidl_audio_patch_AudioPatchFw(
const struct audio_patch& legacy) {
- media::AudioPatch aidl;
+ media::AudioPatchFw aidl;
aidl.id = VALUE_OR_RETURN(legacy2aidl_audio_patch_handle_t_int32_t(legacy.id));
if (legacy.num_sinks > AUDIO_PATCH_PORTS_MAX) {
@@ -2082,14 +413,14 @@
}
for (unsigned int i = 0; i < legacy.num_sinks; ++i) {
aidl.sinks.push_back(
- VALUE_OR_RETURN(legacy2aidl_audio_port_config_AudioPortConfig(legacy.sinks[i])));
+ VALUE_OR_RETURN(legacy2aidl_audio_port_config_AudioPortConfigFw(legacy.sinks[i])));
}
if (legacy.num_sources > AUDIO_PATCH_PORTS_MAX) {
return unexpected(BAD_VALUE);
}
for (unsigned int i = 0; i < legacy.num_sources; ++i) {
aidl.sources.push_back(
- VALUE_OR_RETURN(legacy2aidl_audio_port_config_AudioPortConfig(legacy.sources[i])));
+ VALUE_OR_RETURN(legacy2aidl_audio_port_config_AudioPortConfigFw(legacy.sources[i])));
}
return aidl;
}
@@ -2099,7 +430,7 @@
const audio_io_handle_t io_handle = VALUE_OR_RETURN(
aidl2legacy_int32_t_audio_io_handle_t(aidl.ioHandle));
const struct audio_patch patch = VALUE_OR_RETURN(
- aidl2legacy_AudioPatch_audio_patch(aidl.patch));
+ aidl2legacy_AudioPatchFw_audio_patch(aidl.patch));
const bool isInput = aidl.isInput;
const uint32_t sampling_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.samplingRate));
const audio_format_t format = VALUE_OR_RETURN(
@@ -2119,7 +450,7 @@
const sp<AudioIoDescriptor>& legacy) {
media::AudioIoDescriptor aidl;
aidl.ioHandle = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(legacy->getIoHandle()));
- aidl.patch = VALUE_OR_RETURN(legacy2aidl_audio_patch_AudioPatch(legacy->getPatch()));
+ aidl.patch = VALUE_OR_RETURN(legacy2aidl_audio_patch_AudioPatchFw(legacy->getPatch()));
aidl.isInput = legacy->getIsInput();
aidl.samplingRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy->getSamplingRate()));
aidl.format = VALUE_OR_RETURN(
@@ -2149,148 +480,6 @@
return aidl;
}
-ConversionResult<audio_content_type_t>
-aidl2legacy_AudioContentType_audio_content_type_t(AudioContentType aidl) {
- switch (aidl) {
- case AudioContentType::UNKNOWN:
- return AUDIO_CONTENT_TYPE_UNKNOWN;
- case AudioContentType::SPEECH:
- return AUDIO_CONTENT_TYPE_SPEECH;
- case AudioContentType::MUSIC:
- return AUDIO_CONTENT_TYPE_MUSIC;
- case AudioContentType::MOVIE:
- return AUDIO_CONTENT_TYPE_MOVIE;
- case AudioContentType::SONIFICATION:
- return AUDIO_CONTENT_TYPE_SONIFICATION;
- case AudioContentType::ULTRASOUND:
- return AUDIO_CONTENT_TYPE_ULTRASOUND;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioContentType>
-legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy) {
- switch (legacy) {
- case AUDIO_CONTENT_TYPE_UNKNOWN:
- return AudioContentType::UNKNOWN;
- case AUDIO_CONTENT_TYPE_SPEECH:
- return AudioContentType::SPEECH;
- case AUDIO_CONTENT_TYPE_MUSIC:
- return AudioContentType::MUSIC;
- case AUDIO_CONTENT_TYPE_MOVIE:
- return AudioContentType::MOVIE;
- case AUDIO_CONTENT_TYPE_SONIFICATION:
- return AudioContentType::SONIFICATION;
- case AUDIO_CONTENT_TYPE_ULTRASOUND:
- return AudioContentType::ULTRASOUND;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_usage_t>
-aidl2legacy_AudioUsage_audio_usage_t(AudioUsage aidl) {
- switch (aidl) {
- case AudioUsage::INVALID:
- break; // return error
- case AudioUsage::UNKNOWN:
- return AUDIO_USAGE_UNKNOWN;
- case AudioUsage::MEDIA:
- return AUDIO_USAGE_MEDIA;
- case AudioUsage::VOICE_COMMUNICATION:
- return AUDIO_USAGE_VOICE_COMMUNICATION;
- case AudioUsage::VOICE_COMMUNICATION_SIGNALLING:
- return AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
- case AudioUsage::ALARM:
- return AUDIO_USAGE_ALARM;
- case AudioUsage::NOTIFICATION:
- return AUDIO_USAGE_NOTIFICATION;
- case AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE:
- return AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
- case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST:
- return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
- case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT:
- return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT;
- case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED:
- return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED;
- case AudioUsage::NOTIFICATION_EVENT:
- return AUDIO_USAGE_NOTIFICATION_EVENT;
- case AudioUsage::ASSISTANCE_ACCESSIBILITY:
- return AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
- case AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE:
- return AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
- case AudioUsage::ASSISTANCE_SONIFICATION:
- return AUDIO_USAGE_ASSISTANCE_SONIFICATION;
- case AudioUsage::GAME:
- return AUDIO_USAGE_GAME;
- case AudioUsage::VIRTUAL_SOURCE:
- return AUDIO_USAGE_VIRTUAL_SOURCE;
- case AudioUsage::ASSISTANT:
- return AUDIO_USAGE_ASSISTANT;
- case AudioUsage::CALL_ASSISTANT:
- return AUDIO_USAGE_CALL_ASSISTANT;
- case AudioUsage::EMERGENCY:
- return AUDIO_USAGE_EMERGENCY;
- case AudioUsage::SAFETY:
- return AUDIO_USAGE_SAFETY;
- case AudioUsage::VEHICLE_STATUS:
- return AUDIO_USAGE_VEHICLE_STATUS;
- case AudioUsage::ANNOUNCEMENT:
- return AUDIO_USAGE_ANNOUNCEMENT;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioUsage>
-legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy) {
- switch (legacy) {
- case AUDIO_USAGE_UNKNOWN:
- return AudioUsage::UNKNOWN;
- case AUDIO_USAGE_MEDIA:
- return AudioUsage::MEDIA;
- case AUDIO_USAGE_VOICE_COMMUNICATION:
- return AudioUsage::VOICE_COMMUNICATION;
- case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
- return AudioUsage::VOICE_COMMUNICATION_SIGNALLING;
- case AUDIO_USAGE_ALARM:
- return AudioUsage::ALARM;
- case AUDIO_USAGE_NOTIFICATION:
- return AudioUsage::NOTIFICATION;
- case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
- return AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE;
- case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
- return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST;
- case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
- return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT;
- case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
- return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED;
- case AUDIO_USAGE_NOTIFICATION_EVENT:
- return AudioUsage::NOTIFICATION_EVENT;
- case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
- return AudioUsage::ASSISTANCE_ACCESSIBILITY;
- case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
- return AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE;
- case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
- return AudioUsage::ASSISTANCE_SONIFICATION;
- case AUDIO_USAGE_GAME:
- return AudioUsage::GAME;
- case AUDIO_USAGE_VIRTUAL_SOURCE:
- return AudioUsage::VIRTUAL_SOURCE;
- case AUDIO_USAGE_ASSISTANT:
- return AudioUsage::ASSISTANT;
- case AUDIO_USAGE_CALL_ASSISTANT:
- return AudioUsage::CALL_ASSISTANT;
- case AUDIO_USAGE_EMERGENCY:
- return AudioUsage::EMERGENCY;
- case AUDIO_USAGE_SAFETY:
- return AudioUsage::SAFETY;
- case AUDIO_USAGE_VEHICLE_STATUS:
- return AudioUsage::VEHICLE_STATUS;
- case AUDIO_USAGE_ANNOUNCEMENT:
- return AudioUsage::ANNOUNCEMENT;
- }
- return unexpected(BAD_VALUE);
-}
-
ConversionResult<audio_flags_mask_t>
aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl) {
switch (aidl) {
@@ -2414,140 +603,6 @@
return aidl;
}
-ConversionResult<audio_encapsulation_mode_t>
-aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(AudioEncapsulationMode aidl) {
- switch (aidl) {
- case AudioEncapsulationMode::INVALID:
- break; // return error
- case AudioEncapsulationMode::NONE:
- return AUDIO_ENCAPSULATION_MODE_NONE;
- case AudioEncapsulationMode::ELEMENTARY_STREAM:
- return AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM;
- case AudioEncapsulationMode::HANDLE:
- return AUDIO_ENCAPSULATION_MODE_HANDLE;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioEncapsulationMode>
-legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy) {
- switch (legacy) {
- case AUDIO_ENCAPSULATION_MODE_NONE:
- return AudioEncapsulationMode::NONE;
- case AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM:
- return AudioEncapsulationMode::ELEMENTARY_STREAM;
- case AUDIO_ENCAPSULATION_MODE_HANDLE:
- return AudioEncapsulationMode::HANDLE;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_offload_info_t>
-aidl2legacy_AudioOffloadInfo_audio_offload_info_t(const AudioOffloadInfo& aidl) {
- audio_offload_info_t legacy = AUDIO_INFO_INITIALIZER;
- audio_config_base_t base = VALUE_OR_RETURN(
- aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, false /*isInput*/));
- legacy.sample_rate = base.sample_rate;
- legacy.channel_mask = base.channel_mask;
- legacy.format = base.format;
- legacy.stream_type = VALUE_OR_RETURN(
- aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
- legacy.bit_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitRatePerSecond));
- legacy.duration_us = VALUE_OR_RETURN(convertIntegral<int64_t>(aidl.durationUs));
- legacy.has_video = aidl.hasVideo;
- legacy.is_streaming = aidl.isStreaming;
- legacy.bit_width = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitWidth));
- legacy.offload_buffer_size = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.offloadBufferSize));
- legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
- legacy.encapsulation_mode = VALUE_OR_RETURN(
- aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(aidl.encapsulationMode));
- legacy.content_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.contentId));
- legacy.sync_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.syncId));
- return legacy;
-}
-
-ConversionResult<AudioOffloadInfo>
-legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy) {
- AudioOffloadInfo aidl;
- // Version 0.1 fields.
- if (legacy.size < offsetof(audio_offload_info_t, usage) + sizeof(audio_offload_info_t::usage)) {
- return unexpected(BAD_VALUE);
- }
- const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
- .channel_mask = legacy.channel_mask, .format = legacy.format };
- aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(
- base, false /*isInput*/));
- aidl.streamType = VALUE_OR_RETURN(
- legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream_type));
- aidl.bitRatePerSecond = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_rate));
- aidl.durationUs = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.duration_us));
- aidl.hasVideo = legacy.has_video;
- aidl.isStreaming = legacy.is_streaming;
- aidl.bitWidth = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_width));
- aidl.offloadBufferSize = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.offload_buffer_size));
- aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
-
- // Version 0.2 fields.
- if (legacy.version >= AUDIO_OFFLOAD_INFO_VERSION_0_2) {
- if (legacy.size <
- offsetof(audio_offload_info_t, sync_id) + sizeof(audio_offload_info_t::sync_id)) {
- return unexpected(BAD_VALUE);
- }
- aidl.encapsulationMode = VALUE_OR_RETURN(
- legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(
- legacy.encapsulation_mode));
- aidl.contentId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.content_id));
- aidl.syncId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.sync_id));
- }
- return aidl;
-}
-
-ConversionResult<audio_config_t>
-aidl2legacy_AudioConfig_audio_config_t(const AudioConfig& aidl, bool isInput) {
- const audio_config_base_t legacyBase = VALUE_OR_RETURN(
- aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, isInput));
- audio_config_t legacy = AUDIO_CONFIG_INITIALIZER;
- legacy.sample_rate = legacyBase.sample_rate;
- legacy.channel_mask = legacyBase.channel_mask;
- legacy.format = legacyBase.format;
- legacy.offload_info = VALUE_OR_RETURN(
- aidl2legacy_AudioOffloadInfo_audio_offload_info_t(aidl.offloadInfo));
- legacy.frame_count = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.frameCount));
- return legacy;
-}
-
-ConversionResult<AudioConfig>
-legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput) {
- const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
- .channel_mask = legacy.channel_mask, .format = legacy.format };
- AudioConfig aidl;
- aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(base, isInput));
- aidl.offloadInfo = VALUE_OR_RETURN(
- legacy2aidl_audio_offload_info_t_AudioOffloadInfo(legacy.offload_info));
- aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.frame_count));
- return aidl;
-}
-
-ConversionResult<audio_config_base_t>
-aidl2legacy_AudioConfigBase_audio_config_base_t(const AudioConfigBase& aidl, bool isInput) {
- audio_config_base_t legacy;
- legacy.sample_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
- legacy.channel_mask = VALUE_OR_RETURN(
- aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
- legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
- return legacy;
-}
-
-ConversionResult<AudioConfigBase>
-legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput) {
- AudioConfigBase aidl;
- aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
- aidl.channelMask = VALUE_OR_RETURN(
- legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
- aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
- return aidl;
-}
-
ConversionResult<sp<IMemory>>
aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl) {
sp<IMemory> legacy;
@@ -2566,8 +621,8 @@
return aidl;
}
-ConversionResult<sp<IMemory>>
-aidl2legacy_NullableSharedFileRegion_IMemory(const std::optional<media::SharedFileRegion>& aidl) {
+ConversionResult<sp<IMemory>> aidl2legacy_NullableSharedFileRegion_IMemory(
+ const std::optional<media::SharedFileRegion>& aidl) {
sp<IMemory> legacy;
if (!convertNullableSharedFileRegionToIMemory(aidl, &legacy)) {
return unexpected(BAD_VALUE);
@@ -2602,31 +657,6 @@
return aidl;
}
-ConversionResult<audio_uuid_t>
-aidl2legacy_AudioUuid_audio_uuid_t(const AudioUuid& aidl) {
- audio_uuid_t legacy;
- legacy.timeLow = VALUE_OR_RETURN(convertReinterpret<uint32_t>(aidl.timeLow));
- legacy.timeMid = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeMid));
- legacy.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeHiAndVersion));
- legacy.clockSeq = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.clockSeq));
- if (aidl.node.size() != std::size(legacy.node)) {
- return unexpected(BAD_VALUE);
- }
- std::copy(aidl.node.begin(), aidl.node.end(), legacy.node);
- return legacy;
-}
-
-ConversionResult<AudioUuid>
-legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy) {
- AudioUuid aidl;
- aidl.timeLow = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.timeLow));
- aidl.timeMid = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeMid));
- aidl.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeHiAndVersion));
- aidl.clockSeq = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.clockSeq));
- std::copy(legacy.node, legacy.node + std::size(legacy.node), std::back_inserter(aidl.node));
- return aidl;
-}
-
ConversionResult<effect_descriptor_t>
aidl2legacy_EffectDescriptor_effect_descriptor_t(const media::EffectDescriptor& aidl) {
effect_descriptor_t legacy;
@@ -2657,123 +687,21 @@
return aidl;
}
-ConversionResult<audio_encapsulation_metadata_type_t>
-aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
- AudioEncapsulationMetadataType aidl) {
- switch (aidl) {
- case AudioEncapsulationMetadataType::NONE:
- return AUDIO_ENCAPSULATION_METADATA_TYPE_NONE;
- case AudioEncapsulationMetadataType::FRAMEWORK_TUNER:
- return AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER;
- case AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR:
- return AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioEncapsulationMetadataType>
-legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
- audio_encapsulation_metadata_type_t legacy) {
- switch (legacy) {
- case AUDIO_ENCAPSULATION_METADATA_TYPE_NONE:
- return AudioEncapsulationMetadataType::NONE;
- case AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER:
- return AudioEncapsulationMetadataType::FRAMEWORK_TUNER;
- case AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR:
- return AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl) {
- return convertBitmask<uint32_t,
- int32_t,
- audio_encapsulation_mode_t,
- AudioEncapsulationMode>(
- aidl, aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t,
- indexToEnum_index<AudioEncapsulationMode>,
- enumToMask_index<uint32_t, audio_encapsulation_mode_t>);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy) {
- return convertBitmask<int32_t,
- uint32_t,
- AudioEncapsulationMode,
- audio_encapsulation_mode_t>(
- legacy, legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode,
- indexToEnum_index<audio_encapsulation_mode_t>,
- enumToMask_index<int32_t, AudioEncapsulationMode>);
-}
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl) {
- return convertBitmask<uint32_t,
- int32_t,
- audio_encapsulation_metadata_type_t,
- AudioEncapsulationMetadataType>(
- aidl, aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t,
- indexToEnum_index<AudioEncapsulationMetadataType>,
- enumToMask_index<uint32_t, audio_encapsulation_metadata_type_t>);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy) {
- return convertBitmask<int32_t,
- uint32_t,
- AudioEncapsulationMetadataType,
- audio_encapsulation_metadata_type_t>(
- legacy, legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType,
- indexToEnum_index<audio_encapsulation_metadata_type_t>,
- enumToMask_index<int32_t, AudioEncapsulationMetadataType>);
-}
-
-ConversionResult<audio_port_device_ext>
-aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
- const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlSys) {
- audio_port_device_ext legacy;
- legacy.hw_module = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_module_handle_t(aidlSys.hwModule));
- RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
- aidl.device, &legacy.type, legacy.address));
- legacy.encapsulation_modes = VALUE_OR_RETURN(
- aidl2legacy_AudioEncapsulationMode_mask(aidlSys.encapsulationModes));
- legacy.encapsulation_metadata_types = VALUE_OR_RETURN(
- aidl2legacy_AudioEncapsulationMetadataType_mask(
- aidlSys.encapsulationMetadataTypes));
- return legacy;
-}
-
-status_t legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
- const audio_port_device_ext& legacy,
- AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
- aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
- aidl->device = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
- aidlDeviceExt->encapsulationModes = VALUE_OR_RETURN_STATUS(
- legacy2aidl_AudioEncapsulationMode_mask(legacy.encapsulation_modes));
- aidlDeviceExt->encapsulationMetadataTypes = VALUE_OR_RETURN_STATUS(
- legacy2aidl_AudioEncapsulationMetadataType_mask(legacy.encapsulation_metadata_types));
- return OK;
-}
-
ConversionResult<audio_port_mix_ext>
aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
const AudioPortMixExt& aidl, const media::AudioPortMixExtSys& aidlSys) {
- audio_port_mix_ext legacy{};
+ audio_port_mix_ext legacy = VALUE_OR_RETURN(
+ aidl2legacy_AudioPortMixExt_audio_port_mix_ext(aidl));
legacy.hw_module = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_module_handle_t(aidlSys.hwModule));
- legacy.handle = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.handle));
return legacy;
}
status_t
legacy2aidl_audio_port_mix_ext_AudioPortMixExt(const audio_port_mix_ext& legacy,
AudioPortMixExt* aidl, media::AudioPortMixExtSys* aidlMixExt) {
+ *aidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_mix_ext_AudioPortMixExt(legacy));
aidlMixExt->hwModule = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
- aidl->handle = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
return OK;
}
@@ -2789,6 +717,25 @@
return legacy2aidl_audio_session_t_int32_t(legacy.session);
}
+ConversionResult<audio_port_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
+ const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlSys) {
+ audio_port_device_ext legacy = VALUE_OR_RETURN(
+ aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(aidl));
+ legacy.hw_module = VALUE_OR_RETURN(
+ aidl2legacy_int32_t_audio_module_handle_t(aidlSys.hwModule));
+ return legacy;
+}
+
+status_t legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
+ const audio_port_device_ext& legacy,
+ AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
+ *aidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(legacy));
+ aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
+ return OK;
+}
+
// This type is unnamed in the original definition, thus we name it here.
using audio_port_v7_ext = decltype(audio_port_v7::ext);
@@ -2816,7 +763,7 @@
case media::AudioPortType::SESSION:
legacy.session = VALUE_OR_RETURN(
aidl2legacy_int32_t_audio_port_session_ext(
- VALUE_OR_RETURN(UNION_GET(aidl, session))));
+ VALUE_OR_RETURN(UNION_GET(aidlSys, session))));
return legacy;
}
@@ -2852,247 +799,48 @@
return OK;
}
case AUDIO_PORT_TYPE_SESSION:
- UNION_SET(*aidl, session, VALUE_OR_RETURN_STATUS(
+ UNION_SET(*aidl, unspecified, false);
+ UNION_SET(*aidlSys, session, VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_port_session_ext_int32_t(legacy.session)));
- UNION_SET(*aidlSys, unspecified, false);
return OK;
}
LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
}
-ConversionResult<audio_profile>
-aidl2legacy_AudioProfile_audio_profile(const AudioProfile& aidl, bool isInput) {
- audio_profile legacy;
- legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
-
- if (aidl.sampleRates.size() > std::size(legacy.sample_rates)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(
- convertRange(aidl.sampleRates.begin(), aidl.sampleRates.end(), legacy.sample_rates,
- convertIntegral<int32_t, unsigned int>));
- legacy.num_sample_rates = aidl.sampleRates.size();
-
- if (aidl.channelMasks.size() > std::size(legacy.channel_masks)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(
- convertRange(aidl.channelMasks.begin(), aidl.channelMasks.end(), legacy.channel_masks,
- [isInput](const AudioChannelLayout& l) {
- return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
- }));
- legacy.num_channel_masks = aidl.channelMasks.size();
-
- legacy.encapsulation_type = VALUE_OR_RETURN(
- aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(aidl.encapsulationType));
- return legacy;
-}
-
-ConversionResult<AudioProfile>
-legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput) {
- AudioProfile aidl;
- aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
-
- if (legacy.num_sample_rates > std::size(legacy.sample_rates)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(
- convertRange(legacy.sample_rates, legacy.sample_rates + legacy.num_sample_rates,
- std::back_inserter(aidl.sampleRates),
- convertIntegral<unsigned int, int32_t>));
-
- if (legacy.num_channel_masks > std::size(legacy.channel_masks)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(
- convertRange(legacy.channel_masks, legacy.channel_masks + legacy.num_channel_masks,
- std::back_inserter(aidl.channelMasks),
- [isInput](audio_channel_mask_t m) {
- return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
- }));
-
- aidl.encapsulationType = VALUE_OR_RETURN(
- legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
- legacy.encapsulation_type));
- return aidl;
-}
-
-ConversionResult<audio_gain>
-aidl2legacy_AudioGain_audio_gain(const AudioGain& aidl, bool isInput) {
- audio_gain legacy;
- legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
- legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
- aidl.channelMask, isInput));
- legacy.min_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.minValue));
- legacy.max_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.maxValue));
- legacy.default_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.defaultValue));
- legacy.step_value = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.stepValue));
- legacy.min_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.minRampMs));
- legacy.max_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.maxRampMs));
- return legacy;
-}
-
-ConversionResult<AudioGain>
-legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput) {
- AudioGain aidl;
- aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
- aidl.channelMask = VALUE_OR_RETURN(
- legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
- aidl.minValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_value));
- aidl.maxValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_value));
- aidl.defaultValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.default_value));
- aidl.stepValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.step_value));
- aidl.minRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_ramp_ms));
- aidl.maxRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_ramp_ms));
- return aidl;
-}
-
ConversionResult<audio_port_v7>
-aidl2legacy_AudioPort_audio_port_v7(const media::AudioPort& aidl) {
- audio_port_v7 legacy;
- legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.hal.id));
+aidl2legacy_AudioPortFw_audio_port_v7(const media::AudioPortFw& aidl) {
+ const bool isInput = VALUE_OR_RETURN(
+ portDirection(aidl.sys.role, aidl.sys.type)) == AudioPortDirection::INPUT;
+ audio_port_v7 legacy = VALUE_OR_RETURN(aidl2legacy_AudioPort_audio_port_v7(aidl.hal, isInput));
legacy.role = VALUE_OR_RETURN(aidl2legacy_AudioPortRole_audio_port_role_t(aidl.sys.role));
legacy.type = VALUE_OR_RETURN(aidl2legacy_AudioPortType_audio_port_type_t(aidl.sys.type));
- RETURN_IF_ERROR(aidl2legacy_string(aidl.hal.name, legacy.name, sizeof(legacy.name)));
-
- if (aidl.hal.profiles.size() > std::size(legacy.audio_profiles)) {
- return unexpected(BAD_VALUE);
- }
- const bool isInput =
- VALUE_OR_RETURN(direction(aidl.sys.role, aidl.sys.type)) == Direction::INPUT;
- RETURN_IF_ERROR(convertRange(
- aidl.hal.profiles.begin(), aidl.hal.profiles.end(), legacy.audio_profiles,
- [isInput](const AudioProfile& p) {
- return aidl2legacy_AudioProfile_audio_profile(p, isInput);
- }));
- legacy.num_audio_profiles = aidl.hal.profiles.size();
-
- if (aidl.hal.extraAudioDescriptors.size() > std::size(legacy.extra_audio_descriptors)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(
- convertRange(
- aidl.hal.extraAudioDescriptors.begin(), aidl.hal.extraAudioDescriptors.end(),
- legacy.extra_audio_descriptors,
- aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor));
- legacy.num_extra_audio_descriptors = aidl.hal.extraAudioDescriptors.size();
-
- if (aidl.hal.gains.size() > std::size(legacy.gains)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(convertRange(aidl.hal.gains.begin(), aidl.hal.gains.end(), legacy.gains,
- [isInput](const AudioGain& g) {
- return aidl2legacy_AudioGain_audio_gain(g, isInput);
- }));
- legacy.num_gains = aidl.hal.gains.size();
legacy.active_config = VALUE_OR_RETURN(
- aidl2legacy_AudioPortConfig_audio_port_config(aidl.sys.activeConfig));
+ aidl2legacy_AudioPortConfigFw_audio_port_config(aidl.sys.activeConfig));
legacy.ext = VALUE_OR_RETURN(
aidl2legacy_AudioPortExt_audio_port_v7_ext(aidl.hal.ext, aidl.sys.type, aidl.sys.ext));
return legacy;
}
-ConversionResult<media::AudioPort>
-legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy) {
- media::AudioPort aidl;
- aidl.hal.id = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+ConversionResult<media::AudioPortFw>
+legacy2aidl_audio_port_v7_AudioPortFw(const audio_port_v7& legacy) {
+ const bool isInput = VALUE_OR_RETURN(
+ portDirection(legacy.role, legacy.type)) == AudioPortDirection::INPUT;
+ media::AudioPortFw aidl;
+ aidl.hal = VALUE_OR_RETURN(legacy2aidl_audio_port_v7_AudioPort(legacy, isInput));
aidl.sys.role = VALUE_OR_RETURN(legacy2aidl_audio_port_role_t_AudioPortRole(legacy.role));
aidl.sys.type = VALUE_OR_RETURN(legacy2aidl_audio_port_type_t_AudioPortType(legacy.type));
- aidl.hal.name = VALUE_OR_RETURN(legacy2aidl_string(legacy.name, sizeof(legacy.name)));
-
- if (legacy.num_audio_profiles > std::size(legacy.audio_profiles)) {
- return unexpected(BAD_VALUE);
- }
- const bool isInput = VALUE_OR_RETURN(direction(legacy.role, legacy.type)) == Direction::INPUT;
- RETURN_IF_ERROR(
- convertRange(legacy.audio_profiles, legacy.audio_profiles + legacy.num_audio_profiles,
- std::back_inserter(aidl.hal.profiles),
- [isInput](const audio_profile& p) {
- return legacy2aidl_audio_profile_AudioProfile(p, isInput);
- }));
-
- if (legacy.num_extra_audio_descriptors > std::size(legacy.extra_audio_descriptors)) {
- return unexpected(BAD_VALUE);
- }
+ // These get filled by the call to 'legacy2aidl_AudioPortExt' below.
aidl.sys.profiles.resize(legacy.num_audio_profiles);
- RETURN_IF_ERROR(
- convertRange(legacy.extra_audio_descriptors,
- legacy.extra_audio_descriptors + legacy.num_extra_audio_descriptors,
- std::back_inserter(aidl.hal.extraAudioDescriptors),
- legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor));
-
- if (legacy.num_gains > std::size(legacy.gains)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(
- convertRange(legacy.gains, legacy.gains + legacy.num_gains,
- std::back_inserter(aidl.hal.gains),
- [isInput](const audio_gain& g) {
- return legacy2aidl_audio_gain_AudioGain(g, isInput);
- }));
aidl.sys.gains.resize(legacy.num_gains);
-
aidl.sys.activeConfig = VALUE_OR_RETURN(
- legacy2aidl_audio_port_config_AudioPortConfig(legacy.active_config));
+ legacy2aidl_audio_port_config_AudioPortConfigFw(legacy.active_config, legacy.id));
aidl.sys.activeConfig.hal.portId = aidl.hal.id;
RETURN_IF_ERROR(
legacy2aidl_AudioPortExt(legacy.ext, legacy.type, &aidl.hal.ext, &aidl.sys.ext));
return aidl;
}
-ConversionResult<audio_mode_t>
-aidl2legacy_AudioMode_audio_mode_t(AudioMode aidl) {
- switch (aidl) {
- case AudioMode::SYS_RESERVED_INVALID:
- return AUDIO_MODE_INVALID;
- case AudioMode::SYS_RESERVED_CURRENT:
- return AUDIO_MODE_CURRENT;
- case AudioMode::NORMAL:
- return AUDIO_MODE_NORMAL;
- case AudioMode::RINGTONE:
- return AUDIO_MODE_RINGTONE;
- case AudioMode::IN_CALL:
- return AUDIO_MODE_IN_CALL;
- case AudioMode::IN_COMMUNICATION:
- return AUDIO_MODE_IN_COMMUNICATION;
- case AudioMode::CALL_SCREEN:
- return AUDIO_MODE_CALL_SCREEN;
- case AudioMode::SYS_RESERVED_CALL_REDIRECT:
- return AUDIO_MODE_CALL_REDIRECT;
- case AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT:
- return AUDIO_MODE_COMMUNICATION_REDIRECT;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioMode>
-legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy) {
- switch (legacy) {
- case AUDIO_MODE_INVALID:
- return AudioMode::SYS_RESERVED_INVALID;
- case AUDIO_MODE_CURRENT:
- return AudioMode::SYS_RESERVED_CURRENT;
- case AUDIO_MODE_NORMAL:
- return AudioMode::NORMAL;
- case AUDIO_MODE_RINGTONE:
- return AudioMode::RINGTONE;
- case AUDIO_MODE_IN_CALL:
- return AudioMode::IN_CALL;
- case AUDIO_MODE_IN_COMMUNICATION:
- return AudioMode::IN_COMMUNICATION;
- case AUDIO_MODE_CALL_SCREEN:
- return AudioMode::CALL_SCREEN;
- case AUDIO_MODE_CALL_REDIRECT:
- return AudioMode::SYS_RESERVED_CALL_REDIRECT;
- case AUDIO_MODE_COMMUNICATION_REDIRECT:
- return AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT;
- case AUDIO_MODE_CNT:
- break;
- }
- return unexpected(BAD_VALUE);
-}
-
ConversionResult<audio_unique_id_use_t>
aidl2legacy_AudioUniqueIdUse_audio_unique_id_use_t(media::AudioUniqueIdUse aidl) {
switch (aidl) {
@@ -3161,160 +909,6 @@
return convertReinterpret<int32_t>(legacy);
}
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl) {
- switch (aidl) {
- case media::AudioDualMonoMode::OFF:
- return AUDIO_DUAL_MONO_MODE_OFF;
- case media::AudioDualMonoMode::LR:
- return AUDIO_DUAL_MONO_MODE_LR;
- case media::AudioDualMonoMode::LL:
- return AUDIO_DUAL_MONO_MODE_LL;
- case media::AudioDualMonoMode::RR:
- return AUDIO_DUAL_MONO_MODE_RR;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
- switch (legacy) {
- case AUDIO_DUAL_MONO_MODE_OFF:
- return media::AudioDualMonoMode::OFF;
- case AUDIO_DUAL_MONO_MODE_LR:
- return media::AudioDualMonoMode::LR;
- case AUDIO_DUAL_MONO_MODE_LL:
- return media::AudioDualMonoMode::LL;
- case AUDIO_DUAL_MONO_MODE_RR:
- return media::AudioDualMonoMode::RR;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl) {
- return convertReinterpret<audio_timestretch_fallback_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl) {
- return convertReinterpret<audio_timestretch_stretch_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl) {
- audio_playback_rate_t legacy;
- legacy.mSpeed = aidl.speed;
- legacy.mPitch = aidl.pitch;
- legacy.mFallbackMode = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(aidl.fallbackMode));
- legacy.mStretchMode = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(aidl.stretchMode));
- return legacy;
-}
-
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
- media::AudioPlaybackRate aidl;
- aidl.speed = legacy.mSpeed;
- aidl.pitch = legacy.mPitch;
- aidl.fallbackMode = VALUE_OR_RETURN(
- legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(legacy.mFallbackMode));
- aidl.stretchMode = VALUE_OR_RETURN(
- legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(legacy.mStretchMode));
- return aidl;
-}
-
-ConversionResult<audio_standard_t>
-aidl2legacy_AudioStandard_audio_standard_t(AudioStandard aidl) {
- switch (aidl) {
- case AudioStandard::NONE:
- return AUDIO_STANDARD_NONE;
- case AudioStandard::EDID:
- return AUDIO_STANDARD_EDID;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioStandard>
-legacy2aidl_audio_standard_t_AudioStandard(audio_standard_t legacy) {
- switch (legacy) {
- case AUDIO_STANDARD_NONE:
- return AudioStandard::NONE;
- case AUDIO_STANDARD_EDID:
- return AudioStandard::EDID;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_extra_audio_descriptor>
-aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
- const ExtraAudioDescriptor& aidl) {
- audio_extra_audio_descriptor legacy;
- legacy.standard = VALUE_OR_RETURN(aidl2legacy_AudioStandard_audio_standard_t(aidl.standard));
- if (aidl.audioDescriptor.size() > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
- return unexpected(BAD_VALUE);
- }
- legacy.descriptor_length = aidl.audioDescriptor.size();
- std::copy(aidl.audioDescriptor.begin(), aidl.audioDescriptor.end(),
- std::begin(legacy.descriptor));
- legacy.encapsulation_type =
- VALUE_OR_RETURN(aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
- aidl.encapsulationType));
- return legacy;
-}
-
-ConversionResult<ExtraAudioDescriptor>
-legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
- const audio_extra_audio_descriptor& legacy) {
- ExtraAudioDescriptor aidl;
- aidl.standard = VALUE_OR_RETURN(legacy2aidl_audio_standard_t_AudioStandard(legacy.standard));
- if (legacy.descriptor_length > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
- return unexpected(BAD_VALUE);
- }
- aidl.audioDescriptor.resize(legacy.descriptor_length);
- std::copy(legacy.descriptor, legacy.descriptor + legacy.descriptor_length,
- aidl.audioDescriptor.begin());
- aidl.encapsulationType =
- VALUE_OR_RETURN(legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
- legacy.encapsulation_type));
- return aidl;
-}
-
-ConversionResult<audio_encapsulation_type_t>
-aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
- const AudioEncapsulationType& aidl) {
- switch (aidl) {
- case AudioEncapsulationType::NONE:
- return AUDIO_ENCAPSULATION_TYPE_NONE;
- case AudioEncapsulationType::IEC61937:
- return AUDIO_ENCAPSULATION_TYPE_IEC61937;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioEncapsulationType>
-legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
- const audio_encapsulation_type_t & legacy) {
- switch (legacy) {
- case AUDIO_ENCAPSULATION_TYPE_NONE:
- return AudioEncapsulationType::NONE;
- case AUDIO_ENCAPSULATION_TYPE_IEC61937:
- return AudioEncapsulationType::IEC61937;
- }
- return unexpected(BAD_VALUE);
-}
-
ConversionResult<TrackSecondaryOutputInfoPair>
aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
const media::TrackSecondaryOutputInfo& aidl) {
@@ -3388,24 +982,23 @@
enumToMask_index<int32_t, media::AudioDirectMode>);
}
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl) {
- switch (aidl) {
- case media::LatencyMode::FREE:
- return AUDIO_LATENCY_MODE_FREE;
- case media::LatencyMode::LOW:
- return AUDIO_LATENCY_MODE_LOW;
- }
- return unexpected(BAD_VALUE);
+ConversionResult<audio_microphone_characteristic_t>
+aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(
+ const media::MicrophoneInfoFw& aidl) {
+ audio_microphone_characteristic_t legacy =
+ VALUE_OR_RETURN(aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t(
+ aidl.info, aidl.dynamic));
+ legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.portId));
+ return legacy;
}
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy) {
- switch (legacy) {
- case AUDIO_LATENCY_MODE_FREE:
- return media::LatencyMode::FREE;
- case AUDIO_LATENCY_MODE_LOW:
- return media::LatencyMode::LOW;
- }
- return unexpected(BAD_VALUE);
+ConversionResult<media::MicrophoneInfoFw>
+legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(
+ const audio_microphone_characteristic_t& legacy) {
+ media::MicrophoneInfoFw aidl;
+ RETURN_IF_ERROR(legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfos(
+ legacy, &aidl.info, &aidl.dynamic));
+ aidl.portId = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+ return aidl;
}
+
} // namespace android
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index dccef0e..30658f7 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -54,8 +54,10 @@
"AudioVolumeGroup.cpp",
"PolicyAidlConversion.cpp"
],
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_export_shared",
+ ],
shared_libs: [
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
"audioflinger-aidl-cpp",
"audiopolicy-aidl-cpp",
@@ -76,7 +78,6 @@
include_dirs: ["system/media/audio_utils/include"],
export_include_dirs: ["include"],
export_shared_lib_headers: [
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
"audioflinger-aidl-cpp",
"audiopolicy-aidl-cpp",
@@ -116,8 +117,10 @@
"RecordingActivityTracker.cpp",
"TrackPlayerBase.cpp",
],
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
shared_libs: [
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
"audioflinger-aidl-cpp",
"audiopolicy-aidl-cpp",
@@ -125,6 +128,7 @@
"audiopolicy-types-aidl-cpp",
"av-types-aidl-cpp",
"capture_state_listener-aidl-cpp",
+ "libaudio_aidl_conversion_common_cpp",
"libaudioclient_aidl_conversion",
"libaudiofoundation",
"libaudioutils",
@@ -190,87 +194,31 @@
},
}
-// This is intended for clients needing to include AidlConversionUtil.h, without dragging in a lot of extra
-// dependencies.
-cc_library_headers {
- name: "libaudioclient_aidl_conversion_util",
- host_supported: true,
- vendor_available: true,
- double_loadable: true,
- min_sdk_version: "29",
- export_include_dirs: [
- "include",
- ],
- header_libs: [
- "libbase_headers",
- "liberror_headers",
- ],
- export_header_lib_headers: [
- "libbase_headers",
- "liberror_headers",
- ],
- apex_available: [
- "//apex_available:platform",
- "com.android.bluetooth",
- "com.android.media",
- "com.android.media.swcodec",
- ],
- target: {
- darwin: {
- enabled: false,
- },
- },
-}
-
cc_library {
name: "libaudioclient_aidl_conversion",
srcs: ["AidlConversion.cpp"],
+ shared_libs: [
+ "audioclient-types-aidl-cpp",
+ "av-types-aidl-cpp",
+ ],
+ static_libs: [
+ "libaudio_aidl_conversion_common_cpp",
+ ],
export_include_dirs: ["include"],
- host_supported: true,
- vendor_available: true,
- double_loadable: true,
- min_sdk_version: "29",
header_libs: [
- "libaudioclient_aidl_conversion_util",
- "libaudio_system_headers",
+ "libaudio_aidl_conversion_common_util_cpp",
],
export_header_lib_headers: [
- "libaudioclient_aidl_conversion_util",
- ],
- shared_libs: [
- "android.media.audio.common.types-V1-cpp",
- "audioclient-types-aidl-cpp",
- "libbase",
- "libbinder",
- "liblog",
- "libshmemcompat",
- "libstagefright_foundation",
- "libutils",
- "shared-file-region-aidl-cpp",
- "framework-permission-aidl-cpp",
+ "libaudio_aidl_conversion_common_util_cpp",
],
export_shared_lib_headers: [
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
- "libbase",
- "shared-file-region-aidl-cpp",
+ "av-types-aidl-cpp",
],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-error=deprecated-declarations",
+ defaults: [
+ "audio_aidl_conversion_common_default",
+ "latest_android_media_audio_common_types_cpp_export_shared",
],
- sanitize: {
- misc_undefined: [
- "unsigned-integer-overflow",
- "signed-integer-overflow",
- ],
- },
- target: {
- darwin: {
- enabled: false,
- },
- },
}
// AIDL interface between libaudioclient and framework.jar
@@ -278,6 +226,7 @@
name: "libaudioclient_aidl",
srcs: [
"aidl/android/media/IPlayer.aidl",
+ "aidl/android/media/AudioHalVersion.aidl",
],
path: "aidl",
}
@@ -302,12 +251,26 @@
double_loadable: true,
vendor_available: true,
srcs: [
+ "aidl/android/media/EffectConfig.aidl",
"aidl/android/media/IEffect.aidl",
"aidl/android/media/IEffectClient.aidl",
],
imports: [
+ "android.media.audio.common.types-V2",
"shared-file-region-aidl",
],
+ backend: {
+ cpp: {
+ min_sdk_version: "29",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media",
+ ],
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ },
}
aidl_interface {
@@ -321,16 +284,15 @@
"aidl/android/media/AudioAttributesInternal.aidl",
"aidl/android/media/AudioClient.aidl",
"aidl/android/media/AudioDirectMode.aidl",
- "aidl/android/media/AudioDualMonoMode.aidl",
"aidl/android/media/AudioFlag.aidl",
"aidl/android/media/AudioGainSys.aidl",
+ "aidl/android/media/AudioHalVersion.aidl",
"aidl/android/media/AudioIoConfigEvent.aidl",
"aidl/android/media/AudioIoDescriptor.aidl",
- "aidl/android/media/AudioPatch.aidl",
- "aidl/android/media/AudioPlaybackRate.aidl",
- "aidl/android/media/AudioPort.aidl",
+ "aidl/android/media/AudioPatchFw.aidl",
+ "aidl/android/media/AudioPortFw.aidl",
"aidl/android/media/AudioPortSys.aidl",
- "aidl/android/media/AudioPortConfig.aidl",
+ "aidl/android/media/AudioPortConfigFw.aidl",
"aidl/android/media/AudioPortConfigSys.aidl",
"aidl/android/media/AudioPortDeviceExtSys.aidl",
"aidl/android/media/AudioPortExtSys.aidl",
@@ -342,11 +304,10 @@
"aidl/android/media/AudioUniqueIdUse.aidl",
"aidl/android/media/AudioVibratorInfo.aidl",
"aidl/android/media/EffectDescriptor.aidl",
- "aidl/android/media/LatencyMode.aidl",
"aidl/android/media/TrackSecondaryOutputInfo.aidl",
],
imports: [
- "android.media.audio.common.types-V1",
+ "android.media.audio.common.types-V2",
"framework-permission-aidl",
],
backend: {
@@ -390,7 +351,7 @@
"aidl/android/media/SpatializerHeadTrackingMode.aidl",
],
imports: [
- "android.media.audio.common.types-V1",
+ "android.media.audio.common.types-V2",
"audioclient-types-aidl",
],
backend: {
@@ -433,7 +394,7 @@
"aidl/android/media/IAudioTrackCallback.aidl",
],
imports: [
- "android.media.audio.common.types-V1",
+ "android.media.audio.common.types-V2",
"audioclient-types-aidl",
"av-types-aidl",
"effect-aidl",
@@ -470,7 +431,7 @@
"aidl/android/media/IAudioPolicyServiceClient.aidl",
],
imports: [
- "android.media.audio.common.types-V1",
+ "android.media.audio.common.types-V2",
"audioclient-types-aidl",
"audiopolicy-types-aidl",
"capture_state_listener-aidl",
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index dc21c52..2870c4c 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -89,7 +89,7 @@
return NO_INIT;
}
- if (type == NULL && uuid == NULL) {
+ if (type == nullptr && uuid == nullptr) {
ALOGW("Must specify at least type or uuid");
return BAD_VALUE;
}
@@ -99,8 +99,8 @@
mCallback = callback;
memset(&mDescriptor, 0, sizeof(effect_descriptor_t));
- mDescriptor.type = *(type != NULL ? type : EFFECT_UUID_NULL);
- mDescriptor.uuid = *(uuid != NULL ? uuid : EFFECT_UUID_NULL);
+ mDescriptor.type = *(type != nullptr ? type : EFFECT_UUID_NULL);
+ mDescriptor.uuid = *(uuid != nullptr ? uuid : EFFECT_UUID_NULL);
// TODO b/182392769: use attribution source util
mIEffectClient = new EffectClient(this);
@@ -292,7 +292,7 @@
AudioSystem::releaseAudioSessionId(mSessionId,
VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientAttributionSource.pid)));
}
- if (mIEffect != NULL) {
+ if (mIEffect != nullptr) {
mIEffect->disconnect();
IInterface::asBinder(mIEffect)->unlinkToDeath(mIEffectClient);
}
@@ -370,7 +370,7 @@
if (mEnabled == (cmdCode == EFFECT_CMD_ENABLE)) {
return NO_ERROR;
}
- if (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL) {
+ if (replySize == nullptr || *replySize != sizeof(status_t) || replyData == nullptr) {
return BAD_VALUE;
}
mLock.lock();
@@ -413,7 +413,7 @@
return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
}
- if (param == NULL || param->psize == 0 || param->vsize == 0) {
+ if (param == nullptr || param->psize == 0 || param->vsize == 0) {
return BAD_VALUE;
}
@@ -448,8 +448,7 @@
if (mStatus != NO_ERROR) {
return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
}
-
- if (param == NULL || param->psize == 0 || param->vsize == 0) {
+ if (param == nullptr || param->psize == 0 || param->vsize == 0) {
return BAD_VALUE;
}
@@ -504,8 +503,7 @@
if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
return mStatus;
}
-
- if (param == NULL || param->psize == 0 || param->vsize == 0) {
+ if (param == nullptr || param->psize == 0 || param->vsize == 0) {
return BAD_VALUE;
}
@@ -529,6 +527,36 @@
return status;
}
+status_t AudioEffect::getConfigs(
+ audio_config_base_t *inputCfg, audio_config_base_t *outputCfg)
+{
+ if (mProbe) {
+ return INVALID_OPERATION;
+ }
+ if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
+ return mStatus;
+ }
+ if (inputCfg == NULL || outputCfg == NULL) {
+ return BAD_VALUE;
+ }
+ status_t status;
+ media::EffectConfig cfg;
+ Status bs = mIEffect->getConfig(&cfg, &status);
+ if (!bs.isOk()) {
+ status = statusTFromBinderStatus(bs);
+ ALOGW("%s received status %d from binder transaction", __func__, status);
+ return status;
+ }
+ if (status == NO_ERROR) {
+ *inputCfg = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioConfigBase_audio_config_base_t(
+ cfg.inputCfg, cfg.isOnInputStream));
+ *outputCfg = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioConfigBase_audio_config_base_t(
+ cfg.outputCfg, cfg.isOnInputStream));
+ } else {
+ ALOGW("%s received status %d from the effect", __func__, status);
+ }
+ return status;
+}
// -------------------------------------------------------------------------
@@ -602,6 +630,9 @@
status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
{
+ if (numEffects == nullptr) {
+ return BAD_VALUE;
+ }
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
return af->queryNumberEffects(numEffects);
@@ -609,6 +640,9 @@
status_t AudioEffect::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
{
+ if (descriptor == nullptr) {
+ return BAD_VALUE;
+ }
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
return af->queryEffect(index, descriptor);
@@ -619,6 +653,9 @@
uint32_t preferredTypeFlag,
effect_descriptor_t *descriptor)
{
+ if (uuid == nullptr || type == nullptr || descriptor == nullptr) {
+ return BAD_VALUE;
+ }
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
return af->getEffectDescriptor(uuid, type, preferredTypeFlag, descriptor);
@@ -649,6 +686,9 @@
status_t AudioEffect::newEffectUniqueId(audio_unique_id_t* id)
{
+ if (id == nullptr) {
+ return BAD_VALUE;
+ }
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
*id = af->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
@@ -662,14 +702,15 @@
audio_source_t source,
audio_unique_id_t *id)
{
+ if ((typeStr == nullptr && uuidStr == nullptr) || id == nullptr) {
+ return BAD_VALUE;
+ }
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- if (typeStr == NULL && uuidStr == NULL) return BAD_VALUE;
-
// Convert type & uuid from string to effect_uuid_t.
effect_uuid_t type;
- if (typeStr != NULL) {
+ if (typeStr != nullptr) {
status_t res = stringToGuid(typeStr, &type);
if (res != OK) return res;
} else {
@@ -677,7 +718,7 @@
}
effect_uuid_t uuid;
- if (uuidStr != NULL) {
+ if (uuidStr != nullptr) {
status_t res = stringToGuid(uuidStr, &uuid);
if (res != OK) return res;
} else {
@@ -705,14 +746,15 @@
audio_usage_t usage,
audio_unique_id_t *id)
{
+ if ((typeStr == nullptr && uuidStr == nullptr) || id == nullptr) {
+ return BAD_VALUE;
+ }
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- if (typeStr == NULL && uuidStr == NULL) return BAD_VALUE;
-
// Convert type & uuid from string to effect_uuid_t.
effect_uuid_t type;
- if (typeStr != NULL) {
+ if (typeStr != nullptr) {
status_t res = stringToGuid(typeStr, &type);
if (res != OK) return res;
} else {
@@ -720,7 +762,7 @@
}
effect_uuid_t uuid;
- if (uuidStr != NULL) {
+ if (uuidStr != nullptr) {
status_t res = stringToGuid(uuidStr, &uuid);
if (res != OK) return res;
} else {
@@ -763,7 +805,7 @@
status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
{
- if (str == NULL || guid == NULL) {
+ if (str == nullptr || guid == nullptr) {
return BAD_VALUE;
}
@@ -789,7 +831,7 @@
status_t AudioEffect::guidToString(const effect_uuid_t *guid, char *str, size_t maxLen)
{
- if (guid == NULL || str == NULL) {
+ if (guid == nullptr || str == nullptr) {
return BAD_VALUE;
}
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index c2f7229..4d2b6b1 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -71,6 +71,10 @@
return NO_ERROR;
}
+bool AudioMixMatchCriterion::isExcludeCriterion() const {
+ return mRule & RULE_EXCLUSION_MASK;
+}
+
//
// AudioMix implementation
//
@@ -91,10 +95,11 @@
if (size > MAX_CRITERIA_PER_MIX) {
size = MAX_CRITERIA_PER_MIX;
}
+ mCriteria.reserve(size);
for (size_t i = 0; i < size; i++) {
AudioMixMatchCriterion criterion;
if (criterion.readFromParcel(parcel) == NO_ERROR) {
- mCriteria.add(criterion);
+ mCriteria.push_back(criterion);
}
}
return NO_ERROR;
@@ -135,18 +140,18 @@
return NO_ERROR;
}
-void AudioMix::setExcludeUid(uid_t uid) const {
+void AudioMix::setExcludeUid(uid_t uid) {
AudioMixMatchCriterion crit;
crit.mRule = RULE_EXCLUDE_UID;
crit.mValue.mUid = uid;
- mCriteria.add(crit);
+ mCriteria.push_back(crit);
}
-void AudioMix::setMatchUid(uid_t uid) const {
+void AudioMix::setMatchUid(uid_t uid) {
AudioMixMatchCriterion crit;
crit.mRule = RULE_MATCH_UID;
crit.mValue.mUid = uid;
- mCriteria.add(crit);
+ mCriteria.push_back(crit);
}
bool AudioMix::hasUidRule(bool match, uid_t uid) const {
@@ -169,18 +174,18 @@
return false;
}
-void AudioMix::setExcludeUserId(int userId) const {
+void AudioMix::setExcludeUserId(int userId) {
AudioMixMatchCriterion crit;
crit.mRule = RULE_EXCLUDE_USERID;
crit.mValue.mUserId = userId;
- mCriteria.add(crit);
+ mCriteria.push_back(crit);
}
-void AudioMix::setMatchUserId(int userId) const {
+void AudioMix::setMatchUserId(int userId) {
AudioMixMatchCriterion crit;
crit.mRule = RULE_MATCH_USERID;
crit.mValue.mUserId = userId;
- mCriteria.add(crit);
+ mCriteria.push_back(crit);
}
bool AudioMix::hasUserIdRule(bool match, int userId) const {
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 15203d6..91b54a8 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -146,39 +146,6 @@
audio_channel_mask_t channelMask,
const AttributionSourceState& client,
size_t frameCount,
- legacy_callback_t callback,
- void* user,
- uint32_t notificationFrames,
- audio_session_t sessionId,
- transfer_type transferType,
- audio_input_flags_t flags,
- const audio_attributes_t* pAttributes,
- audio_port_handle_t selectedDeviceId,
- audio_microphone_direction_t selectedMicDirection,
- float microphoneFieldDimension)
- : mActive(false),
- mStatus(NO_INIT),
- mClientAttributionSource(client),
- mSessionId(AUDIO_SESSION_ALLOCATE),
- mPreviousPriority(ANDROID_PRIORITY_NORMAL),
- mPreviousSchedulingGroup(SP_DEFAULT),
- mProxy(NULL)
-{
- uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(mClientAttributionSource.uid));
- pid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientAttributionSource.pid));
- (void)set(inputSource, sampleRate, format, channelMask, frameCount, callback, user,
- notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
- uid, pid, pAttributes, selectedDeviceId, selectedMicDirection,
- microphoneFieldDimension);
-}
-
-AudioRecord::AudioRecord(
- audio_source_t inputSource,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- const AttributionSourceState& client,
- size_t frameCount,
const wp<IAudioRecordCallback>& callback,
uint32_t notificationFrames,
audio_session_t sessionId,
@@ -255,37 +222,6 @@
mDeviceCallback.clear();
}
}
-namespace {
-class LegacyCallbackWrapper : public AudioRecord::IAudioRecordCallback {
- const AudioRecord::legacy_callback_t mCallback;
- void* const mData;
-
- public:
- LegacyCallbackWrapper(AudioRecord::legacy_callback_t callback, void* user)
- : mCallback(callback), mData(user) {}
-
- size_t onMoreData(const AudioRecord::Buffer& buffer) override {
- AudioRecord::Buffer copy = buffer;
- mCallback(AudioRecord::EVENT_MORE_DATA, mData, ©);
- return copy.size();
- }
-
- void onOverrun() override { mCallback(AudioRecord::EVENT_OVERRUN, mData, nullptr); }
-
- void onMarker(uint32_t markerPosition) override {
- mCallback(AudioRecord::EVENT_MARKER, mData, &markerPosition);
- }
-
- void onNewPos(uint32_t newPos) override {
- mCallback(AudioRecord::EVENT_NEW_POS, mData, &newPos);
- }
-
- void onNewIAudioRecord() override {
- mCallback(AudioRecord::EVENT_NEW_IAUDIORECORD, mData, nullptr);
- }
-};
-} // namespace
-
status_t AudioRecord::set(
audio_source_t inputSource,
uint32_t sampleRate,
@@ -479,37 +415,6 @@
return status;
}
-status_t AudioRecord::set(
- audio_source_t inputSource,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- size_t frameCount,
- legacy_callback_t callback,
- void* user,
- uint32_t notificationFrames,
- bool threadCanCallJava,
- audio_session_t sessionId,
- transfer_type transferType,
- audio_input_flags_t flags,
- uid_t uid,
- pid_t pid,
- const audio_attributes_t* pAttributes,
- audio_port_handle_t selectedDeviceId,
- audio_microphone_direction_t selectedMicDirection,
- float microphoneFieldDimension,
- int32_t maxSharedAudioHistoryMs)
-{
- if (callback != nullptr) {
- mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
- } else if (user) {
- LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
- }
- return set(inputSource, sampleRate, format, channelMask, frameCount, mLegacyCallbackWrapper,
- notificationFrames, threadCanCallJava, sessionId, transferType, flags, uid, pid,
- pAttributes, selectedDeviceId, selectedMicDirection, microphoneFieldDimension,
- maxSharedAudioHistoryMs);
-}
// -------------------------------------------------------------------------
status_t AudioRecord::start(AudioSystem::sync_event_t event, audio_session_t triggerSession)
@@ -1712,16 +1617,10 @@
// -------------------------------------------------------------------------
-status_t AudioRecord::getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
+status_t AudioRecord::getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones)
{
AutoMutex lock(mLock);
- std::vector<media::MicrophoneInfoData> mics;
- status_t status = statusTFromBinderStatus(mAudioRecord->getActiveMicrophones(&mics));
- activeMicrophones->resize(mics.size());
- for (size_t i = 0; status == OK && i < mics.size(); ++i) {
- status = activeMicrophones->at(i).readFromParcelable(mics[i]);
- }
- return status;
+ return statusTFromBinderStatus(mAudioRecord->getActiveMicrophones(activeMicrophones));
}
status_t AudioRecord::setPreferredMicrophoneDirection(audio_microphone_direction_t direction)
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index bacca3a..6ffbdc4 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -671,12 +671,12 @@
}
Status AudioSystem::AudioFlingerClient::onSupportedLatencyModesChanged(
- int output, const std::vector<media::LatencyMode>& latencyModes) {
+ int output, const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_io_handle_t(output));
std::vector<audio_latency_mode_t> modesLegacy = VALUE_OR_RETURN_BINDER_STATUS(
convertContainer<std::vector<audio_latency_mode_t>>(
- latencyModes, aidl2legacy_LatencyMode_audio_latency_mode_t));
+ latencyModes, aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
std::vector<sp<SupportedLatencyModesCallback>> callbacks;
{
@@ -1532,7 +1532,7 @@
legacy2aidl_audio_port_type_t_AudioPortType(type));
Int numPortsAidl;
numPortsAidl.value = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(*num_ports));
- std::vector<media::AudioPort> portsAidl;
+ std::vector<media::AudioPortFw> portsAidl;
int32_t generationAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -1540,7 +1540,7 @@
*num_ports = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(numPortsAidl.value));
*generation = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(generationAidl));
RETURN_STATUS_IF_ERROR(convertRange(portsAidl.begin(), portsAidl.end(), ports,
- aidl2legacy_AudioPort_audio_port_v7));
+ aidl2legacy_AudioPortFw_audio_port_v7));
return OK;
}
@@ -1551,10 +1551,10 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioPort portAidl;
+ media::AudioPortFw portAidl;
RETURN_STATUS_IF_ERROR(
statusTFromBinderStatus(aps->getAudioPort(port->id, &portAidl)));
- *port = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPort_audio_port_v7(portAidl));
+ *port = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPortFw_audio_port_v7(portAidl));
return OK;
}
@@ -1567,8 +1567,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioPatch patchAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_patch_AudioPatch(*patch));
+ media::AudioPatchFw patchAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_patch_AudioPatchFw(*patch));
int32_t handleAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_patch_handle_t_int32_t(*handle));
RETURN_STATUS_IF_ERROR(
statusTFromBinderStatus(aps->createAudioPatch(patchAidl, handleAidl, &handleAidl)));
@@ -1598,7 +1598,7 @@
Int numPatchesAidl;
numPatchesAidl.value = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(*num_patches));
- std::vector<media::AudioPatch> patchesAidl;
+ std::vector<media::AudioPatchFw> patchesAidl;
int32_t generationAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -1606,7 +1606,7 @@
*num_patches = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(numPatchesAidl.value));
*generation = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(generationAidl));
RETURN_STATUS_IF_ERROR(convertRange(patchesAidl.begin(), patchesAidl.end(), patches,
- aidl2legacy_AudioPatch_audio_patch));
+ aidl2legacy_AudioPatchFw_audio_patch));
return OK;
}
@@ -1618,8 +1618,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioPortConfig configAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_port_config_AudioPortConfig(*config));
+ media::AudioPortConfigFw configAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_port_config_AudioPortConfigFw(*config));
return statusTFromBinderStatus(aps->setAudioPortConfig(configAidl));
}
@@ -1839,8 +1839,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioPortConfig sourceAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_port_config_AudioPortConfig(*source));
+ media::AudioPortConfigFw sourceAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_port_config_AudioPortConfigFw(*source));
media::AudioAttributesInternal attributesAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attributes));
int32_t portIdAidl;
@@ -1904,7 +1904,7 @@
return result.value_or(NAN);
}
-status_t AudioSystem::getMicrophones(std::vector<media::MicrophoneInfo>* microphones) {
+status_t AudioSystem::getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
return af->getMicrophones(microphones);
@@ -2339,6 +2339,9 @@
const AudioDeviceTypeAddrVector &devices,
bool *canBeSpatialized) {
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (canBeSpatialized == nullptr) {
+ return BAD_VALUE;
+ }
if (aps == 0) {
return PERMISSION_DENIED;
}
@@ -2384,7 +2387,7 @@
status_t AudioSystem::getDirectProfilesForAttributes(const audio_attributes_t* attr,
std::vector<audio_profile>* audioProfiles) {
- if (attr == nullptr) {
+ if (attr == nullptr || audioProfiles == nullptr) {
return BAD_VALUE;
}
@@ -2423,6 +2426,32 @@
return af->getSupportedLatencyModes(output, modes);
}
+status_t AudioSystem::setBluetoothVariableLatencyEnabled(bool enabled) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == nullptr) {
+ return PERMISSION_DENIED;
+ }
+ return af->setBluetoothVariableLatencyEnabled(enabled);
+}
+
+status_t AudioSystem::isBluetoothVariableLatencyEnabled(
+ bool *enabled) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == nullptr) {
+ return PERMISSION_DENIED;
+ }
+ return af->isBluetoothVariableLatencyEnabled(enabled);
+}
+
+status_t AudioSystem::supportsBluetoothVariableLatency(
+ bool *support) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == nullptr) {
+ return PERMISSION_DENIED;
+ }
+ return af->supportsBluetoothVariableLatency(support);
+}
+
class CaptureStateListenerImpl : public media::BnCaptureStateListener,
public IBinder::DeathRecipient {
public:
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 6ab8339..ff4b071 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -325,45 +325,6 @@
}
};
}
-
-AudioTrack::AudioTrack(
- audio_stream_type_t streamType,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- size_t frameCount,
- audio_output_flags_t flags,
- legacy_callback_t callback,
- void* user,
- int32_t notificationFrames,
- audio_session_t sessionId,
- transfer_type transferType,
- const audio_offload_info_t *offloadInfo,
- const AttributionSourceState& attributionSource,
- const audio_attributes_t* pAttributes,
- bool doNotReconnect,
- float maxRequiredSpeed,
- audio_port_handle_t selectedDeviceId)
- : mStatus(NO_INIT),
- mState(STATE_STOPPED),
- mPreviousPriority(ANDROID_PRIORITY_NORMAL),
- mPreviousSchedulingGroup(SP_DEFAULT),
- mPausedPosition(0),
- mAudioTrackCallback(new AudioTrackCallback())
-{
- mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
- if (callback != nullptr) {
- mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
- } else if (user) {
- LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
- }
- mSetParams = std::unique_ptr<SetParams>{new SetParams{
- streamType, sampleRate, format, channelMask, frameCount, flags, mLegacyCallbackWrapper,
- notificationFrames, 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId,
- transferType, offloadInfo, attributionSource, pAttributes, doNotReconnect,
- maxRequiredSpeed, selectedDeviceId}};
-}
-
AudioTrack::AudioTrack(
audio_stream_type_t streamType,
uint32_t sampleRate,
@@ -397,44 +358,6 @@
doNotReconnect, maxRequiredSpeed, AUDIO_PORT_HANDLE_NONE}};
}
-AudioTrack::AudioTrack(
- audio_stream_type_t streamType,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- const sp<IMemory>& sharedBuffer,
- audio_output_flags_t flags,
- legacy_callback_t callback,
- void* user,
- int32_t notificationFrames,
- audio_session_t sessionId,
- transfer_type transferType,
- const audio_offload_info_t *offloadInfo,
- const AttributionSourceState& attributionSource,
- const audio_attributes_t* pAttributes,
- bool doNotReconnect,
- float maxRequiredSpeed)
- : mStatus(NO_INIT),
- mState(STATE_STOPPED),
- mPreviousPriority(ANDROID_PRIORITY_NORMAL),
- mPreviousSchedulingGroup(SP_DEFAULT),
- mPausedPosition(0),
- mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
- mAudioTrackCallback(new AudioTrackCallback())
-{
- mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
- if (callback) {
- mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
- } else if (user) {
- LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
- }
- mSetParams = std::unique_ptr<SetParams>{new SetParams{
- streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags,
- mLegacyCallbackWrapper, notificationFrames, sharedBuffer, false /*threadCanCallJava*/,
- sessionId, transferType, offloadInfo, attributionSource, pAttributes, doNotReconnect,
- maxRequiredSpeed, AUDIO_PORT_HANDLE_NONE}};
-}
-
void AudioTrack::onFirstRef() {
if (mSetParams) {
set(*mSetParams);
@@ -496,38 +419,6 @@
mDeviceCallback.clear();
}
}
-
-status_t AudioTrack::set(
- audio_stream_type_t streamType,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- size_t frameCount,
- audio_output_flags_t flags,
- legacy_callback_t callback,
- void * user,
- int32_t notificationFrames,
- const sp<IMemory>& sharedBuffer,
- bool threadCanCallJava,
- audio_session_t sessionId,
- transfer_type transferType,
- const audio_offload_info_t *offloadInfo,
- const AttributionSourceState& attributionSource,
- const audio_attributes_t* pAttributes,
- bool doNotReconnect,
- float maxRequiredSpeed,
- audio_port_handle_t selectedDeviceId)
-{
- if (callback) {
- mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
- } else if (user) {
- LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
- }
- return set(streamType, sampleRate,format, channelMask, frameCount, flags,
- mLegacyCallbackWrapper, notificationFrames, sharedBuffer, threadCanCallJava,
- sessionId, transferType, offloadInfo, attributionSource, pAttributes,
- doNotReconnect, maxRequiredSpeed, selectedDeviceId);
-}
status_t AudioTrack::set(
audio_stream_type_t streamType,
uint32_t sampleRate,
@@ -559,7 +450,7 @@
std::string errorMessage;
// Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
ALOGV("%s(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
- "flags #%x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d",
+ "flags %#x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d",
__func__,
streamType, sampleRate, format, channelMask, frameCount, flags, notificationFrames,
sessionId, transferType, attributionSource.uid, attributionSource.pid);
@@ -1357,7 +1248,7 @@
status_t AudioTrack::getDualMonoMode(audio_dual_mono_mode_t* mode) const
{
AutoMutex lock(mLock);
- media::AudioDualMonoMode mediaMode;
+ media::audio::common::AudioDualMonoMode mediaMode;
const status_t status = statusTFromBinderStatus(mAudioTrack->getDualMonoMode(&mediaMode));
if (status == NO_ERROR) {
*mode = VALUE_OR_RETURN_STATUS(
@@ -1398,6 +1289,10 @@
legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(playbackRate))));
if (status == NO_ERROR) {
mPlaybackRate = playbackRate;
+ } else if (status == INVALID_OPERATION
+ && playbackRate.mSpeed == 1.0f && mPlaybackRate.mPitch == 1.0f) {
+ mPlaybackRate = playbackRate;
+ return NO_ERROR;
}
return status;
}
@@ -1468,7 +1363,7 @@
{
AutoMutex lock(mLock);
if (isOffloadedOrDirect_l()) {
- media::AudioPlaybackRate playbackRateTemp;
+ media::audio::common::AudioPlaybackRate playbackRateTemp;
const status_t status = statusTFromBinderStatus(
mAudioTrack->getPlaybackRateParameters(&playbackRateTemp));
if (status == NO_ERROR) { // update local version if changed.
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index f290453..a005ab4 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -666,17 +666,19 @@
}
status_t AudioFlingerClientAdapter::getAudioPort(struct audio_port_v7* port) {
- media::AudioPort portAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_v7_AudioPort(*port));
- media::AudioPort aidlRet;
+ media::AudioPortFw portAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_port_v7_AudioPortFw(*port));
+ media::AudioPortFw aidlRet;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
mDelegate->getAudioPort(portAidl, &aidlRet)));
- *port = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPort_audio_port_v7(aidlRet));
+ *port = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPortFw_audio_port_v7(aidlRet));
return OK;
}
status_t AudioFlingerClientAdapter::createAudioPatch(const struct audio_patch* patch,
audio_patch_handle_t* handle) {
- media::AudioPatch patchAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_patch_AudioPatch(*patch));
+ media::AudioPatchFw patchAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_patch_AudioPatchFw(*patch));
int32_t aidlRet = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_patch_handle_t_int32_t(
AUDIO_PATCH_HANDLE_NONE));
if (handle != nullptr) {
@@ -697,18 +699,18 @@
status_t AudioFlingerClientAdapter::listAudioPatches(unsigned int* num_patches,
struct audio_patch* patches) {
- std::vector<media::AudioPatch> aidlRet;
+ std::vector<media::AudioPatchFw> aidlRet;
int32_t maxPatches = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(*num_patches));
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
mDelegate->listAudioPatches(maxPatches, &aidlRet)));
*num_patches = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(aidlRet.size()));
return convertRange(aidlRet.begin(), aidlRet.end(), patches,
- aidl2legacy_AudioPatch_audio_patch);
+ aidl2legacy_AudioPatchFw_audio_patch);
}
status_t AudioFlingerClientAdapter::setAudioPortConfig(const struct audio_port_config* config) {
- media::AudioPortConfig configAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_port_config_AudioPortConfig(*config));
+ media::AudioPortConfigFw configAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_port_config_AudioPortConfigFw(*config));
return statusTFromBinderStatus(mDelegate->setAudioPortConfig(configAidl));
}
@@ -744,14 +746,11 @@
}
status_t
-AudioFlingerClientAdapter::getMicrophones(std::vector<media::MicrophoneInfo>* microphones) {
- std::vector<media::MicrophoneInfoData> aidlRet;
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
- mDelegate->getMicrophones(&aidlRet)));
+AudioFlingerClientAdapter::getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) {
+ std::vector<media::MicrophoneInfoFw> aidlRet;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mDelegate->getMicrophones(&aidlRet)));
if (microphones != nullptr) {
- *microphones = VALUE_OR_RETURN_STATUS(
- convertContainer<std::vector<media::MicrophoneInfo>>(aidlRet,
- media::aidl2legacy_MicrophoneInfo));
+ *microphones = std::move(aidlRet);
}
return OK;
}
@@ -805,16 +804,16 @@
status_t AudioFlingerClientAdapter::setDeviceConnectedState(
const struct audio_port_v7 *port, bool connected) {
- media::AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_port_v7_AudioPort(*port));
+ media::AudioPortFw aidlPort = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_port_v7_AudioPortFw(*port));
return statusTFromBinderStatus(mDelegate->setDeviceConnectedState(aidlPort, connected));
}
status_t AudioFlingerClientAdapter::setRequestedLatencyMode(
audio_io_handle_t output, audio_latency_mode_t mode) {
int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
- media::LatencyMode modeAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_latency_mode_t_LatencyMode(mode));
+ media::audio::common::AudioLatencyMode modeAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode));
return statusTFromBinderStatus(mDelegate->setRequestedLatencyMode(outputAidl, modeAidl));
}
@@ -825,14 +824,40 @@
}
int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
- std::vector<media::LatencyMode> modesAidl;
+ std::vector<media::audio::common::AudioLatencyMode> modesAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
mDelegate->getSupportedLatencyModes(outputAidl, &modesAidl)));
*modes = VALUE_OR_RETURN_STATUS(
convertContainer<std::vector<audio_latency_mode_t>>(modesAidl,
- aidl2legacy_LatencyMode_audio_latency_mode_t));
+ aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
+
+ return NO_ERROR;
+}
+
+status_t AudioFlingerClientAdapter::setBluetoothVariableLatencyEnabled(bool enabled) {
+ return statusTFromBinderStatus(mDelegate->setBluetoothVariableLatencyEnabled(enabled));
+}
+
+status_t AudioFlingerClientAdapter::isBluetoothVariableLatencyEnabled(bool* enabled) {
+ if (enabled == nullptr) {
+ return BAD_VALUE;
+ }
+
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->isBluetoothVariableLatencyEnabled(enabled)));
+
+ return NO_ERROR;
+}
+
+status_t AudioFlingerClientAdapter::supportsBluetoothVariableLatency(bool* support) {
+ if (support == nullptr) {
+ return BAD_VALUE;
+ }
+
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->supportsBluetoothVariableLatency(support)));
return NO_ERROR;
}
@@ -1211,17 +1236,17 @@
return Status::fromStatusT(mDelegate->setLowRamDevice(isLowRamDevice, totalMemory));
}
-Status AudioFlingerServerAdapter::getAudioPort(const media::AudioPort& port,
- media::AudioPort* _aidl_return) {
- audio_port_v7 portLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPort_audio_port_v7(port));
+Status AudioFlingerServerAdapter::getAudioPort(const media::AudioPortFw& port,
+ media::AudioPortFw* _aidl_return) {
+ audio_port_v7 portLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPortFw_audio_port_v7(port));
RETURN_BINDER_IF_ERROR(mDelegate->getAudioPort(&portLegacy));
- *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_port_v7_AudioPort(portLegacy));
+ *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_port_v7_AudioPortFw(portLegacy));
return Status::ok();
}
-Status AudioFlingerServerAdapter::createAudioPatch(const media::AudioPatch& patch,
+Status AudioFlingerServerAdapter::createAudioPatch(const media::AudioPatchFw& patch,
int32_t* _aidl_return) {
- audio_patch patchLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPatch_audio_patch(patch));
+ audio_patch patchLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPatchFw_audio_patch(patch));
audio_patch_handle_t handleLegacy = VALUE_OR_RETURN_BINDER(
aidl2legacy_int32_t_audio_patch_handle_t(*_aidl_return));
RETURN_BINDER_IF_ERROR(mDelegate->createAudioPatch(&patchLegacy, &handleLegacy));
@@ -1236,7 +1261,7 @@
}
Status AudioFlingerServerAdapter::listAudioPatches(int32_t maxCount,
- std::vector<media::AudioPatch>* _aidl_return) {
+ std::vector<media::AudioPatchFw>* _aidl_return) {
unsigned int count = VALUE_OR_RETURN_BINDER(convertIntegral<unsigned int>(maxCount));
count = std::min(count, static_cast<unsigned int>(MAX_ITEMS_PER_LIST));
std::unique_ptr<audio_patch[]> patchesLegacy(new audio_patch[count]);
@@ -1244,13 +1269,13 @@
RETURN_BINDER_IF_ERROR(convertRange(&patchesLegacy[0],
&patchesLegacy[count],
std::back_inserter(*_aidl_return),
- legacy2aidl_audio_patch_AudioPatch));
+ legacy2aidl_audio_patch_AudioPatchFw));
return Status::ok();
}
-Status AudioFlingerServerAdapter::setAudioPortConfig(const media::AudioPortConfig& config) {
+Status AudioFlingerServerAdapter::setAudioPortConfig(const media::AudioPortConfigFw& config) {
audio_port_config configLegacy = VALUE_OR_RETURN_BINDER(
- aidl2legacy_AudioPortConfig_audio_port_config(config));
+ aidl2legacy_AudioPortConfigFw_audio_port_config(config));
return Status::fromStatusT(mDelegate->setAudioPortConfig(&configLegacy));
}
@@ -1281,11 +1306,8 @@
}
Status AudioFlingerServerAdapter::getMicrophones(
- std::vector<media::MicrophoneInfoData>* _aidl_return) {
- std::vector<media::MicrophoneInfo> resultLegacy;
- RETURN_BINDER_IF_ERROR(mDelegate->getMicrophones(&resultLegacy));
- *_aidl_return = VALUE_OR_RETURN_BINDER(convertContainer<std::vector<media::MicrophoneInfoData>>(
- resultLegacy, media::legacy2aidl_MicrophoneInfo));
+ std::vector<media::MicrophoneInfoFw>* _aidl_return) {
+ RETURN_BINDER_IF_ERROR(mDelegate->getMicrophones(_aidl_return));
return Status::ok();
}
@@ -1328,23 +1350,23 @@
}
Status AudioFlingerServerAdapter::setDeviceConnectedState(
- const media::AudioPort& port, bool connected) {
- audio_port_v7 portLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPort_audio_port_v7(port));
+ const media::AudioPortFw& port, bool connected) {
+ audio_port_v7 portLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPortFw_audio_port_v7(port));
return Status::fromStatusT(mDelegate->setDeviceConnectedState(&portLegacy, connected));
}
Status AudioFlingerServerAdapter::setRequestedLatencyMode(
- int32_t output, media::LatencyMode modeAidl) {
+ int32_t output, media::audio::common::AudioLatencyMode modeAidl) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
aidl2legacy_int32_t_audio_io_handle_t(output));
audio_latency_mode_t modeLegacy = VALUE_OR_RETURN_BINDER(
- aidl2legacy_LatencyMode_audio_latency_mode_t(modeAidl));
+ aidl2legacy_AudioLatencyMode_audio_latency_mode_t(modeAidl));
return Status::fromStatusT(mDelegate->setRequestedLatencyMode(
outputLegacy, modeLegacy));
}
Status AudioFlingerServerAdapter::getSupportedLatencyModes(
- int output, std::vector<media::LatencyMode>* _aidl_return) {
+ int output, std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
aidl2legacy_int32_t_audio_io_handle_t(output));
std::vector<audio_latency_mode_t> modesLegacy;
@@ -1352,9 +1374,21 @@
RETURN_BINDER_IF_ERROR(mDelegate->getSupportedLatencyModes(outputLegacy, &modesLegacy));
*_aidl_return = VALUE_OR_RETURN_BINDER(
- convertContainer<std::vector<media::LatencyMode>>(
- modesLegacy, legacy2aidl_audio_latency_mode_t_LatencyMode));
+ convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+ modesLegacy, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
return Status::ok();
}
+Status AudioFlingerServerAdapter::setBluetoothVariableLatencyEnabled(bool enabled) {
+ return Status::fromStatusT(mDelegate->setBluetoothVariableLatencyEnabled(enabled));
+}
+
+Status AudioFlingerServerAdapter::isBluetoothVariableLatencyEnabled(bool *enabled) {
+ return Status::fromStatusT(mDelegate->isBluetoothVariableLatencyEnabled(enabled));
+}
+
+Status AudioFlingerServerAdapter::supportsBluetoothVariableLatency(bool *support) {
+ return Status::fromStatusT(mDelegate->supportsBluetoothVariableLatency(support));
+}
+
} // namespace android
diff --git a/media/libaudioclient/TEST_MAPPING b/media/libaudioclient/TEST_MAPPING
index 3751f80..10f9d9b 100644
--- a/media/libaudioclient/TEST_MAPPING
+++ b/media/libaudioclient/TEST_MAPPING
@@ -4,12 +4,38 @@
"name": "audio_aidl_conversion_tests"
},
{
+ "name": "audio_aidl_status_tests"
+ },
+ {
"name": "CtsNativeMediaAAudioTestCases",
"options" : [
{
"include-filter": "android.nativemedia.aaudio.AAudioTests#AAudioBasic.*"
}
]
+ },
+ {
+ "name": "audiorecord_tests"
+ },
+ {
+ "name": "audioeffect_tests"
+ },
+ {
+ "name": "audiorouting_tests"
+ },
+ {
+ "name": "audioclient_serialization_tests"
+ },
+ {
+ "name": "trackplayerbase_tests"
+ },
+ {
+ "name": "audiosystem_tests"
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "audioeffect_analysis"
}
]
}
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index f968a4b..f0b4d11 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -1027,7 +1027,7 @@
if (property_get("gsm.operator.iso-country", value, "") == 0) {
property_get("gsm.sim.operator.iso-country", value, "");
}
- // If dual sim device has two SIM cards inserted and is not registerd to any network,
+ // If dual sim device has two SIM cards inserted and is not registered to any network,
// "," is set to "gsm.operator.iso-country" prop.
// In this case, "gsm.sim.operator.iso-country" prop should be used.
if (strlen(value) == 1 && strstr(value, ",") != NULL) {
diff --git a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl b/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
deleted file mode 100644
index f6220c2..0000000
--- a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-package android.media;
-
-// TODO(b/175167149): Reconcile AudioDualMonoMode with framework-media-sources
-
-@Backing(type="int")
-enum AudioDualMonoMode {
- OFF = 0,
- LR = 1,
- LL = 2,
- RR = 3,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioHalVersion.aidl b/media/libaudioclient/aidl/android/media/AudioHalVersion.aidl
new file mode 100644
index 0000000..49048040
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioHalVersion.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package android.media;
+
+/**
+ * The audio HAL version definition.
+ *
+ * {@hide}
+ */
+parcelable AudioHalVersion {
+
+ @Backing(type="int")
+ enum Type {
+ /**
+ * Indicate the audio HAL is implemented with HIDL (HAL interface definition language).
+ * @see <a href="https://source.android.com/docs/core/architecture/hidl/">HIDL</a>
+ */
+ HIDL = 0,
+
+ /**
+ * Indicate the audio HAL is implemented with AIDL (Android Interface Definition Language).
+ * @see <a href="https://source.android.com/docs/core/architecture/aidl/">AIDL</a>
+ */
+ AIDL
+ }
+
+ Type type = Type.HIDL;
+
+ /**
+ * Major version number.
+ */
+ int major;
+
+ /**
+ * Minor version number.
+ */
+ int minor;
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioIoDescriptor.aidl b/media/libaudioclient/aidl/android/media/AudioIoDescriptor.aidl
index b01f902..5dd898c 100644
--- a/media/libaudioclient/aidl/android/media/AudioIoDescriptor.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioIoDescriptor.aidl
@@ -16,7 +16,7 @@
package android.media;
-import android.media.AudioPatch;
+import android.media.AudioPatchFw;
import android.media.audio.common.AudioChannelLayout;
import android.media.audio.common.AudioFormatDescription;
@@ -26,7 +26,7 @@
parcelable AudioIoDescriptor {
/** Interpreted as audio_io_handle_t. */
int ioHandle;
- AudioPatch patch;
+ AudioPatchFw patch;
boolean isInput;
int samplingRate;
AudioFormatDescription format;
diff --git a/media/libaudioclient/aidl/android/media/AudioPatch.aidl b/media/libaudioclient/aidl/android/media/AudioPatchFw.aidl
similarity index 74%
rename from media/libaudioclient/aidl/android/media/AudioPatch.aidl
rename to media/libaudioclient/aidl/android/media/AudioPatchFw.aidl
index 8519faf..9ec3fa9 100644
--- a/media/libaudioclient/aidl/android/media/AudioPatch.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPatchFw.aidl
@@ -16,17 +16,19 @@
package android.media;
-import android.media.AudioPortConfig;
+import android.media.AudioPortConfigFw;
/**
* {@hide}
+ * The Fw suffix is used to break a namespace collision with an SDK API.
+ * It contains the framework version of AudioPortConfig.
*/
-parcelable AudioPatch {
+parcelable AudioPatchFw {
/**
* Patch unique ID.
* Interpreted as audio_patch_handle_t.
*/
int id;
- AudioPortConfig[] sources;
- AudioPortConfig[] sinks;
+ AudioPortConfigFw[] sources;
+ AudioPortConfigFw[] sinks;
}
diff --git a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl b/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
deleted file mode 100644
index e29d398..0000000
--- a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-package android.media;
-
-/**
- * The AudioPlaybackRate.
- *
- * See https://developer.android.com/reference/android/media/PlaybackParams.
- * TODO(b/175166815): Reconcile with framework-media-sources PlaybackParams.aidl.
- * As this is used for native wire serialization, no need to define
- * audio_timestretch_stretch_mode_t and audio_timestretch_fallback_mode_t enums
- * until we attempt to unify with PlaybackParams.
- *
- * {@hide}
- */
-parcelable AudioPlaybackRate {
- /** Speed of audio playback, >= 0.f, 1.f nominal (system limits are further restrictive) */
- float speed;
- /** Pitch of audio, >= 0.f, 1.f nominal (system limits are further restrictive) */
- float pitch;
- /** Interpreted as audio_timestretch_stretch_mode_t */
- int stretchMode;
- /** Interpreted as audio_timestretch_fallback_mode_t */
- int fallbackMode;
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioPortConfig.aidl b/media/libaudioclient/aidl/android/media/AudioPortConfigFw.aidl
similarity index 89%
rename from media/libaudioclient/aidl/android/media/AudioPortConfig.aidl
rename to media/libaudioclient/aidl/android/media/AudioPortConfigFw.aidl
index 3a4ca31..e7565d7 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortConfig.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortConfigFw.aidl
@@ -21,8 +21,9 @@
/**
* {@hide}
+ * Suffixed with Fw to avoid name conflict with SDK class.
*/
-parcelable AudioPortConfig {
+parcelable AudioPortConfigFw {
AudioPortConfig hal;
AudioPortConfigSys sys;
}
diff --git a/media/libaudioclient/aidl/android/media/AudioPortDeviceExtSys.aidl b/media/libaudioclient/aidl/android/media/AudioPortDeviceExtSys.aidl
index 0f5a9b6..24ec230 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortDeviceExtSys.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortDeviceExtSys.aidl
@@ -22,8 +22,4 @@
parcelable AudioPortDeviceExtSys {
/** Module the device is attached to. Interpreted as audio_module_handle_t. */
int hwModule;
- /** Bitmask, indexed by AudioEncapsulationMode. */
- int encapsulationModes;
- /** Bitmask, indexed by AudioEncapsulationMetadataType. */
- int encapsulationMetadataTypes;
}
diff --git a/media/libaudioclient/aidl/android/media/AudioPortExtSys.aidl b/media/libaudioclient/aidl/android/media/AudioPortExtSys.aidl
index 2cdf4f6..d9c6df4 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortExtSys.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortExtSys.aidl
@@ -31,4 +31,6 @@
AudioPortDeviceExtSys device;
/** System-only parameters when the port is an audio mix. */
AudioPortMixExtSys mix;
+ /** Framework audio session identifier. */
+ int session;
}
diff --git a/media/libaudioclient/aidl/android/media/AudioPort.aidl b/media/libaudioclient/aidl/android/media/AudioPortFw.aidl
similarity index 88%
rename from media/libaudioclient/aidl/android/media/AudioPort.aidl
rename to media/libaudioclient/aidl/android/media/AudioPortFw.aidl
index ff177c0..5580e35 100644
--- a/media/libaudioclient/aidl/android/media/AudioPort.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortFw.aidl
@@ -21,8 +21,9 @@
/**
* {@hide}
+ * The Fw suffix is used to break a namespace collision with an SDK API.
*/
-parcelable AudioPort {
+parcelable AudioPortFw {
AudioPort hal;
AudioPortSys sys;
}
diff --git a/media/libaudioclient/aidl/android/media/AudioPortSys.aidl b/media/libaudioclient/aidl/android/media/AudioPortSys.aidl
index f3b5c19..756c469 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortSys.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortSys.aidl
@@ -17,7 +17,7 @@
package android.media;
import android.media.AudioGainSys;
-import android.media.AudioPortConfig;
+import android.media.AudioPortConfigFw;
import android.media.AudioPortExtSys;
import android.media.AudioPortRole;
import android.media.AudioPortType;
@@ -36,7 +36,7 @@
/** System-only parameters for each AudioGain from 'port.gains'. */
AudioGainSys[] gains;
/** Current audio port configuration. */
- AudioPortConfig activeConfig;
+ AudioPortConfigFw activeConfig;
/** System-only extra parameters for 'port.ext'. */
AudioPortExtSys ext;
}
diff --git a/media/libaudioclient/aidl/android/media/EffectConfig.aidl b/media/libaudioclient/aidl/android/media/EffectConfig.aidl
new file mode 100644
index 0000000..5f62b73
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/EffectConfig.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package android.media;
+
+import android.media.audio.common.AudioConfigBase;
+
+/**
+ * Describes configuration of an audio effect. Input and output
+ * audio configurations are described separately because the effect
+ * can perform transformations on channel layouts, for example.
+ *
+ * {@hide}
+ */
+parcelable EffectConfig {
+ /** Configuration of the audio input of the effect. */
+ AudioConfigBase inputCfg;
+ /** Configuration of the audio output of the effect. */
+ AudioConfigBase outputCfg;
+ /**
+ * Specifies whether the effect is instantiated on an input stream,
+ * e.g. on the input from a microphone.
+ */
+ boolean isOnInputStream;
+}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
index a2bb024..f055cc4 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
@@ -18,7 +18,7 @@
import android.media.AudioIoConfigEvent;
import android.media.AudioIoDescriptor;
-import android.media.LatencyMode;
+import android.media.audio.common.AudioLatencyMode;
/**
* A callback interface for AudioFlinger.
@@ -31,7 +31,8 @@
/**
* Called when the latency modes supported on a given output stream change.
* output is the I/O handle of the output stream for which the change is signalled.
- * latencyModes is the new list of supported latency modes (See LatencyMode.aidl).
+ * latencyModes is the new list of supported latency modes (See AudioLatencyMode.aidl).
*/
- oneway void onSupportedLatencyModesChanged(int output, in LatencyMode[] latencyModes);
+ oneway void onSupportedLatencyModesChanged(
+ int output, in AudioLatencyMode[] latencyModes);
}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 9b8a843..7c44c74 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -16,9 +16,9 @@
package android.media;
-import android.media.AudioPatch;
-import android.media.AudioPort;
-import android.media.AudioPortConfig;
+import android.media.AudioPatchFw;
+import android.media.AudioPortFw;
+import android.media.AudioPortConfigFw;
import android.media.AudioUniqueIdUse;
import android.media.AudioVibratorInfo;
import android.media.CreateEffectRequest;
@@ -35,12 +35,12 @@
import android.media.IAudioFlingerClient;
import android.media.IAudioRecord;
import android.media.IAudioTrack;
-import android.media.LatencyMode;
-import android.media.MicrophoneInfoData;
+import android.media.MicrophoneInfoFw;
import android.media.RenderPosition;
import android.media.TrackSecondaryOutputInfo;
import android.media.audio.common.AudioChannelLayout;
import android.media.audio.common.AudioFormatDescription;
+import android.media.audio.common.AudioLatencyMode;
import android.media.audio.common.AudioMMapPolicyInfo;
import android.media.audio.common.AudioMMapPolicyType;
import android.media.audio.common.AudioMode;
@@ -182,18 +182,18 @@
void setLowRamDevice(boolean isLowRamDevice, long totalMemory);
/* Get attributes for a given audio port */
- AudioPort getAudioPort(in AudioPort port);
+ AudioPortFw getAudioPort(in AudioPortFw port);
/* Create an audio patch between several source and sink ports */
- int /* audio_patch_handle_t */ createAudioPatch(in AudioPatch patch);
+ int /* audio_patch_handle_t */ createAudioPatch(in AudioPatchFw patch);
/* Release an audio patch */
void releaseAudioPatch(int /* audio_patch_handle_t */ handle);
/* List existing audio patches */
- AudioPatch[] listAudioPatches(int maxCount);
+ AudioPatchFw[] listAudioPatches(int maxCount);
/* Set audio port configuration */
- void setAudioPortConfig(in AudioPortConfig config);
+ void setAudioPortConfig(in AudioPortConfigFw config);
/* Get the HW synchronization source used for an audio session */
int /* audio_hw_sync_t */ getAudioHwSyncForSession(int /* audio_session_t */ sessionId);
@@ -208,7 +208,7 @@
long frameCountHAL(int /* audio_io_handle_t */ ioHandle);
/* List available microphones and their characteristics */
- MicrophoneInfoData[] getMicrophones();
+ MicrophoneInfoFw[] getMicrophones();
void setAudioHalPids(in int[] /* pid_t[] */ pids);
@@ -227,24 +227,44 @@
int getAAudioHardwareBurstMinUsec();
- void setDeviceConnectedState(in AudioPort devicePort, boolean connected);
+ void setDeviceConnectedState(in AudioPortFw devicePort, boolean connected);
/**
- * Requests a given latency mode (See LatencyMode.aidl) on an output stream.
+ * Requests a given latency mode (See AudioLatencyMode.aidl) on an output stream.
* This can be used when some use case on a given mixer/stream can only be enabled
* if a specific latency mode is selected on the audio path below the HAL.
* For instance spatial audio with head tracking.
* output is the I/O handle of the output stream for which the request is made.
* latencyMode is the requested latency mode.
*/
- void setRequestedLatencyMode(int output, LatencyMode latencyMode);
+ void setRequestedLatencyMode(int output, AudioLatencyMode latencyMode);
/**
* Queries the list of latency modes (See LatencyMode.aidl) supported by an output stream.
* output is the I/O handle of the output stream to which the query applies.
* returns the list of supported latency modes.
*/
- LatencyMode[] getSupportedLatencyModes(int output);
+ AudioLatencyMode[] getSupportedLatencyModes(int output);
+
+ /**
+ * Requests if the implementation supports controlling the latency modes
+ * over the Bluetooth A2DP or LE Audio links. If it does,
+ * setRequestedLatencyMode() and getSupportedLatencyModes() APIs can also be used
+ * for streams routed to Bluetooth and not just for the spatializer output.
+ */
+ boolean supportsBluetoothVariableLatency();
+
+ /**
+ * Enables or disables the variable Bluetooth latency control mechanism in the
+ * audio framework and the audio HAL. This does not apply to the latency mode control
+ * on the spatializer output as this is a built-in feature.
+ */
+ void setBluetoothVariableLatencyEnabled(boolean enabled);
+
+ /**
+ * Indicates if the variable Bluetooth latency control mechanism is enabled or disabled.
+ */
+ boolean isBluetoothVariableLatencyEnabled();
// When adding a new method, please review and update
// IAudioFlinger.h AudioFlingerServerAdapter::Delegate::TransactionCode
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 8ac89a8..ed7e243 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -23,12 +23,12 @@
import android.media.AudioDirectMode;
import android.media.AudioMix;
import android.media.AudioOffloadMode;
-import android.media.AudioPatch;
+import android.media.AudioPatchFw;
import android.media.AudioPolicyDeviceState;
import android.media.AudioPolicyForcedConfig;
import android.media.AudioPolicyForceUse;
-import android.media.AudioPort;
-import android.media.AudioPortConfig;
+import android.media.AudioPortFw;
+import android.media.AudioPortConfigFw;
import android.media.AudioPortRole;
import android.media.AudioPortType;
import android.media.AudioProductStrategy;
@@ -212,16 +212,16 @@
int listAudioPorts(AudioPortRole role,
AudioPortType type,
inout Int count,
- out AudioPort[] ports);
+ out AudioPortFw[] ports);
/** Get attributes for the audio port with the given id (AudioPort.hal.id field). */
- AudioPort getAudioPort(int /* audio_port_handle_t */ portId);
+ AudioPortFw getAudioPort(int /* audio_port_handle_t */ portId);
/**
* Create an audio patch between several source and sink ports.
* The handle argument is used when updating an existing patch.
*/
- int /* audio_patch_handle_t */ createAudioPatch(in AudioPatch patch, int handle);
+ int /* audio_patch_handle_t */ createAudioPatch(in AudioPatchFw patch, int handle);
/** Release an audio patch. */
void releaseAudioPatch(int /* audio_patch_handle_t */ handle);
@@ -234,10 +234,10 @@
* Passing '0' on input and inspecting the value on output is a common way of determining the
* number of elements without actually retrieving them.
*/
- int listAudioPatches(inout Int count, out AudioPatch[] patches);
+ int listAudioPatches(inout Int count, out AudioPatchFw[] patches);
/** Set audio port configuration. */
- void setAudioPortConfig(in AudioPortConfig config);
+ void setAudioPortConfig(in AudioPortConfigFw config);
void registerClient(IAudioPolicyServiceClient client);
@@ -261,7 +261,7 @@
void removeUserIdDeviceAffinities(int userId);
- int /* audio_port_handle_t */ startAudioSource(in AudioPortConfig source,
+ int /* audio_port_handle_t */ startAudioSource(in AudioPortConfigFw source,
in AudioAttributesInternal attributes);
void stopAudioSource(int /* audio_port_handle_t */ portId);
diff --git a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
index 44ef80b..1ea4156 100644
--- a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
@@ -16,7 +16,7 @@
package android.media;
-import android.media.MicrophoneInfoData;
+import android.media.MicrophoneInfoFw;
/**
* Native code must specify namespace media (media::IAudioRecord) when referring to this class.
@@ -39,7 +39,7 @@
/* Get a list of current active microphones.
*/
- void getActiveMicrophones(out MicrophoneInfoData[] activeMicrophones);
+ void getActiveMicrophones(out MicrophoneInfoFw[] activeMicrophones);
/* Set the microphone direction (for processing).
*/
diff --git a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
index ac58925..c3a2dbe 100644
--- a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
@@ -16,13 +16,13 @@
package android.media;
-import android.media.AudioDualMonoMode;
-import android.media.AudioPlaybackRate;
import android.media.AudioTimestampInternal;
import android.media.SharedFileRegion;
import android.media.VolumeShaperConfiguration;
import android.media.VolumeShaperOperation;
import android.media.VolumeShaperState;
+import android.media.audio.common.AudioDualMonoMode;
+import android.media.audio.common.AudioPlaybackRate;
/**
* Unless otherwise noted, methods returning int expect it to be interpreted as a status_t.
diff --git a/media/libaudioclient/aidl/android/media/IEffect.aidl b/media/libaudioclient/aidl/android/media/IEffect.aidl
index 6ec0405..b7f70a6 100644
--- a/media/libaudioclient/aidl/android/media/IEffect.aidl
+++ b/media/libaudioclient/aidl/android/media/IEffect.aidl
@@ -16,6 +16,7 @@
package android.media;
+import android.media.EffectConfig;
import android.media.SharedFileRegion;
/**
@@ -63,6 +64,14 @@
*/
SharedFileRegion getCblk();
+ /**
+ * Provides audio configurations for effect's input and output,
+ * see EffectConfig parcelable for more details.
+ *
+ * @return a status_t code.
+ */
+ int getConfig(out EffectConfig config);
+
// When adding a new method, please review and update
// Effects.cpp AudioFlinger::EffectHandle::onTransact()
// Effects.cpp IEFFECT_BINDER_METHOD_MACRO_LIST
diff --git a/media/libaudioclient/aidl/android/media/LatencyMode.aidl b/media/libaudioclient/aidl/android/media/LatencyMode.aidl
deleted file mode 100644
index 0b2a72b..0000000
--- a/media/libaudioclient/aidl/android/media/LatencyMode.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.
- */
-
-package android.media;
-
-/**
- * The latency mode currently used by the spatializer mixer.
- * {@hide}
- */
-@Backing(type="byte")
-enum LatencyMode {
- /** No specific constraint on the latency */
- FREE = 0,
- /** A relatively low latency compatible with head tracking operation (e.g less than 100ms) */
- LOW = 1,
-}
diff --git a/media/libaudioclient/aidl/android/media/OpenOutputRequest.aidl b/media/libaudioclient/aidl/android/media/OpenOutputRequest.aidl
index 90e7ea6..ddda8bb 100644
--- a/media/libaudioclient/aidl/android/media/OpenOutputRequest.aidl
+++ b/media/libaudioclient/aidl/android/media/OpenOutputRequest.aidl
@@ -16,7 +16,7 @@
package android.media;
-import android.media.AudioPort;
+import android.media.AudioPortFw;
import android.media.audio.common.AudioConfig;
import android.media.audio.common.AudioConfigBase;
@@ -29,7 +29,7 @@
AudioConfig halConfig;
AudioConfigBase mixerConfig;
/** Type must be DEVICE. */
- AudioPort device;
+ AudioPortFw device;
/** Bitmask, indexed by AudioOutputFlag. */
int flags;
}
diff --git a/media/libaudioclient/fuzzer/Android.bp b/media/libaudioclient/fuzzer/Android.bp
index 969e3e6..b1feb60 100644
--- a/media/libaudioclient/fuzzer/Android.bp
+++ b/media/libaudioclient/fuzzer/Android.bp
@@ -25,6 +25,9 @@
cc_fuzz {
name: "audioflinger_fuzzer",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
srcs: [
"audioflinger_fuzzer.cpp",
],
@@ -46,7 +49,6 @@
],
shared_libs: [
"android.hardware.audio.common-util",
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
"audioflinger-aidl-cpp",
"audiopolicy-aidl-cpp",
@@ -54,6 +56,7 @@
"av-types-aidl-cpp",
"capture_state_listener-aidl-cpp",
"libaudioclient_aidl_conversion",
+ "libaudio_aidl_conversion_common_cpp",
"libaudioflinger",
"libaudiofoundation",
"libaudiomanager",
diff --git a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
index 036e72e..d881447 100644
--- a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
+++ b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
@@ -359,7 +359,7 @@
record->getInputFramesLost();
record->getFlags();
- std::vector<media::MicrophoneInfo> activeMicrophones;
+ std::vector<media::MicrophoneInfoFw> activeMicrophones;
record->getActiveMicrophones(&activeMicrophones);
record->releaseBuffer(&audioBuffer);
@@ -541,7 +541,7 @@
AudioSystem::getPrimaryOutputFrameCount();
AudioSystem::setLowRamDevice(mFdp.ConsumeBool(), mFdp.ConsumeIntegral<int64_t>());
- std::vector<media::MicrophoneInfo> microphones;
+ std::vector<media::MicrophoneInfoFw> microphones;
AudioSystem::getMicrophones(µphones);
std::vector<pid_t> pids;
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 1e66164..5bd0114 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -24,46 +24,21 @@
#include <android/media/AudioAttributesInternal.h>
#include <android/media/AudioClient.h>
#include <android/media/AudioDirectMode.h>
-#include <android/media/AudioDualMonoMode.h>
#include <android/media/AudioFlag.h>
#include <android/media/AudioIoConfigEvent.h>
#include <android/media/AudioIoDescriptor.h>
-#include <android/media/AudioPlaybackRate.h>
-#include <android/media/AudioPort.h>
-#include <android/media/AudioPortConfig.h>
+#include <android/media/AudioPortFw.h>
+#include <android/media/AudioPortConfigFw.h>
#include <android/media/AudioPortDeviceExtSys.h>
#include <android/media/AudioTimestampInternal.h>
#include <android/media/AudioUniqueIdUse.h>
#include <android/media/EffectDescriptor.h>
-#include <android/media/LatencyMode.h>
+#include <android/media/MicrophoneInfoFw.h>
#include <android/media/TrackSecondaryOutputInfo.h>
-#include <android/media/audio/common/AudioChannelLayout.h>
-#include <android/media/audio/common/AudioConfig.h>
-#include <android/media/audio/common/AudioConfigBase.h>
-#include <android/media/audio/common/AudioContentType.h>
-#include <android/media/audio/common/AudioDeviceDescription.h>
-#include <android/media/audio/common/AudioEncapsulationMetadataType.h>
-#include <android/media/audio/common/AudioEncapsulationMode.h>
-#include <android/media/audio/common/AudioEncapsulationType.h>
-#include <android/media/audio/common/AudioFormatDescription.h>
-#include <android/media/audio/common/AudioGain.h>
-#include <android/media/audio/common/AudioGainConfig.h>
-#include <android/media/audio/common/AudioGainMode.h>
-#include <android/media/audio/common/AudioInputFlags.h>
-#include <android/media/audio/common/AudioMode.h>
-#include <android/media/audio/common/AudioOffloadInfo.h>
-#include <android/media/audio/common/AudioOutputFlags.h>
-#include <android/media/audio/common/AudioPortExt.h>
-#include <android/media/audio/common/AudioPortMixExt.h>
-#include <android/media/audio/common/AudioProfile.h>
-#include <android/media/audio/common/AudioSource.h>
-#include <android/media/audio/common/AudioStandard.h>
-#include <android/media/audio/common/AudioUsage.h>
-#include <android/media/audio/common/AudioUuid.h>
-#include <android/media/audio/common/ExtraAudioDescriptor.h>
#include <android/media/SharedFileRegion.h>
#include <binder/IMemory.h>
+#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionUtil.h>
#include <media/AudioClient.h>
#include <media/AudioCommonTypes.h>
@@ -73,49 +48,6 @@
namespace android {
-// maxSize is the size of the C-string buffer (including the 0-terminator), NOT the max length of
-// the string.
-status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize);
-ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize);
-
-ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy);
-
-ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy);
-
-ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy);
-
-ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy);
-
-ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy);
-
-ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy);
-
-ConversionResult<unsigned int> aidl2legacy_int32_t_config_mask(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_config_mask_int32_t(unsigned int legacy);
-
-ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy);
-
-ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy);
-
-ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl);
-ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy);
-
-ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl);
-ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy);
-
-ConversionResult<std::optional<String16>>
-aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl);
-ConversionResult<std::optional<std::string_view>>
-legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy);
-
ConversionResult<audio_io_config_event_t> aidl2legacy_AudioIoConfigEvent_audio_io_config_event_t(
media::AudioIoConfigEvent aidl);
ConversionResult<media::AudioIoConfigEvent> legacy2aidl_audio_io_config_event_t_AudioIoConfigEvent(
@@ -131,75 +63,6 @@
ConversionResult<media::AudioPortType> legacy2aidl_audio_port_type_t_AudioPortType(
audio_port_type_t legacy);
-ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
- const media::audio::common::AudioChannelLayout& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioChannelLayout>
-legacy2aidl_audio_channel_mask_t_AudioChannelLayout(audio_channel_mask_t legacy, bool isInput);
-
-ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
- const media::audio::common::AudioDeviceDescription& aidl);
-ConversionResult<media::audio::common::AudioDeviceDescription>
-legacy2aidl_audio_devices_t_AudioDeviceDescription(audio_devices_t legacy);
-
-status_t aidl2legacy_AudioDevice_audio_device(
- const media::audio::common::AudioDevice& aidl,
- audio_devices_t* legacyType, char* legacyAddress);
-status_t aidl2legacy_AudioDevice_audio_device(
- const media::audio::common::AudioDevice& aidl,
- audio_devices_t* legacyType, String8* legacyAddress);
-status_t aidl2legacy_AudioDevice_audio_device(
- const media::audio::common::AudioDevice& aidl,
- audio_devices_t* legacyType, std::string* legacyAddress);
-ConversionResult<media::audio::common::AudioDevice>
-legacy2aidl_audio_device_AudioDevice(
- audio_devices_t legacyType, const char* legacyAddress);
-ConversionResult<media::audio::common::AudioDevice>
-legacy2aidl_audio_device_AudioDevice(
- audio_devices_t legacyType, const String8& legacyAddress);
-
-ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
- const media::audio::common::AudioFormatDescription& aidl);
-ConversionResult<media::audio::common::AudioFormatDescription>
-legacy2aidl_audio_format_t_AudioFormatDescription(audio_format_t legacy);
-
-ConversionResult<audio_gain_mode_t>
-aidl2legacy_AudioGainMode_audio_gain_mode_t(media::audio::common::AudioGainMode aidl);
-ConversionResult<media::audio::common::AudioGainMode>
-legacy2aidl_audio_gain_mode_t_AudioGainMode(audio_gain_mode_t legacy);
-
-ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy);
-
-ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
- const media::audio::common::AudioGainConfig& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioGainConfig>
-legacy2aidl_audio_gain_config_AudioGainConfig(const audio_gain_config& legacy, bool isInput);
-
-ConversionResult<audio_input_flags_t>
-aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
-ConversionResult<media::audio::common::AudioInputFlags>
-legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
-
-ConversionResult<audio_output_flags_t>
-aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
-ConversionResult<media::audio::common::AudioOutputFlags>
-legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
-
-ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
- int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
- audio_input_flags_t legacy);
-
-ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
- int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
- audio_output_flags_t legacy);
-
-ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
- const media::audio::common::AudioIoFlags& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
- const audio_io_flags& legacy, bool isInput);
-
ConversionResult<audio_port_config_device_ext>
aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
const media::audio::common::AudioPortDeviceExt& aidl,
@@ -214,15 +77,6 @@
ConversionResult<media::audio::common::AudioStreamType>
legacy2aidl_audio_stream_type_t_AudioStreamType(audio_stream_type_t legacy);
-ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
- media::audio::common::AudioSource aidl);
-ConversionResult<media::audio::common::AudioSource>
- legacy2aidl_audio_source_t_AudioSource(
- audio_source_t legacy);
-
-ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy);
-
ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortMixExt(
const media::audio::common::AudioPortMixExt& aidl, media::AudioPortRole role,
const media::AudioPortMixExtSys& aidlMixExt);
@@ -235,14 +89,15 @@
ConversionResult<int32_t> legacy2aidl_audio_port_config_session_ext_AudioPortConfigSessionExt(
const audio_port_config_session_ext& legacy);
-ConversionResult<audio_port_config> aidl2legacy_AudioPortConfig_audio_port_config(
- const media::AudioPortConfig& aidl);
-ConversionResult<media::AudioPortConfig> legacy2aidl_audio_port_config_AudioPortConfig(
- const audio_port_config& legacy);
+// portId needs to be set when dealing with the HAL.
+ConversionResult<audio_port_config> aidl2legacy_AudioPortConfigFw_audio_port_config(
+ const media::AudioPortConfigFw& aidl, int32_t* aidlPortId = nullptr);
+ConversionResult<media::AudioPortConfigFw> legacy2aidl_audio_port_config_AudioPortConfigFw(
+ const audio_port_config& legacy, int32_t portId = 0);
-ConversionResult<struct audio_patch> aidl2legacy_AudioPatch_audio_patch(
- const media::AudioPatch& aidl);
-ConversionResult<media::AudioPatch> legacy2aidl_audio_patch_AudioPatch(
+ConversionResult<struct audio_patch> aidl2legacy_AudioPatchFw_audio_patch(
+ const media::AudioPatchFw& aidl);
+ConversionResult<media::AudioPatchFw> legacy2aidl_audio_patch_AudioPatchFw(
const struct audio_patch& legacy);
ConversionResult<sp<AudioIoDescriptor>> aidl2legacy_AudioIoDescriptor_AudioIoDescriptor(
@@ -255,17 +110,6 @@
ConversionResult<media::AudioClient> legacy2aidl_AudioClient_AudioClient(
const AudioClient& legacy);
-ConversionResult<audio_content_type_t>
-aidl2legacy_AudioContentType_audio_content_type_t(
- media::audio::common::AudioContentType aidl);
-ConversionResult<media::audio::common::AudioContentType>
-legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy);
-
-ConversionResult<audio_usage_t>
-aidl2legacy_AudioUsage_audio_usage_t(media::audio::common::AudioUsage aidl);
-ConversionResult<media::audio::common::AudioUsage>
-legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy);
-
ConversionResult<audio_flags_mask_t>
aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl);
ConversionResult<media::AudioFlag>
@@ -281,36 +125,13 @@
ConversionResult<media::AudioAttributesInternal>
legacy2aidl_audio_attributes_t_AudioAttributesInternal(const audio_attributes_t& legacy);
-ConversionResult<audio_encapsulation_mode_t>
-aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(
- media::audio::common::AudioEncapsulationMode aidl);
-ConversionResult<media::audio::common::AudioEncapsulationMode>
-legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy);
-
-ConversionResult<audio_offload_info_t>
-aidl2legacy_AudioOffloadInfo_audio_offload_info_t(
- const media::audio::common::AudioOffloadInfo& aidl);
-ConversionResult<media::audio::common::AudioOffloadInfo>
-legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy);
-
-ConversionResult<audio_config_t>
-aidl2legacy_AudioConfig_audio_config_t(const media::audio::common::AudioConfig& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioConfig>
-legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput);
-
-ConversionResult<audio_config_base_t>
-aidl2legacy_AudioConfigBase_audio_config_base_t(
- const media::audio::common::AudioConfigBase& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioConfigBase>
-legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput);
-
ConversionResult<sp<IMemory>>
aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl);
ConversionResult<media::SharedFileRegion>
legacy2aidl_IMemory_SharedFileRegion(const sp<IMemory>& legacy);
-ConversionResult<sp<IMemory>>
-aidl2legacy_NullableSharedFileRegion_IMemory(const std::optional<media::SharedFileRegion>& aidl);
+ConversionResult<sp<::android::IMemory>> aidl2legacy_NullableSharedFileRegion_IMemory(
+ const std::optional<media::SharedFileRegion>& aidl);
ConversionResult<std::optional<media::SharedFileRegion>>
legacy2aidl_NullableIMemory_SharedFileRegion(const sp<IMemory>& legacy);
@@ -319,32 +140,10 @@
ConversionResult<media::AudioTimestampInternal>
legacy2aidl_AudioTimestamp_AudioTimestampInternal(const AudioTimestamp& legacy);
-ConversionResult<audio_uuid_t>
-aidl2legacy_AudioUuid_audio_uuid_t(const media::audio::common::AudioUuid& aidl);
-ConversionResult<media::audio::common::AudioUuid>
-legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy);
-
ConversionResult<effect_descriptor_t>
aidl2legacy_EffectDescriptor_effect_descriptor_t(const media::EffectDescriptor& aidl);
-ConversionResult<media::EffectDescriptor>
-legacy2aidl_effect_descriptor_t_EffectDescriptor(const effect_descriptor_t& legacy);
-
-ConversionResult<audio_encapsulation_metadata_type_t>
-aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
- media::audio::common::AudioEncapsulationMetadataType aidl);
-ConversionResult<media::audio::common::AudioEncapsulationMetadataType>
-legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
- audio_encapsulation_metadata_type_t legacy);
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy);
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy);
+ConversionResult<media::EffectDescriptor> legacy2aidl_effect_descriptor_t_EffectDescriptor(
+ const effect_descriptor_t& legacy);
ConversionResult<audio_port_device_ext>
aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
@@ -369,26 +168,10 @@
ConversionResult<int32_t>
legacy2aidl_audio_port_session_ext_int32_t(const audio_port_session_ext& legacy);
-ConversionResult<audio_profile>
-aidl2legacy_AudioProfile_audio_profile(
- const media::audio::common::AudioProfile& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioProfile>
-legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput);
-
-ConversionResult<audio_gain>
-aidl2legacy_AudioGain_audio_gain(const media::audio::common::AudioGain& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioGain>
-legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput);
-
ConversionResult<audio_port_v7>
-aidl2legacy_AudioPort_audio_port_v7(const media::AudioPort& aidl);
-ConversionResult<media::AudioPort>
-legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy);
-
-ConversionResult<audio_mode_t>
-aidl2legacy_AudioMode_audio_mode_t(media::audio::common::AudioMode aidl);
-ConversionResult<media::audio::common::AudioMode>
-legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy);
+aidl2legacy_AudioPortFw_audio_port_v7(const media::AudioPortFw& aidl);
+ConversionResult<media::AudioPortFw>
+legacy2aidl_audio_port_v7_AudioPortFw(const audio_port_v7& legacy);
ConversionResult<audio_unique_id_use_t>
aidl2legacy_AudioUniqueIdUse_audio_unique_id_use_t(media::AudioUniqueIdUse aidl);
@@ -400,45 +183,6 @@
ConversionResult<int32_t>
legacy2aidl_volume_group_t_int32_t(volume_group_t legacy);
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl);
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy);
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy);
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl);
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
-
-ConversionResult<audio_standard_t>
-aidl2legacy_AudioStandard_audio_standard_t(media::audio::common::AudioStandard aidl);
-ConversionResult<media::audio::common::AudioStandard>
-legacy2aidl_audio_standard_t_AudioStandard(audio_standard_t legacy);
-
-ConversionResult<audio_extra_audio_descriptor>
-aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
- const media::audio::common::ExtraAudioDescriptor& aidl);
-ConversionResult<media::audio::common::ExtraAudioDescriptor>
-legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
- const audio_extra_audio_descriptor& legacy);
-
-ConversionResult<audio_encapsulation_type_t>
-aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
- const media::audio::common::AudioEncapsulationType& aidl);
-ConversionResult<media::audio::common::AudioEncapsulationType>
-legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
- const audio_encapsulation_type_t & legacy);
-
using TrackSecondaryOutputInfoPair = std::pair<audio_port_handle_t, std::vector<audio_io_handle_t>>;
ConversionResult<TrackSecondaryOutputInfoPair>
aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
@@ -455,9 +199,11 @@
ConversionResult<audio_direct_mode_t> aidl2legacy_int32_t_audio_direct_mode_t_mask(int32_t aidl);
ConversionResult<int32_t> legacy2aidl_audio_direct_mode_t_int32_t_mask(audio_direct_mode_t legacy);
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl);
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy);
+ConversionResult<audio_microphone_characteristic_t>
+aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(
+ const media::MicrophoneInfoFw& aidl);
+ConversionResult<media::MicrophoneInfoFw>
+legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(
+ const audio_microphone_characteristic_t& legacy);
} // namespace android
diff --git a/media/libaudioclient/include/media/AudioEffect.h b/media/libaudioclient/include/media/AudioEffect.h
index 56884a3..291312e 100644
--- a/media/libaudioclient/include/media/AudioEffect.h
+++ b/media/libaudioclient/include/media/AudioEffect.h
@@ -136,7 +136,7 @@
* indicated by count.
* PERMISSION_DENIED could not get AudioFlinger interface
* NO_INIT effect library failed to initialize
- * BAD_VALUE invalid audio session or descriptor pointers
+ * BAD_VALUE invalid audio session, or invalid descriptor or count pointers
*
* Returned value
* *descriptor updated with descriptors of pre processings enabled by default
@@ -160,6 +160,7 @@
* NO_ERROR successful operation.
* PERMISSION_DENIED could not get AudioFlinger interface
* or caller lacks required permissions.
+ * BAD_VALUE invalid pointer to id
* Returned value
* *id: The new unique system-wide effect id.
*/
@@ -194,7 +195,7 @@
* PERMISSION_DENIED could not get AudioFlinger interface
* or caller lacks required permissions.
* NO_INIT effect library failed to initialize.
- * BAD_VALUE invalid source, type uuid or implementation uuid.
+ * BAD_VALUE invalid source, type uuid or implementation uuid, or id pointer
* NAME_NOT_FOUND no effect with this uuid or type found.
*
* Returned value
@@ -233,7 +234,7 @@
* PERMISSION_DENIED could not get AudioFlinger interface
* or caller lacks required permissions.
* NO_INIT effect library failed to initialize.
- * BAD_VALUE invalid type uuid or implementation uuid.
+ * BAD_VALUE invalid type uuid or implementation uuid, or id pointer
* NAME_NOT_FOUND no effect with this uuid or type found.
*
* Returned value
@@ -517,7 +518,7 @@
* Returned status (from utils/Errors.h) can be:
* - NO_ERROR: successful operation.
* - INVALID_OPERATION: the application does not have control of the effect engine.
- * - BAD_VALUE: invalid parameter identifier or value.
+ * - BAD_VALUE: invalid parameter structure pointer, or invalid identifier or value.
* - DEAD_OBJECT: the effect engine has been deleted.
*/
virtual status_t setParameter(effect_param_t *param);
@@ -562,7 +563,7 @@
* Returned status (from utils/Errors.h) can be:
* - NO_ERROR: successful operation.
* - INVALID_OPERATION: the AudioEffect was not successfully initialized.
- * - BAD_VALUE: invalid parameter identifier.
+ * - BAD_VALUE: invalid parameter structure pointer, or invalid parameter identifier.
* - DEAD_OBJECT: the effect engine has been deleted.
*/
virtual status_t getParameter(effect_param_t *param);
@@ -577,6 +578,25 @@
uint32_t *replySize,
void *replyData);
+ /* Retrieves the configuration of the effect.
+ *
+ * Parameters:
+ * inputCfg: pointer to audio_config_base_t structure receiving input
+ * configuration of the effect
+ * outputCfg: pointer to audio_config_base_t structure receiving output
+ * configuration of the effect
+ *
+ * Channel masks of the returned configs are "input" or "output" depending
+ * on the direction of the stream that the effect is attached to.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation.
+ * - INVALID_OPERATION: the AudioEffect was not successfully initialized.
+ * - BAD_VALUE: null config pointers
+ * - DEAD_OBJECT: the effect engine has been deleted.
+ */
+ virtual status_t getConfigs(audio_config_base_t *inputCfg,
+ audio_config_base_t *outputCfg);
/*
* Utility functions.
@@ -628,7 +648,7 @@
{
public:
- EffectClient(AudioEffect *effect) : mEffect(effect){}
+ explicit EffectClient(const sp<AudioEffect>& effect) : mEffect(effect){}
// IEffectClient
binder::Status controlStatusChanged(bool controlGranted) override {
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index fbb1100..cab476e 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -72,6 +72,7 @@
status_t readFromParcel(Parcel *parcel);
status_t writeToParcel(Parcel *parcel) const;
+ bool isExcludeCriterion() const;
union {
audio_usage_t mUsage;
audio_source_t mSource;
@@ -88,23 +89,24 @@
static const uint32_t kCbFlagNotifyActivity = 0x1;
AudioMix() {}
- AudioMix(Vector<AudioMixMatchCriterion> criteria, uint32_t mixType, audio_config_t format,
- uint32_t routeFlags, String8 registrationId, uint32_t flags) :
+ AudioMix(const std::vector<AudioMixMatchCriterion> &criteria, uint32_t mixType,
+ audio_config_t format, uint32_t routeFlags,const String8 ®istrationId,
+ uint32_t flags) :
mCriteria(criteria), mMixType(mixType), mFormat(format),
mRouteFlags(routeFlags), mDeviceAddress(registrationId), mCbFlags(flags){}
status_t readFromParcel(Parcel *parcel);
status_t writeToParcel(Parcel *parcel) const;
- void setExcludeUid(uid_t uid) const;
- void setMatchUid(uid_t uid) const;
+ void setExcludeUid(uid_t uid);
+ void setMatchUid(uid_t uid);
/** returns true if this mix has a rule to match or exclude the given uid */
bool hasUidRule(bool match, uid_t uid) const;
/** returns true if this mix has a rule for uid match (any uid) */
bool hasMatchUidRule() const;
- void setExcludeUserId(int userId) const;
- void setMatchUserId(int userId) const;
+ void setExcludeUserId(int userId);
+ void setMatchUserId(int userId);
/** returns true if this mix has a rule to match or exclude the given userId */
bool hasUserIdRule(bool match, int userId) const;
/** returns true if this mix has a rule for userId match (any userId) */
@@ -112,7 +114,7 @@
/** returns true if this mix can be used for uid-device affinity routing */
bool isDeviceAffinityCompatible() const;
- mutable Vector<AudioMixMatchCriterion> mCriteria;
+ std::vector<AudioMixMatchCriterion> mCriteria;
uint32_t mMixType;
audio_config_t mFormat;
uint32_t mRouteFlags;
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index cb05dd9..ae70a7f 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -26,7 +26,6 @@
#include <media/AudioTimestamp.h>
#include <media/MediaMetricsItem.h>
#include <media/Modulo.h>
-#include <media/MicrophoneInfo.h>
#include <media/RecordingActivityTracker.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
@@ -46,27 +45,6 @@
{
public:
- /* Events used by AudioRecord callback function (legacy_callback_t).
- * Keep in sync with frameworks/base/media/java/android/media/AudioRecord.java NATIVE_EVENT_*.
- */
- enum event_type {
- EVENT_MORE_DATA = 0, // Request to read available data from buffer.
- // If this event is delivered but the callback handler
- // does not want to read the available data, the handler must
- // explicitly ignore the event by setting frameCount to zero.
- EVENT_OVERRUN = 1, // Buffer overrun occurred.
- EVENT_MARKER = 2, // Record head is at the specified marker position
- // (See setMarkerPosition()).
- EVENT_NEW_POS = 3, // Record head is at a new position
- // (See setPositionUpdatePeriod()).
- EVENT_NEW_IAUDIORECORD = 4, // IAudioRecord was re-created, either due to re-routing and
- // voluntary invalidation by mediaserver, or mediaserver crash.
- };
-
- /* Client should declare a Buffer and pass address to obtainBuffer()
- * and releaseBuffer(). See also legacy_callback_t for EVENT_MORE_DATA.
- */
-
class Buffer
{
friend AudioRecord;
@@ -122,7 +100,6 @@
* - EVENT_NEW_IAUDIORECORD: unused.
*/
- typedef void (*legacy_callback_t)(int event, void* user, void *info);
class IAudioRecordCallback : public virtual RefBase {
friend AudioRecord;
@@ -226,24 +203,6 @@
float selectedMicFieldDimension = MIC_FIELD_DIMENSION_DEFAULT);
- AudioRecord(audio_source_t inputSource,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- const android::content::AttributionSourceState& client,
- size_t frameCount,
- legacy_callback_t callback,
- void* user,
- uint32_t notificationFrames = 0,
- audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
- transfer_type transferType = TRANSFER_DEFAULT,
- audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
- const audio_attributes_t* pAttributes = nullptr,
- audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE,
- audio_microphone_direction_t
- selectedMicDirection = MIC_DIRECTION_UNSPECIFIED,
- float selectedMicFieldDimension = MIC_FIELD_DIMENSION_DEFAULT);
-
/* Terminates the AudioRecord and unregisters it from AudioFlinger.
* Also destroys all resources associated with the AudioRecord.
*/
@@ -286,27 +245,6 @@
float selectedMicFieldDimension = MIC_FIELD_DIMENSION_DEFAULT,
int32_t maxSharedAudioHistoryMs = 0);
- status_t set(audio_source_t inputSource,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- size_t frameCount,
- legacy_callback_t callback,
- void* user,
- uint32_t notificationFrames = 0,
- bool threadCanCallJava = false,
- audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
- transfer_type transferType = TRANSFER_DEFAULT,
- audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
- uid_t uid = AUDIO_UID_INVALID,
- pid_t pid = -1,
- const audio_attributes_t* pAttributes = nullptr,
- audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE,
- audio_microphone_direction_t
- selectedMicDirection = MIC_DIRECTION_UNSPECIFIED,
- float selectedMicFieldDimension = MIC_FIELD_DIMENSION_DEFAULT,
- int32_t maxSharedAudioHistoryMs = 0);
-
/* Result of constructing the AudioRecord. This must be checked for successful initialization
* before using any AudioRecord API (except for set()), because using
* an uninitialized AudioRecord produces undefined results.
@@ -636,10 +574,11 @@
/* Get the flags */
audio_input_flags_t getFlags() const { AutoMutex _l(mLock); return mFlags; }
- /* Get active microphones. A empty vector of MicrophoneInfo will be passed as a parameter,
+ /* Get active microphones. A empty vector of MicrophoneInfoFw will be passed as a parameter,
* the data will be filled when querying the hal.
*/
- status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ status_t getActiveMicrophones(
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones);
/* Set the Microphone direction (for processing purposes).
*/
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 9411f46..543ce00 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -28,6 +28,7 @@
#include <android/media/BnAudioPolicyServiceClient.h>
#include <android/media/INativeSpatializerCallback.h>
#include <android/media/ISpatializer.h>
+#include <android/media/MicrophoneInfoFw.h>
#include <android/media/audio/common/AudioMMapPolicyInfo.h>
#include <android/media/audio/common/AudioMMapPolicyType.h>
#include <android/media/audio/common/AudioPort.h>
@@ -38,7 +39,6 @@
#include <media/AudioProductStrategy.h>
#include <media/AudioVolumeGroup.h>
#include <media/AudioIoDescriptor.h>
-#include <media/MicrophoneInfo.h>
#include <system/audio.h>
#include <system/audio_effect.h>
#include <system/audio_policy.h>
@@ -428,7 +428,7 @@
static float getStreamVolumeDB(
audio_stream_type_t stream, int index, audio_devices_t device);
- static status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+ static status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones);
static status_t getHwOffloadFormatsSupportedForBluetoothMedia(
audio_devices_t device, std::vector<audio_format_t> *formats);
@@ -575,6 +575,12 @@
static status_t getSupportedLatencyModes(audio_io_handle_t output,
std::vector<audio_latency_mode_t>* modes);
+ static status_t setBluetoothVariableLatencyEnabled(bool enabled);
+
+ static status_t isBluetoothVariableLatencyEnabled(bool *enabled);
+
+ static status_t supportsBluetoothVariableLatency(bool *support);
+
// A listener for capture state changes.
class CaptureStateListener : public virtual RefBase {
public:
@@ -705,7 +711,8 @@
const media::AudioIoDescriptor& ioDesc) override;
binder::Status onSupportedLatencyModesChanged(
- int output, const std::vector<media::LatencyMode>& latencyModes) override;
+ int output,
+ const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) override;
status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
audio_io_handle_t audioIo,
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 9f540e6..b6ee483 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -148,7 +148,6 @@
* - EVENT_NEW_TIMESTAMP: pointer to const AudioTimestamp.
*/
- typedef void (*legacy_callback_t)(int event, void* user, void* info);
class IAudioTrackCallback : public virtual RefBase {
friend AudioTrack;
protected:
@@ -343,26 +342,6 @@
float maxRequiredSpeed = 1.0f,
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
-
- AudioTrack( audio_stream_type_t streamType,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- size_t frameCount,
- audio_output_flags_t flags,
- legacy_callback_t cbf,
- void* user = nullptr,
- int32_t notificationFrames = 0,
- audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
- transfer_type transferType = TRANSFER_DEFAULT,
- const audio_offload_info_t *offloadInfo = nullptr,
- const AttributionSourceState& attributionSource =
- AttributionSourceState(),
- const audio_attributes_t* pAttributes = nullptr,
- bool doNotReconnect = false,
- float maxRequiredSpeed = 1.0f,
- audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
-
/* Creates an audio track and registers it with AudioFlinger.
* With this constructor, the track is configured for static buffer mode.
* Data to be rendered is passed in a shared memory buffer
@@ -391,25 +370,6 @@
bool doNotReconnect = false,
float maxRequiredSpeed = 1.0f);
-
- AudioTrack( audio_stream_type_t streamType,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- const sp<IMemory>& sharedBuffer,
- audio_output_flags_t flags,
- legacy_callback_t cbf,
- void* user = nullptr,
- int32_t notificationFrames = 0,
- audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
- transfer_type transferType = TRANSFER_DEFAULT,
- const audio_offload_info_t *offloadInfo = nullptr,
- const AttributionSourceState& attributionSource =
- AttributionSourceState(),
- const audio_attributes_t* pAttributes = nullptr,
- bool doNotReconnect = false,
- float maxRequiredSpeed = 1.0f);
-
/* Terminates the AudioTrack and unregisters it from AudioFlinger.
* Also destroys all resources associated with the AudioTrack.
*/
@@ -490,28 +450,8 @@
}
void onFirstRef() override;
public:
- status_t set(audio_stream_type_t streamType,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- size_t frameCount,
- audio_output_flags_t flags,
- legacy_callback_t callback,
- void * user = nullptr,
- int32_t notificationFrames = 0,
- const sp<IMemory>& sharedBuffer = 0,
- bool threadCanCallJava = false,
- audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
- transfer_type transferType = TRANSFER_DEFAULT,
- const audio_offload_info_t *offloadInfo = nullptr,
- const AttributionSourceState& attributionSource =
- AttributionSourceState(),
- const audio_attributes_t* pAttributes = nullptr,
- bool doNotReconnect = false,
- float maxRequiredSpeed = 1.0f,
- audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
-
- // FIXME(b/169889714): Vendor code depends on the old method signature at link time
+ typedef void (*legacy_callback_t)(int event, void* user, void* info);
+ // FIXME(b/169889714): Vendor code depends on the old method signature at link time
status_t set(audio_stream_type_t streamType,
uint32_t sampleRate,
audio_format_t format,
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index c891ae6..25b5414 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -32,7 +32,6 @@
#include <system/audio_effect.h>
#include <system/audio_policy.h>
#include <utils/String8.h>
-#include <media/MicrophoneInfo.h>
#include <map>
#include <string>
#include <vector>
@@ -339,7 +338,7 @@
virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const = 0;
/* List available microphones and their characteristics */
- virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
+ virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) = 0;
virtual status_t setAudioHalPids(const std::vector<pid_t>& pids) = 0;
@@ -367,6 +366,11 @@
virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
std::vector<audio_latency_mode_t>* modes) = 0;
+ virtual status_t setBluetoothVariableLatencyEnabled(bool enabled) = 0;
+
+ virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled) = 0;
+
+ virtual status_t supportsBluetoothVariableLatency(bool* support) = 0;
};
/**
@@ -458,7 +462,7 @@
status_t audioPolicyReady() override;
size_t frameCountHAL(audio_io_handle_t ioHandle) const override;
- status_t getMicrophones(std::vector<media::MicrophoneInfo>* microphones) override;
+ status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) override;
status_t setAudioHalPids(const std::vector<pid_t>& pids) override;
status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) override;
status_t updateSecondaryOutputs(
@@ -473,6 +477,9 @@
audio_latency_mode_t mode) override;
status_t getSupportedLatencyModes(
audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) override;
+ status_t setBluetoothVariableLatencyEnabled(bool enabled) override;
+ status_t isBluetoothVariableLatencyEnabled(bool* enabled) override;
+ status_t supportsBluetoothVariableLatency(bool* support) override;
private:
const sp<media::IAudioFlingerService> mDelegate;
@@ -564,6 +571,12 @@
SET_DEVICE_CONNECTED_STATE = media::BnAudioFlingerService::TRANSACTION_setDeviceConnectedState,
SET_REQUESTED_LATENCY_MODE = media::BnAudioFlingerService::TRANSACTION_setRequestedLatencyMode,
GET_SUPPORTED_LATENCY_MODES = media::BnAudioFlingerService::TRANSACTION_getSupportedLatencyModes,
+ SET_BLUETOOTH_VARIABLE_LATENCY_ENABLED =
+ media::BnAudioFlingerService::TRANSACTION_setBluetoothVariableLatencyEnabled,
+ IS_BLUETOOTH_VARIABLE_LATENCY_ENABLED =
+ media::BnAudioFlingerService::TRANSACTION_isBluetoothVariableLatencyEnabled,
+ SUPPORTS_BLUETOOTH_VARIABLE_LATENCY =
+ media::BnAudioFlingerService::TRANSACTION_supportsBluetoothVariableLatency,
};
protected:
@@ -664,17 +677,17 @@
Status getPrimaryOutputSamplingRate(int32_t* _aidl_return) override;
Status getPrimaryOutputFrameCount(int64_t* _aidl_return) override;
Status setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) override;
- Status getAudioPort(const media::AudioPort& port, media::AudioPort* _aidl_return) override;
- Status createAudioPatch(const media::AudioPatch& patch, int32_t* _aidl_return) override;
+ Status getAudioPort(const media::AudioPortFw& port, media::AudioPortFw* _aidl_return) override;
+ Status createAudioPatch(const media::AudioPatchFw& patch, int32_t* _aidl_return) override;
Status releaseAudioPatch(int32_t handle) override;
Status listAudioPatches(int32_t maxCount,
- std::vector<media::AudioPatch>* _aidl_return) override;
- Status setAudioPortConfig(const media::AudioPortConfig& config) override;
+ std::vector<media::AudioPatchFw>* _aidl_return) override;
+ Status setAudioPortConfig(const media::AudioPortConfigFw& config) override;
Status getAudioHwSyncForSession(int32_t sessionId, int32_t* _aidl_return) override;
Status systemReady() override;
Status audioPolicyReady() override;
Status frameCountHAL(int32_t ioHandle, int64_t* _aidl_return) override;
- Status getMicrophones(std::vector<media::MicrophoneInfoData>* _aidl_return) override;
+ Status getMicrophones(std::vector<media::MicrophoneInfoFw>* _aidl_return) override;
Status setAudioHalPids(const std::vector<int32_t>& pids) override;
Status setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) override;
Status updateSecondaryOutputs(
@@ -684,10 +697,14 @@
std::vector<media::audio::common::AudioMMapPolicyInfo> *_aidl_return) override;
Status getAAudioMixerBurstCount(int32_t* _aidl_return) override;
Status getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
- Status setDeviceConnectedState(const media::AudioPort& port, bool connected) override;
- Status setRequestedLatencyMode(int output, media::LatencyMode mode) override;
+ Status setDeviceConnectedState(const media::AudioPortFw& port, bool connected) override;
+ Status setRequestedLatencyMode(
+ int output, media::audio::common::AudioLatencyMode mode) override;
Status getSupportedLatencyModes(int output,
- std::vector<media::LatencyMode>* _aidl_return) override;
+ std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) override;
+ Status setBluetoothVariableLatencyEnabled(bool enabled) override;
+ Status isBluetoothVariableLatencyEnabled(bool* enabled) override;
+ Status supportsBluetoothVariableLatency(bool* support) override;
private:
const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
};
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index 891293e..2189521 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -24,7 +24,10 @@
cc_test {
name: "audio_aidl_conversion_tests",
- defaults: ["libaudioclient_tests_defaults"],
+ defaults: [
+ "libaudioclient_tests_defaults",
+ "latest_android_media_audio_common_types_cpp_static",
+ ],
srcs: ["audio_aidl_legacy_conversion_tests.cpp"],
shared_libs: [
"libbinder",
@@ -33,9 +36,10 @@
"libutils",
],
static_libs: [
- "android.media.audio.common.types-V1-cpp",
- "audioclient-types-aidl-cpp",
"libaudioclient_aidl_conversion",
+ "libaudio_aidl_conversion_common_cpp",
+ "audioclient-types-aidl-cpp",
+ "av-types-aidl-cpp",
"libstagefright_foundation",
],
}
@@ -93,3 +97,132 @@
],
data: ["record_test_input_*.txt"],
}
+
+cc_defaults {
+ name: "libaudioclient_gtests_defaults",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_static",
+ ],
+ shared_libs: [
+ "capture_state_listener-aidl-cpp",
+ "framework-permission-aidl-cpp",
+ "libaudioclient_aidl_conversion",
+ "libaudio_aidl_conversion_common_cpp",
+ "libbase",
+ "libbinder",
+ "libcgrouprc",
+ "libcutils",
+ "libdl",
+ "liblog",
+ "libmedia",
+ "libmediametrics",
+ "libmediautils",
+ "libmedia_helper",
+ "libnblog",
+ "libprocessgroup",
+ "libshmemcompat",
+ "libstagefright_foundation",
+ "libutils",
+ "libxml2",
+ "mediametricsservice-aidl-cpp",
+ "packagemanager_aidl-cpp",
+ "shared-file-region-aidl-cpp",
+ ],
+ static_libs: [
+ "android.hardware.audio.common@7.0-enums",
+ "audioclient-types-aidl-cpp",
+ "audioflinger-aidl-cpp",
+ "audiopolicy-aidl-cpp",
+ "audiopolicy-types-aidl-cpp",
+ "av-types-aidl-cpp",
+ "effect-aidl-cpp",
+ "libaudioclient",
+ "libaudiofoundation",
+ "libaudiomanager",
+ "libaudiopolicy",
+ "libaudioutils",
+ ],
+ data: ["bbb*.raw"],
+ test_config_template: "audio_test_template.xml",
+ test_suites: ["device-tests"],
+}
+
+cc_test {
+ name: "audiorecord_tests",
+ defaults: ["libaudioclient_gtests_defaults"],
+ srcs: [
+ "audiorecord_tests.cpp",
+ "audio_test_utils.cpp",
+ ],
+}
+
+cc_test {
+ name: "audiotrack_tests",
+ defaults: ["libaudioclient_gtests_defaults"],
+ srcs: [
+ "audiotrack_tests.cpp",
+ "audio_test_utils.cpp",
+ ],
+}
+
+cc_test {
+ name: "audioeffect_tests",
+ defaults: ["libaudioclient_gtests_defaults"],
+ srcs: [
+ "audioeffect_tests.cpp",
+ "audio_test_utils.cpp",
+ ],
+}
+
+cc_test {
+ name: "audioeffect_analysis",
+ defaults: ["libaudioclient_gtests_defaults"],
+ // flag needed for pfft/pffft.hpp
+ cflags: [
+ "-Wno-error=unused-parameter",
+ ],
+ srcs: [
+ "audioeffect_analyser.cpp",
+ "audio_test_utils.cpp",
+ ],
+ static_libs: [
+ "libpffft",
+ ],
+}
+
+cc_test {
+ name: "audiorouting_tests",
+ defaults: ["libaudioclient_gtests_defaults"],
+ srcs: [
+ "audiorouting_tests.cpp",
+ "audio_test_utils.cpp",
+ ],
+}
+
+cc_test {
+ name: "audioclient_serialization_tests",
+ defaults: ["libaudioclient_gtests_defaults"],
+ srcs: [
+ "audioclient_serialization_tests.cpp",
+ "audio_test_utils.cpp",
+ ],
+}
+
+cc_test {
+ name: "trackplayerbase_tests",
+ defaults: ["libaudioclient_gtests_defaults"],
+ srcs: ["trackplayerbase_tests.cpp"],
+}
+
+cc_test {
+ name: "audiosystem_tests",
+ defaults: ["libaudioclient_gtests_defaults"],
+ srcs: [
+ "audiosystem_tests.cpp",
+ "audio_test_utils.cpp",
+ ],
+}
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index 997f62a..e2216a0 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -14,24 +14,68 @@
* limitations under the License.
*/
+#include <iostream>
+
#include <gtest/gtest.h>
-#include <media/AudioCommonTypes.h>
#include <media/AidlConversion.h>
+#include <media/AudioCommonTypes.h>
using namespace android;
using namespace android::aidl_utils;
+using media::AudioDirectMode;
+using media::AudioPortConfigFw;
+using media::AudioPortDeviceExtSys;
+using media::AudioPortFw;
+using media::AudioPortRole;
+using media::AudioPortType;
using media::audio::common::AudioChannelLayout;
+using media::audio::common::AudioDevice;
using media::audio::common::AudioDeviceDescription;
using media::audio::common::AudioDeviceType;
+using media::audio::common::AudioEncapsulationMetadataType;
+using media::audio::common::AudioEncapsulationType;
using media::audio::common::AudioFormatDescription;
using media::audio::common::AudioFormatType;
+using media::audio::common::AudioGain;
+using media::audio::common::AudioGainConfig;
+using media::audio::common::AudioGainMode;
+using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioPortDeviceExt;
+using media::audio::common::AudioProfile;
+using media::audio::common::AudioStandard;
+using media::audio::common::ExtraAudioDescriptor;
+using media::audio::common::Int;
+using media::audio::common::MicrophoneDynamicInfo;
+using media::audio::common::MicrophoneInfo;
using media::audio::common::PcmType;
+// Provide value printers for types generated from AIDL
+// They need to be in the same namespace as the types we intend to print
+namespace android::media {
+#define DEFINE_PRINTING_TEMPLATES() \
+ template <typename P> \
+ std::enable_if_t<std::is_base_of_v<::android::Parcelable, P>, std::ostream&> operator<<( \
+ std::ostream& os, const P& p) { \
+ return os << p.toString(); \
+ } \
+ template <typename E> \
+ std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) { \
+ return os << toString(e); \
+ }
+DEFINE_PRINTING_TEMPLATES();
+
+namespace audio::common {
+DEFINE_PRINTING_TEMPLATES();
+} // namespace audio::common
+#undef DEFINE_PRINTING_TEMPLATES
+} // namespace android::media
+
namespace {
-template<typename T> size_t hash(const T& t) {
+template <typename T>
+size_t hash(const T& t) {
return std::hash<T>{}(t);
}
@@ -52,10 +96,8 @@
return AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
// Use channels that exist both for input and output,
// but doesn't form a known layout mask.
- AudioChannelLayout::CHANNEL_FRONT_LEFT |
- AudioChannelLayout::CHANNEL_FRONT_RIGHT |
- AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT |
- AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT);
+ AudioChannelLayout::CHANNEL_FRONT_LEFT | AudioChannelLayout::CHANNEL_FRONT_RIGHT |
+ AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT | AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT);
}
AudioChannelLayout make_ACL_ChannelIndex2() {
@@ -74,7 +116,7 @@
}
AudioDeviceDescription make_AudioDeviceDescription(AudioDeviceType type,
- const std::string& connection = "") {
+ const std::string& connection = "") {
AudioDeviceDescription result;
result.type = type;
result.connection = connection;
@@ -95,12 +137,12 @@
AudioDeviceDescription make_ADD_WiredHeadset() {
return make_AudioDeviceDescription(AudioDeviceType::OUT_HEADSET,
- AudioDeviceDescription::CONNECTION_ANALOG());
+ AudioDeviceDescription::CONNECTION_ANALOG());
}
AudioDeviceDescription make_ADD_BtScoHeadset() {
return make_AudioDeviceDescription(AudioDeviceType::OUT_HEADSET,
- AudioDeviceDescription::CONNECTION_BT_SCO());
+ AudioDeviceDescription::CONNECTION_BT_SCO());
}
AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
@@ -121,8 +163,7 @@
return result;
}
-AudioFormatDescription make_AudioFormatDescription(PcmType transport,
- const std::string& encoding) {
+AudioFormatDescription make_AudioFormatDescription(PcmType transport, const std::string& encoding) {
auto result = make_AudioFormatDescription(encoding);
result.pcm = transport;
return result;
@@ -154,6 +195,22 @@
return afd;
}
+android::media::TrackSecondaryOutputInfo make_TrackSecondaryOutputInfo() {
+ android::media::TrackSecondaryOutputInfo result;
+ result.portId = 1;
+ result.secondaryOutputIds = {0, 5, 7};
+ return result;
+}
+
+ExtraAudioDescriptor make_ExtraAudioDescriptor(AudioStandard audioStandard,
+ AudioEncapsulationType audioEncapsulationType) {
+ ExtraAudioDescriptor result;
+ result.standard = audioStandard;
+ result.audioDescriptor = {0xb4, 0xaf, 0x98, 0x1a};
+ result.encapsulationType = audioEncapsulationType;
+ return result;
+}
+
} // namespace
// Verify that two independently constructed ADDs/AFDs have the same hash.
@@ -163,7 +220,8 @@
// is identical to the same format description constructed by the framework.
class HashIdentityTest : public ::testing::Test {
public:
- template<typename T> void verifyHashIdentity(const std::vector<std::function<T()>>& valueGens) {
+ template <typename T>
+ void verifyHashIdentity(const std::vector<std::function<T()>>& valueGens) {
for (size_t i = 0; i < valueGens.size(); ++i) {
for (size_t j = 0; j < valueGens.size(); ++j) {
if (i == j) {
@@ -177,27 +235,25 @@
};
TEST_F(HashIdentityTest, AudioChannelLayoutHashIdentity) {
- verifyHashIdentity<AudioChannelLayout>({
- make_ACL_None, make_ACL_Invalid, make_ACL_Stereo,
- make_ACL_LayoutArbitrary, make_ACL_ChannelIndex2,
- make_ACL_ChannelIndexArbitrary, make_ACL_VoiceCall});
+ verifyHashIdentity<AudioChannelLayout>({make_ACL_None, make_ACL_Invalid, make_ACL_Stereo,
+ make_ACL_LayoutArbitrary, make_ACL_ChannelIndex2,
+ make_ACL_ChannelIndexArbitrary, make_ACL_VoiceCall});
}
TEST_F(HashIdentityTest, AudioDeviceDescriptionHashIdentity) {
- verifyHashIdentity<AudioDeviceDescription>({
- make_ADD_None, make_ADD_DefaultIn, make_ADD_DefaultOut, make_ADD_WiredHeadset,
- make_ADD_BtScoHeadset});
+ verifyHashIdentity<AudioDeviceDescription>({make_ADD_None, make_ADD_DefaultIn,
+ make_ADD_DefaultOut, make_ADD_WiredHeadset,
+ make_ADD_BtScoHeadset});
}
TEST_F(HashIdentityTest, AudioFormatDescriptionHashIdentity) {
- verifyHashIdentity<AudioFormatDescription>({
- make_AFD_Default, make_AFD_Invalid, make_AFD_Pcm16Bit, make_AFD_Bitstream,
- make_AFD_Encap, make_AFD_Encap_with_Enc});
+ verifyHashIdentity<AudioFormatDescription>({make_AFD_Default, make_AFD_Invalid,
+ make_AFD_Pcm16Bit, make_AFD_Bitstream,
+ make_AFD_Encap, make_AFD_Encap_with_Enc});
}
using ChannelLayoutParam = std::tuple<AudioChannelLayout, bool /*isInput*/>;
-class AudioChannelLayoutRoundTripTest :
- public testing::TestWithParam<ChannelLayoutParam> {};
+class AudioChannelLayoutRoundTripTest : public testing::TestWithParam<ChannelLayoutParam> {};
TEST_P(AudioChannelLayoutRoundTripTest, Aidl2Legacy2Aidl) {
const auto initial = std::get<0>(GetParam());
const bool isInput = std::get<1>(GetParam());
@@ -207,21 +263,82 @@
ASSERT_TRUE(convBack.ok());
EXPECT_EQ(initial, convBack.value());
}
-INSTANTIATE_TEST_SUITE_P(AudioChannelLayoutRoundTrip,
- AudioChannelLayoutRoundTripTest,
+
+INSTANTIATE_TEST_SUITE_P(
+ AudioChannelLayoutRoundTrip, AudioChannelLayoutRoundTripTest,
testing::Combine(
testing::Values(AudioChannelLayout{}, make_ACL_Invalid(), make_ACL_Stereo(),
- make_ACL_LayoutArbitrary(), make_ACL_ChannelIndex2(),
- make_ACL_ChannelIndexArbitrary()),
+ make_ACL_LayoutArbitrary(), make_ACL_ChannelIndex2(),
+ make_ACL_ChannelIndexArbitrary(),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_FRONT_LEFT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_FRONT_RIGHT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_BACK_CENTER),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_BACK_LEFT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_BACK_RIGHT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_FRONT_CENTER),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_LOW_FREQUENCY),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT)),
testing::Values(false, true)));
-INSTANTIATE_TEST_SUITE_P(AudioChannelVoiceRoundTrip,
- AudioChannelLayoutRoundTripTest,
- // In legacy constants the voice call is only defined for input.
- testing::Combine(testing::Values(make_ACL_VoiceCall()), testing::Values(true)));
+INSTANTIATE_TEST_SUITE_P(AudioChannelVoiceRoundTrip, AudioChannelLayoutRoundTripTest,
+ // In legacy constants the voice call is only defined for input.
+ testing::Combine(testing::Values(make_ACL_VoiceCall()),
+ testing::Values(true)));
+
+INSTANTIATE_TEST_SUITE_P(
+ OutAudioChannelLayoutLayoutRoundTrip, AudioChannelLayoutRoundTripTest,
+ testing::Combine(
+ testing::Values(AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_FRONT_LEFT_OF_CENTER),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_FRONT_RIGHT_OF_CENTER),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_SIDE_LEFT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_SIDE_RIGHT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_TOP_CENTER),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_TOP_FRONT_LEFT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_TOP_FRONT_CENTER),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_TOP_FRONT_RIGHT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_TOP_BACK_LEFT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_TOP_BACK_CENTER),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_TOP_BACK_RIGHT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_BOTTOM_FRONT_LEFT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_BOTTOM_FRONT_CENTER),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_BOTTOM_FRONT_RIGHT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_LOW_FREQUENCY_2),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_FRONT_WIDE_LEFT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_FRONT_WIDE_RIGHT),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_HAPTIC_A),
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::CHANNEL_HAPTIC_B)),
+ testing::Values(false)));
using ChannelLayoutEdgeCaseParam = std::tuple<int /*legacy*/, bool /*isInput*/, bool /*isValid*/>;
-class AudioChannelLayoutEdgeCaseTest :
- public testing::TestWithParam<ChannelLayoutEdgeCaseParam> {};
+class AudioChannelLayoutEdgeCaseTest : public testing::TestWithParam<ChannelLayoutEdgeCaseParam> {};
TEST_P(AudioChannelLayoutEdgeCaseTest, Legacy2Aidl) {
const audio_channel_mask_t legacy = static_cast<audio_channel_mask_t>(std::get<0>(GetParam()));
const bool isInput = std::get<1>(GetParam());
@@ -229,8 +346,8 @@
auto conv = legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy, isInput);
EXPECT_EQ(isValid, conv.ok());
}
-INSTANTIATE_TEST_SUITE_P(AudioChannelLayoutEdgeCase,
- AudioChannelLayoutEdgeCaseTest,
+INSTANTIATE_TEST_SUITE_P(
+ AudioChannelLayoutEdgeCase, AudioChannelLayoutEdgeCaseTest,
testing::Values(
// Valid legacy input masks.
std::make_tuple(AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO, true, true),
@@ -240,25 +357,26 @@
std::make_tuple(
// This has the same numerical representation as Mask 'A' below
AUDIO_CHANNEL_OUT_FRONT_CENTER | AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
- AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT, false, true),
+ AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT,
+ false, true),
std::make_tuple(
// This has the same numerical representation as Mask 'B' below
AUDIO_CHANNEL_OUT_FRONT_CENTER | AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
- AUDIO_CHANNEL_OUT_TOP_BACK_LEFT, false, true),
+ AUDIO_CHANNEL_OUT_TOP_BACK_LEFT,
+ false, true),
// Invalid legacy input masks.
std::make_tuple(AUDIO_CHANNEL_IN_6, true, false),
- std::make_tuple(
- AUDIO_CHANNEL_IN_6 | AUDIO_CHANNEL_IN_FRONT_PROCESSED, true, false),
- std::make_tuple(
- AUDIO_CHANNEL_IN_PRESSURE | AUDIO_CHANNEL_IN_X_AXIS |
- AUDIO_CHANNEL_IN_Y_AXIS | AUDIO_CHANNEL_IN_Z_AXIS, true, false),
+ std::make_tuple(AUDIO_CHANNEL_IN_6 | AUDIO_CHANNEL_IN_FRONT_PROCESSED, true, false),
+ std::make_tuple(AUDIO_CHANNEL_IN_PRESSURE | AUDIO_CHANNEL_IN_X_AXIS |
+ AUDIO_CHANNEL_IN_Y_AXIS | AUDIO_CHANNEL_IN_Z_AXIS,
+ true, false),
std::make_tuple( // Mask 'A'
AUDIO_CHANNEL_IN_STEREO | AUDIO_CHANNEL_IN_VOICE_UPLINK, true, false),
std::make_tuple( // Mask 'B'
AUDIO_CHANNEL_IN_STEREO | AUDIO_CHANNEL_IN_VOICE_DNLINK, true, false)));
-class AudioDeviceDescriptionRoundTripTest :
- public testing::TestWithParam<AudioDeviceDescription> {};
+class AudioDeviceDescriptionRoundTripTest : public testing::TestWithParam<AudioDeviceDescription> {
+};
TEST_P(AudioDeviceDescriptionRoundTripTest, Aidl2Legacy2Aidl) {
const auto initial = GetParam();
auto conv = aidl2legacy_AudioDeviceDescription_audio_devices_t(initial);
@@ -267,13 +385,13 @@
ASSERT_TRUE(convBack.ok());
EXPECT_EQ(initial, convBack.value());
}
-INSTANTIATE_TEST_SUITE_P(AudioDeviceDescriptionRoundTrip,
- AudioDeviceDescriptionRoundTripTest,
- testing::Values(AudioDeviceDescription{}, make_ADD_DefaultIn(),
- make_ADD_DefaultOut(), make_ADD_WiredHeadset(), make_ADD_BtScoHeadset()));
+INSTANTIATE_TEST_SUITE_P(AudioDeviceDescriptionRoundTrip, AudioDeviceDescriptionRoundTripTest,
+ testing::Values(AudioDeviceDescription{}, make_ADD_DefaultIn(),
+ make_ADD_DefaultOut(), make_ADD_WiredHeadset(),
+ make_ADD_BtScoHeadset()));
-class AudioFormatDescriptionRoundTripTest :
- public testing::TestWithParam<AudioFormatDescription> {};
+class AudioFormatDescriptionRoundTripTest : public testing::TestWithParam<AudioFormatDescription> {
+};
TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) {
const auto initial = GetParam();
auto conv = aidl2legacy_AudioFormatDescription_audio_format_t(initial);
@@ -282,6 +400,338 @@
ASSERT_TRUE(convBack.ok());
EXPECT_EQ(initial, convBack.value());
}
-INSTANTIATE_TEST_SUITE_P(AudioFormatDescriptionRoundTrip,
- AudioFormatDescriptionRoundTripTest,
- testing::Values(make_AFD_Invalid(), AudioFormatDescription{}, make_AFD_Pcm16Bit()));
+INSTANTIATE_TEST_SUITE_P(AudioFormatDescriptionRoundTrip, AudioFormatDescriptionRoundTripTest,
+ testing::Values(make_AFD_Invalid(), AudioFormatDescription{},
+ make_AFD_Pcm16Bit()));
+
+AudioPortConfigFw createAudioPortConfigFw(const AudioChannelLayout& layout,
+ const AudioFormatDescription& format,
+ const AudioDeviceDescription& device) {
+ const bool isInput = device.type < AudioDeviceType::OUT_DEFAULT;
+ AudioPortConfigFw result;
+ result.hal.id = 43;
+ result.hal.portId = 42;
+ Int sr44100;
+ sr44100.value = 44100;
+ result.hal.sampleRate = sr44100;
+ result.hal.channelMask = layout;
+ result.hal.format = format;
+ AudioGainConfig gain;
+ gain.mode = 1 << static_cast<int>(AudioGainMode::JOINT);
+ gain.values = std::vector<int32_t>({100});
+ result.hal.gain = gain;
+ AudioPortDeviceExt ext;
+ AudioDevice audioDevice;
+ audioDevice.type = device;
+ ext.device = audioDevice;
+ result.hal.ext = ext;
+ result.sys.role = isInput ? AudioPortRole::SOURCE : AudioPortRole::SINK;
+ result.sys.type = AudioPortType::DEVICE;
+ AudioPortDeviceExtSys sysDevice;
+ sysDevice.hwModule = 1;
+ result.sys.ext = sysDevice;
+ return result;
+}
+
+using AudioPortConfigParam =
+ std::tuple<AudioChannelLayout, AudioFormatDescription, AudioDeviceDescription>;
+class AudioPortConfigRoundTripTest : public testing::TestWithParam<AudioPortConfigParam> {};
+TEST_P(AudioPortConfigRoundTripTest, Aidl2Legacy2Aidl) {
+ const AudioChannelLayout layout = std::get<0>(GetParam());
+ const AudioFormatDescription format = std::get<1>(GetParam());
+ const AudioDeviceDescription device = std::get<2>(GetParam());
+ const bool isInput = device.type < AudioDeviceType::OUT_DEFAULT;
+ AudioPortConfigFw initial = createAudioPortConfigFw(layout, format, device);
+ {
+ audio_port_config conv{};
+ int32_t portId = -1;
+ status_t status =
+ aidl2legacy_AudioPortConfig_audio_port_config(initial.hal, isInput, &conv, &portId);
+ ASSERT_EQ(OK, status);
+ EXPECT_NE(-1, portId);
+ auto convBack = legacy2aidl_audio_port_config_AudioPortConfig(conv, isInput, portId);
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial.hal, convBack.value());
+ }
+ {
+ int32_t portId = -1;
+ auto conv = aidl2legacy_AudioPortConfigFw_audio_port_config(initial, &portId);
+ ASSERT_TRUE(conv.ok());
+ EXPECT_NE(-1, portId);
+ auto convBack = legacy2aidl_audio_port_config_AudioPortConfigFw(conv.value(), portId);
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+ }
+}
+INSTANTIATE_TEST_SUITE_P(
+ AudioPortConfig, AudioPortConfigRoundTripTest,
+ testing::Combine(testing::Values(make_ACL_Stereo(), make_ACL_ChannelIndex2()),
+ testing::Values(make_AFD_Pcm16Bit()),
+ testing::Values(make_ADD_DefaultIn(), make_ADD_DefaultOut(),
+ make_ADD_WiredHeadset())));
+
+class AudioPortFwRoundTripTest : public testing::TestWithParam<AudioDeviceDescription> {
+ public:
+ AudioProfile createProfile(const AudioFormatDescription& format,
+ const std::vector<AudioChannelLayout>& channelMasks,
+ const std::vector<int32_t>& sampleRates) {
+ AudioProfile profile;
+ profile.format = format;
+ profile.channelMasks = channelMasks;
+ profile.sampleRates = sampleRates;
+ return profile;
+ }
+};
+TEST_P(AudioPortFwRoundTripTest, Aidl2Legacy2Aidl) {
+ const AudioDeviceDescription device = GetParam();
+ const bool isInput = device.type < AudioDeviceType::OUT_DEFAULT;
+ AudioPortFw initial;
+ initial.hal.id = 42;
+ initial.hal.profiles.push_back(createProfile(
+ make_AFD_Pcm16Bit(), {make_ACL_Stereo(), make_ACL_ChannelIndex2()}, {44100, 48000}));
+ if (isInput) {
+ initial.hal.flags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
+ } else {
+ initial.hal.flags = AudioIoFlags::make<AudioIoFlags::Tag::output>(0);
+ }
+ AudioGain initialGain;
+ initialGain.mode = 1 << static_cast<int>(AudioGainMode::JOINT);
+ initialGain.channelMask = make_ACL_Stereo();
+ initial.hal.gains.push_back(initialGain);
+ AudioPortDeviceExt initialExt;
+ AudioDevice initialDevice;
+ initialDevice.type = device;
+ initialExt.device = initialDevice;
+ initial.hal.ext = initialExt;
+ {
+ auto conv = aidl2legacy_AudioPort_audio_port_v7(initial.hal, isInput);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_port_v7_AudioPort(conv.value(), isInput);
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial.hal, convBack.value());
+ }
+ initial.sys.role = isInput ? AudioPortRole::SOURCE : AudioPortRole::SINK;
+ initial.sys.type = AudioPortType::DEVICE;
+ initial.sys.profiles.resize(initial.hal.profiles.size());
+ initial.sys.gains.resize(initial.hal.gains.size());
+ initial.sys.activeConfig =
+ createAudioPortConfigFw(make_ACL_Stereo(), make_AFD_Pcm16Bit(), device);
+ initial.sys.activeConfig.hal.flags = initial.hal.flags;
+ AudioPortDeviceExtSys initialSysDevice;
+ initialSysDevice.hwModule = 1;
+ initial.sys.ext = initialSysDevice;
+ {
+ auto conv = aidl2legacy_AudioPortFw_audio_port_v7(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_port_v7_AudioPortFw(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+ }
+}
+INSTANTIATE_TEST_SUITE_P(AudioPortFw, AudioPortFwRoundTripTest,
+ testing::Values(make_ADD_DefaultIn(), make_ADD_DefaultOut(),
+ make_ADD_WiredHeadset()));
+
+class AudioDirectModeRoundTripTest : public testing::TestWithParam<AudioDirectMode> {};
+TEST_P(AudioDirectModeRoundTripTest, Aidl2Legacy2Aidl) {
+ const auto initial = GetParam();
+ auto conv = aidl2legacy_AudioDirectMode_audio_direct_mode_t(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_direct_mode_t_AudioDirectMode(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioDirectMode, AudioDirectModeRoundTripTest,
+ testing::Values(AudioDirectMode::NONE, AudioDirectMode::OFFLOAD,
+ AudioDirectMode::OFFLOAD_GAPLESS,
+ AudioDirectMode::BITSTREAM));
+
+class AudioStandardRoundTripTest : public testing::TestWithParam<AudioStandard> {};
+TEST_P(AudioStandardRoundTripTest, Aidl2Legacy2Aidl) {
+ const auto initial = GetParam();
+ auto conv = aidl2legacy_AudioStandard_audio_standard_t(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_standard_t_AudioStandard(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioStandard, AudioStandardRoundTripTest,
+ testing::Values(AudioStandard::NONE, AudioStandard::EDID));
+
+class AudioEncapsulationMetadataTypeRoundTripTest
+ : public testing::TestWithParam<AudioEncapsulationMetadataType> {};
+TEST_P(AudioEncapsulationMetadataTypeRoundTripTest, Aidl2Legacy2Aidl) {
+ const auto initial = GetParam();
+ auto conv =
+ aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
+ conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioEncapsulationMetadataType,
+ AudioEncapsulationMetadataTypeRoundTripTest,
+ testing::Values(AudioEncapsulationMetadataType::NONE,
+ AudioEncapsulationMetadataType::FRAMEWORK_TUNER,
+ AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR));
+
+class AudioGainModeRoundTripTest : public testing::TestWithParam<AudioGainMode> {};
+TEST_P(AudioGainModeRoundTripTest, Aidl2Legacy2Aidl) {
+ const auto initial = GetParam();
+ auto conv = aidl2legacy_AudioGainMode_audio_gain_mode_t(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_gain_mode_t_AudioGainMode(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioGainMode, AudioGainModeRoundTripTest,
+ testing::Values(AudioGainMode::JOINT, AudioGainMode::CHANNELS,
+ AudioGainMode::RAMP));
+
+TEST(AudioTrackSecondaryOutputInfoRoundTripTest, Aidl2Legacy2Aidl) {
+ const auto initial = make_TrackSecondaryOutputInfo();
+ auto conv = aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_TrackSecondaryOutputInfoPair_TrackSecondaryOutputInfo(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+
+using ExtraAudioDescriptorParam = std::tuple<AudioStandard, AudioEncapsulationType>;
+class ExtraAudioDescriptorRoundTripTest : public testing::TestWithParam<ExtraAudioDescriptorParam> {
+};
+TEST_P(ExtraAudioDescriptorRoundTripTest, Aidl2Legacy2Aidl) {
+ ExtraAudioDescriptor initial =
+ make_ExtraAudioDescriptor(std::get<0>(GetParam()), std::get<1>(GetParam()));
+ auto conv = aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ ExtraAudioDescriptor, ExtraAudioDescriptorRoundTripTest,
+ testing::Values(std::make_tuple(AudioStandard::NONE, AudioEncapsulationType::NONE),
+ std::make_tuple(AudioStandard::EDID, AudioEncapsulationType::NONE),
+ std::make_tuple(AudioStandard::EDID, AudioEncapsulationType::IEC61937)));
+
+TEST(AudioPortSessionExtRoundTripTest, Aidl2Legacy2Aidl) {
+ const int32_t initial = 7;
+ auto conv = aidl2legacy_int32_t_audio_port_session_ext(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_port_session_ext_int32_t(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+
+class AudioGainTest : public testing::TestWithParam<bool> {};
+TEST_P(AudioGainTest, Legacy2Aidl2Legacy) {
+ audio_port_v7 port;
+ port.num_gains = 2;
+ port.gains[0] = {.mode = AUDIO_GAIN_MODE_JOINT,
+ .channel_mask = AUDIO_CHANNEL_IN_STEREO,
+ .min_value = -3200,
+ .max_value = 600,
+ .default_value = 0,
+ .step_value = 100,
+ .min_ramp_ms = 10,
+ .max_ramp_ms = 20};
+ port.gains[1] = {.mode = AUDIO_GAIN_MODE_JOINT,
+ .channel_mask = AUDIO_CHANNEL_IN_MONO,
+ .min_value = -8800,
+ .max_value = 4000,
+ .default_value = 0,
+ .step_value = 100,
+ .min_ramp_ms = 192,
+ .max_ramp_ms = 224};
+
+ const auto isInput = GetParam();
+ for (int i = 0; i < port.num_gains; i++) {
+ auto initial = port.gains[i];
+ auto conv = legacy2aidl_audio_gain_AudioGain(initial, isInput);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = aidl2legacy_AudioGain_audio_gain(conv.value(), isInput);
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial.mode, convBack.value().mode);
+ EXPECT_EQ(initial.channel_mask, convBack.value().channel_mask);
+ EXPECT_EQ(initial.min_value, convBack.value().min_value);
+ EXPECT_EQ(initial.max_value, convBack.value().max_value);
+ EXPECT_EQ(initial.default_value, convBack.value().default_value);
+ EXPECT_EQ(initial.step_value, convBack.value().step_value);
+ EXPECT_EQ(initial.min_ramp_ms, convBack.value().min_ramp_ms);
+ EXPECT_EQ(initial.max_ramp_ms, convBack.value().max_ramp_ms);
+ }
+}
+INSTANTIATE_TEST_SUITE_P(AudioGain, AudioGainTest, testing::Values(true, false));
+
+TEST(AudioMicrophoneInfoFw, Aidl2Legacy2Aidl) {
+ media::MicrophoneInfoFw initial{};
+ // HALs must return at least 1 element in channelMapping. The zero value is 'UNUSED'.
+ initial.dynamic.channelMapping.resize(1);
+ auto conv = aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+
+TEST(AudioMicrophoneInfoFw, UnknownValues) {
+ {
+ media::MicrophoneInfoFw initial;
+ initial.dynamic.channelMapping.resize(1);
+ initial.info.indexInTheGroup = MicrophoneInfo::INDEX_IN_THE_GROUP_UNKNOWN;
+ auto conv = aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack =
+ legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+ }
+ for (const auto f : {&audio_microphone_characteristic_t::sensitivity,
+ &audio_microphone_characteristic_t::max_spl,
+ &audio_microphone_characteristic_t::min_spl}) {
+ audio_microphone_characteristic_t mic{};
+ if (f == &audio_microphone_characteristic_t::sensitivity) {
+ mic.*f = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN;
+ } else {
+ mic.*f = AUDIO_MICROPHONE_SPL_UNKNOWN;
+ }
+ auto aidl = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(mic);
+ ASSERT_TRUE(aidl.ok());
+ EXPECT_FALSE(aidl.value().info.sensitivity.has_value());
+ }
+ for (const auto f : {&audio_microphone_characteristic_t::geometric_location,
+ &audio_microphone_characteristic_t::orientation}) {
+ for (const auto c : {&audio_microphone_coordinate::x, &audio_microphone_coordinate::y,
+ &audio_microphone_coordinate::z}) {
+ audio_microphone_characteristic_t mic{};
+ mic.*f.*c = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
+ auto conv = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(mic);
+ ASSERT_TRUE(conv.ok());
+ const auto& aidl = conv.value();
+ if (f == &audio_microphone_characteristic_t::geometric_location) {
+ EXPECT_FALSE(aidl.info.position.has_value());
+ EXPECT_TRUE(aidl.info.orientation.has_value());
+ } else {
+ EXPECT_TRUE(aidl.info.position.has_value());
+ EXPECT_FALSE(aidl.info.orientation.has_value());
+ }
+ }
+ }
+}
+
+TEST(AudioMicrophoneInfoFw, ChannelMapping) {
+ audio_microphone_characteristic_t mic{};
+ mic.channel_mapping[1] = AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT;
+ mic.channel_mapping[3] = AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED;
+ auto conv = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(mic);
+ ASSERT_TRUE(conv.ok());
+ const auto& aidl = conv.value();
+ EXPECT_EQ(4, aidl.dynamic.channelMapping.size());
+ EXPECT_EQ(MicrophoneDynamicInfo::ChannelMapping::UNUSED, aidl.dynamic.channelMapping[0]);
+ EXPECT_EQ(MicrophoneDynamicInfo::ChannelMapping::DIRECT, aidl.dynamic.channelMapping[1]);
+ EXPECT_EQ(MicrophoneDynamicInfo::ChannelMapping::UNUSED, aidl.dynamic.channelMapping[2]);
+ EXPECT_EQ(MicrophoneDynamicInfo::ChannelMapping::PROCESSED, aidl.dynamic.channelMapping[3]);
+}
diff --git a/media/libaudioclient/tests/audio_aidl_status_tests.cpp b/media/libaudioclient/tests/audio_aidl_status_tests.cpp
index 5517091..8a7e6c1 100644
--- a/media/libaudioclient/tests/audio_aidl_status_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_status_tests.cpp
@@ -37,25 +37,10 @@
// Special status values are preserved on round trip.
TEST(audio_aidl_status_tests, statusRoundTripSpecialValues) {
- for (status_t status : {
- OK,
- UNKNOWN_ERROR,
- NO_MEMORY,
- INVALID_OPERATION,
- BAD_VALUE,
- BAD_TYPE,
- NAME_NOT_FOUND,
- PERMISSION_DENIED,
- NO_INIT,
- ALREADY_EXISTS,
- DEAD_OBJECT,
- FAILED_TRANSACTION,
- BAD_INDEX,
- NOT_ENOUGH_DATA,
- WOULD_BLOCK,
- TIMED_OUT,
- UNKNOWN_TRANSACTION,
- FDS_NOT_ALLOWED}) {
+ for (status_t status :
+ {OK, UNKNOWN_ERROR, NO_MEMORY, INVALID_OPERATION, BAD_VALUE, BAD_TYPE, NAME_NOT_FOUND,
+ PERMISSION_DENIED, NO_INIT, ALREADY_EXISTS, DEAD_OBJECT, FAILED_TRANSACTION, BAD_INDEX,
+ NOT_ENOUGH_DATA, WOULD_BLOCK, TIMED_OUT, UNKNOWN_TRANSACTION, FDS_NOT_ALLOWED}) {
ASSERT_EQ(status, statusTFromBinderStatus(binderStatusFromStatusT(status)));
}
}
@@ -63,47 +48,29 @@
// Binder exceptions show as an error (not fixed at this time); these come fromExceptionCode().
TEST(audio_aidl_status_tests, binderStatusExceptions) {
for (int exceptionCode : {
- //Status::EX_NONE,
- Status::EX_SECURITY,
- Status::EX_BAD_PARCELABLE,
- Status::EX_ILLEGAL_ARGUMENT,
- Status::EX_NULL_POINTER,
- Status::EX_ILLEGAL_STATE,
- Status::EX_NETWORK_MAIN_THREAD,
- Status::EX_UNSUPPORTED_OPERATION,
- //Status::EX_SERVICE_SPECIFIC, -- tested fromServiceSpecificError()
- Status::EX_PARCELABLE,
- // This is special and Java specific; see Parcel.java.
- Status::EX_HAS_REPLY_HEADER,
- // This is special, and indicates to C++ binder proxies that the
- // transaction has failed at a low level.
- //Status::EX_TRANSACTION_FAILED, -- tested fromStatusT().
- }) {
+ // Status::EX_NONE,
+ Status::EX_SECURITY, Status::EX_BAD_PARCELABLE, Status::EX_ILLEGAL_ARGUMENT,
+ Status::EX_NULL_POINTER, Status::EX_ILLEGAL_STATE, Status::EX_NETWORK_MAIN_THREAD,
+ Status::EX_UNSUPPORTED_OPERATION,
+ // Status::EX_SERVICE_SPECIFIC, -- tested fromServiceSpecificError()
+ Status::EX_PARCELABLE,
+ // This is special and Java specific; see Parcel.java.
+ Status::EX_HAS_REPLY_HEADER,
+ // This is special, and indicates to C++ binder proxies that the
+ // transaction has failed at a low level.
+ // Status::EX_TRANSACTION_FAILED, -- tested fromStatusT().
+ }) {
ASSERT_NE(OK, statusTFromBinderStatus(Status::fromExceptionCode(exceptionCode)));
}
}
// Binder transaction errors show exactly in status_t; these come fromStatusT().
TEST(audio_aidl_status_tests, binderStatusTransactionError) {
- for (status_t status : {
- OK, // Note: fromStatusT does check if this is 0, so this is no error.
- UNKNOWN_ERROR,
- NO_MEMORY,
- INVALID_OPERATION,
- BAD_VALUE,
- BAD_TYPE,
- NAME_NOT_FOUND,
- PERMISSION_DENIED,
- NO_INIT,
- ALREADY_EXISTS,
- DEAD_OBJECT,
- FAILED_TRANSACTION,
- BAD_INDEX,
- NOT_ENOUGH_DATA,
- WOULD_BLOCK,
- TIMED_OUT,
- UNKNOWN_TRANSACTION,
- FDS_NOT_ALLOWED}) {
+ for (status_t status :
+ {OK, // Note: fromStatusT does check if this is 0, so this is no error.
+ UNKNOWN_ERROR, NO_MEMORY, INVALID_OPERATION, BAD_VALUE, BAD_TYPE, NAME_NOT_FOUND,
+ PERMISSION_DENIED, NO_INIT, ALREADY_EXISTS, DEAD_OBJECT, FAILED_TRANSACTION, BAD_INDEX,
+ NOT_ENOUGH_DATA, WOULD_BLOCK, TIMED_OUT, UNKNOWN_TRANSACTION, FDS_NOT_ALLOWED}) {
ASSERT_EQ(status, statusTFromBinderStatus(Status::fromStatusT(status)));
}
}
diff --git a/media/libaudioclient/tests/audio_test_template.xml b/media/libaudioclient/tests/audio_test_template.xml
new file mode 100644
index 0000000..ed0cb21
--- /dev/null
+++ b/media/libaudioclient/tests/audio_test_template.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+<configuration description="Unit test configuration for {MODULE}">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="{MODULE}" value="/data/local/tmp/{MODULE}" />
+
+ <!-- Files used for audio testing -->
+ <option name="push-file" key="bbb_1ch_8kHz_s16le.raw" value="/data/local/tmp/bbb_1ch_8kHz_s16le.raw" />
+ <option name="push-file" key="bbb_2ch_24kHz_s16le.raw" value="/data/local/tmp/bbb_2ch_24kHz_s16le.raw" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="{MODULE}" />
+ </test>
+</configuration>
diff --git a/media/libaudioclient/tests/audio_test_utils.cpp b/media/libaudioclient/tests/audio_test_utils.cpp
new file mode 100644
index 0000000..1e26ff6
--- /dev/null
+++ b/media/libaudioclient/tests/audio_test_utils.cpp
@@ -0,0 +1,910 @@
+/*
+ * Copyright (C) 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 "AudioTestUtils"
+
+#include <android-base/file.h>
+#include <system/audio_config.h>
+#include <utils/Log.h>
+
+#include "audio_test_utils.h"
+
+#define WAIT_PERIOD_MS 10 // from AudioTrack.cpp
+#define MAX_WAIT_TIME_MS 5000
+
+template <class T>
+constexpr void (*xmlDeleter)(T* t);
+template <>
+constexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;
+template <>
+constexpr auto xmlDeleter<xmlChar> = [](xmlChar* s) { xmlFree(s); };
+
+/** @return a unique_ptr with the correct deleter for the libxml2 object. */
+template <class T>
+constexpr auto make_xmlUnique(T* t) {
+ // Wrap deleter in lambda to enable empty base optimization
+ auto deleter = [](T* t) { xmlDeleter<T>(t); };
+ return std::unique_ptr<T, decltype(deleter)>{t, deleter};
+}
+
+void OnAudioDeviceUpdateNotifier::onAudioDeviceUpdate(audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId) {
+ std::unique_lock<std::mutex> lock{mMutex};
+ ALOGD("%s audioIo=%d deviceId=%d", __func__, audioIo, deviceId);
+ mAudioIo = audioIo;
+ mDeviceId = deviceId;
+ mCondition.notify_all();
+}
+
+status_t OnAudioDeviceUpdateNotifier::waitForAudioDeviceCb(audio_port_handle_t expDeviceId) {
+ std::unique_lock<std::mutex> lock{mMutex};
+ if (mAudioIo == AUDIO_IO_HANDLE_NONE ||
+ (expDeviceId != AUDIO_PORT_HANDLE_NONE && expDeviceId != mDeviceId)) {
+ mCondition.wait_for(lock, std::chrono::milliseconds(500));
+ if (mAudioIo == AUDIO_IO_HANDLE_NONE ||
+ (expDeviceId != AUDIO_PORT_HANDLE_NONE && expDeviceId != mDeviceId))
+ return TIMED_OUT;
+ }
+ return OK;
+}
+
+AudioPlayback::AudioPlayback(uint32_t sampleRate, audio_format_t format,
+ audio_channel_mask_t channelMask, audio_output_flags_t flags,
+ audio_session_t sessionId, AudioTrack::transfer_type transferType,
+ audio_attributes_t* attributes, audio_offload_info_t* info)
+ : mSampleRate(sampleRate),
+ mFormat(format),
+ mChannelMask(channelMask),
+ mFlags(flags),
+ mSessionId(sessionId),
+ mTransferType(transferType),
+ mAttributes(attributes),
+ mOffloadInfo(info) {
+ mStopPlaying = false;
+ mBytesUsedSoFar = 0;
+ mState = PLAY_NO_INIT;
+ mMemCapacity = 0;
+ mMemoryDealer = nullptr;
+ mMemory = nullptr;
+}
+
+AudioPlayback::~AudioPlayback() {
+ stop();
+}
+
+status_t AudioPlayback::create() {
+ if (mState != PLAY_NO_INIT) return INVALID_OPERATION;
+ std::string packageName{"AudioPlayback"};
+ AttributionSourceState attributionSource;
+ attributionSource.packageName = packageName;
+ attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
+ attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
+ attributionSource.token = sp<BBinder>::make();
+ if (mTransferType == AudioTrack::TRANSFER_OBTAIN) {
+ mTrack = new AudioTrack(attributionSource);
+ mTrack->set(AUDIO_STREAM_MUSIC, mSampleRate, mFormat, mChannelMask, 0 /* frameCount */,
+ mFlags, nullptr /* callback */, 0 /* notificationFrames */,
+ nullptr /* sharedBuffer */, false /*canCallJava */, mSessionId, mTransferType,
+ mOffloadInfo, attributionSource, mAttributes);
+ } else if (mTransferType == AudioTrack::TRANSFER_SHARED) {
+ mTrack = new AudioTrack(AUDIO_STREAM_MUSIC, mSampleRate, mFormat, mChannelMask, mMemory,
+ mFlags, wp<AudioTrack::IAudioTrackCallback>::fromExisting(this), 0,
+ mSessionId, mTransferType, nullptr, attributionSource, mAttributes);
+ } else {
+ ALOGE("Test application is not handling transfer type %s",
+ AudioTrack::convertTransferToText(mTransferType));
+ return INVALID_OPERATION;
+ }
+ mTrack->setCallerName(packageName);
+ status_t status = mTrack->initCheck();
+ if (NO_ERROR == status) mState = PLAY_READY;
+ return status;
+}
+
+status_t AudioPlayback::loadResource(const char* name) {
+ status_t status = OK;
+ FILE* fp = fopen(name, "rbe");
+ struct stat buf {};
+ if (fp && !fstat(fileno(fp), &buf)) {
+ mMemCapacity = buf.st_size;
+ mMemoryDealer = new MemoryDealer(mMemCapacity, "AudioPlayback");
+ if (nullptr == mMemoryDealer.get()) {
+ ALOGE("couldn't get MemoryDealer!");
+ fclose(fp);
+ return NO_MEMORY;
+ }
+ mMemory = mMemoryDealer->allocate(mMemCapacity);
+ if (nullptr == mMemory.get()) {
+ ALOGE("couldn't get IMemory!");
+ fclose(fp);
+ return NO_MEMORY;
+ }
+ uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mMemory->unsecurePointer()));
+ fread(ipBuffer, sizeof(uint8_t), mMemCapacity, fp);
+ } else {
+ ALOGE("unable to open input file %s", name);
+ status = NAME_NOT_FOUND;
+ }
+ if (fp) fclose(fp);
+ return status;
+}
+
+sp<AudioTrack> AudioPlayback::getAudioTrackHandle() {
+ return (PLAY_NO_INIT != mState) ? mTrack : nullptr;
+}
+
+status_t AudioPlayback::start() {
+ status_t status;
+ if (PLAY_READY != mState) {
+ return INVALID_OPERATION;
+ } else {
+ status = mTrack->start();
+ if (OK == status) {
+ mState = PLAY_STARTED;
+ LOG_FATAL_IF(false != mTrack->stopped());
+ }
+ }
+ return status;
+}
+
+void AudioPlayback::onBufferEnd() {
+ std::unique_lock<std::mutex> lock{mMutex};
+ mStopPlaying = true;
+ mCondition.notify_all();
+}
+
+status_t AudioPlayback::fillBuffer() {
+ if (PLAY_STARTED != mState) return INVALID_OPERATION;
+ const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+ int counter = 0;
+ uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mMemory->unsecurePointer()));
+ size_t nonContig = 0;
+ size_t bytesAvailable = mMemCapacity - mBytesUsedSoFar;
+ while (bytesAvailable > 0) {
+ AudioTrack::Buffer trackBuffer;
+ trackBuffer.frameCount = mTrack->frameCount() * 2;
+ status_t status = mTrack->obtainBuffer(&trackBuffer, 1, &nonContig);
+ if (OK == status) {
+ size_t bytesToCopy = std::min(bytesAvailable, trackBuffer.size());
+ if (bytesToCopy > 0) {
+ memcpy(trackBuffer.data(), ipBuffer + mBytesUsedSoFar, bytesToCopy);
+ }
+ mTrack->releaseBuffer(&trackBuffer);
+ mBytesUsedSoFar += bytesToCopy;
+ bytesAvailable = mMemCapacity - mBytesUsedSoFar;
+ counter = 0;
+ } else if (WOULD_BLOCK == status) {
+ // if not received a buffer for MAX_WAIT_TIME_MS, something has gone wrong
+ if (counter == maxTries) return TIMED_OUT;
+ counter++;
+ }
+ }
+ return OK;
+}
+
+status_t AudioPlayback::waitForConsumption(bool testSeek) {
+ if (PLAY_STARTED != mState) return INVALID_OPERATION;
+
+ const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+ int counter = 0;
+ size_t totalFrameCount = mMemCapacity / mTrack->frameSize();
+ while (!mStopPlaying && counter < maxTries) {
+ uint32_t currPosition;
+ mTrack->getPosition(&currPosition);
+ if (currPosition >= totalFrameCount) counter++;
+
+ if (testSeek && (currPosition > totalFrameCount * 0.6)) {
+ testSeek = false;
+ if (!mTrack->hasStarted()) return BAD_VALUE;
+ mTrack->pauseAndWait(std::chrono::seconds(2));
+ if (mTrack->hasStarted()) return BAD_VALUE;
+ mTrack->reload();
+ mTrack->getPosition(&currPosition);
+ if (currPosition != 0) return BAD_VALUE;
+ mTrack->start();
+ while (currPosition < totalFrameCount * 0.3) {
+ mTrack->getPosition(&currPosition);
+ }
+ mTrack->pauseAndWait(std::chrono::seconds(2));
+ uint32_t setPosition = totalFrameCount * 0.9;
+ mTrack->setPosition(setPosition);
+ uint32_t bufferPosition;
+ mTrack->getBufferPosition(&bufferPosition);
+ if (bufferPosition != setPosition) return BAD_VALUE;
+ mTrack->start();
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_PERIOD_MS));
+ }
+ if (!mStopPlaying && counter == maxTries) return TIMED_OUT;
+ return OK;
+}
+
+status_t AudioPlayback::onProcess(bool testSeek) {
+ if (mTransferType == AudioTrack::TRANSFER_SHARED)
+ return waitForConsumption(testSeek);
+ else if (mTransferType == AudioTrack::TRANSFER_OBTAIN)
+ return fillBuffer();
+ else
+ return INVALID_OPERATION;
+}
+
+void AudioPlayback::stop() {
+ std::unique_lock<std::mutex> lock{mMutex};
+ mStopPlaying = true;
+ if (mState != PLAY_STOPPED && mState != PLAY_NO_INIT) {
+ int32_t msec = 0;
+ (void)mTrack->pendingDuration(&msec);
+ mTrack->stopAndJoinCallbacks();
+ LOG_FATAL_IF(true != mTrack->stopped());
+ mState = PLAY_STOPPED;
+ if (msec > 0) {
+ ALOGD("deleting recycled track, waiting for data drain (%d msec)", msec);
+ usleep(msec * 1000LL);
+ }
+ }
+}
+
+// hold pcm data sent by AudioRecord
+RawBuffer::RawBuffer(int64_t ptsPipeline, int64_t ptsManual, int32_t capacity)
+ : mData(capacity > 0 ? new uint8_t[capacity] : nullptr),
+ mPtsPipeline(ptsPipeline),
+ mPtsManual(ptsManual),
+ mCapacity(capacity) {}
+
+// Simple AudioCapture
+size_t AudioCapture::onMoreData(const AudioRecord::Buffer& buffer) {
+ if (mState != REC_STARTED) {
+ ALOGE("Unexpected Callback from audiorecord, not reading data");
+ return 0;
+ }
+
+ // no more frames to read
+ if (mNumFramesReceived >= mNumFramesToRecord || mStopRecording) {
+ mStopRecording = true;
+ return 0;
+ }
+
+ int64_t timeUs = 0, position = 0, timeNs = 0;
+ ExtendedTimestamp ts;
+ ExtendedTimestamp::Location location;
+ const int32_t usPerSec = 1000000;
+
+ if (mRecord->getTimestamp(&ts) == OK &&
+ ts.getBestTimestamp(&position, &timeNs, ExtendedTimestamp::TIMEBASE_MONOTONIC, &location) ==
+ OK) {
+ // Use audio timestamp.
+ timeUs = timeNs / 1000 -
+ (position - mNumFramesReceived + mNumFramesLost) * usPerSec / mSampleRate;
+ } else {
+ // This should not happen in normal case.
+ ALOGW("Failed to get audio timestamp, fallback to use systemclock");
+ timeUs = systemTime() / 1000LL;
+ // Estimate the real sampling time of the 1st sample in this buffer
+ // from AudioRecord's latency. (Apply this adjustment first so that
+ // the start time logic is not affected.)
+ timeUs -= mRecord->latency() * 1000LL;
+ }
+
+ ALOGV("dataCallbackTimestamp: %" PRId64 " us", timeUs);
+
+ const size_t frameSize = mRecord->frameSize();
+ uint64_t numLostBytes = (uint64_t)mRecord->getInputFramesLost() * frameSize;
+ if (numLostBytes > 0) {
+ ALOGW("Lost audio record data: %" PRIu64 " bytes", numLostBytes);
+ }
+ std::deque<RawBuffer> tmpQueue;
+ while (numLostBytes > 0) {
+ uint64_t bufferSize = numLostBytes;
+ if (numLostBytes > mMaxBytesPerCallback) {
+ numLostBytes -= mMaxBytesPerCallback;
+ bufferSize = mMaxBytesPerCallback;
+ } else {
+ numLostBytes = 0;
+ }
+ const int64_t timestampUs =
+ ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
+ mRecord->getSampleRate();
+ RawBuffer emptyBuffer{timeUs, timestampUs, static_cast<int32_t>(bufferSize)};
+ memset(emptyBuffer.mData.get(), 0, bufferSize);
+ mNumFramesLost += bufferSize / frameSize;
+ mNumFramesReceived += bufferSize / frameSize;
+ tmpQueue.push_back(std::move(emptyBuffer));
+ }
+
+ if (buffer.size() == 0) {
+ ALOGW("Nothing is available from AudioRecord callback buffer");
+ } else {
+ const size_t bufferSize = buffer.size();
+ const int64_t timestampUs =
+ ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
+ mRecord->getSampleRate();
+ RawBuffer audioBuffer{timeUs, timestampUs, static_cast<int32_t>(bufferSize)};
+ memcpy(audioBuffer.mData.get(), buffer.data(), bufferSize);
+ mNumFramesReceived += bufferSize / frameSize;
+ tmpQueue.push_back(std::move(audioBuffer));
+ }
+
+ if (tmpQueue.size() > 0) {
+ std::unique_lock<std::mutex> lock{mMutex};
+ for (auto it = tmpQueue.begin(); it != tmpQueue.end(); it++)
+ mBuffersReceived.push_back(std::move(*it));
+ mCondition.notify_all();
+ }
+ return buffer.size();
+}
+
+void AudioCapture::onOverrun() {
+ ALOGV("received event overrun");
+ mBufferOverrun = true;
+}
+
+void AudioCapture::onMarker(uint32_t markerPosition) {
+ ALOGV("received Callback at position %d", markerPosition);
+ mReceivedCbMarkerAtPosition = markerPosition;
+}
+
+void AudioCapture::onNewPos(uint32_t markerPosition) {
+ ALOGV("received Callback at position %d", markerPosition);
+ mReceivedCbMarkerCount++;
+}
+
+void AudioCapture::onNewIAudioRecord() {
+ ALOGV("IAudioRecord is re-created");
+}
+
+AudioCapture::AudioCapture(audio_source_t inputSource, uint32_t sampleRate, audio_format_t format,
+ audio_channel_mask_t channelMask, audio_input_flags_t flags,
+ audio_session_t sessionId, AudioRecord::transfer_type transferType,
+ const audio_attributes_t* attributes)
+ : mInputSource(inputSource),
+ mSampleRate(sampleRate),
+ mFormat(format),
+ mChannelMask(channelMask),
+ mFlags(flags),
+ mSessionId(sessionId),
+ mTransferType(transferType),
+ mAttributes(attributes) {
+ mFrameCount = 0;
+ mNotificationFrames = 0;
+ mNumFramesToRecord = 0;
+ mNumFramesReceived = 0;
+ mNumFramesLost = 0;
+ mBufferOverrun = false;
+ mMarkerPosition = 0;
+ mMarkerPeriod = 0;
+ mReceivedCbMarkerAtPosition = -1;
+ mReceivedCbMarkerCount = 0;
+ mState = REC_NO_INIT;
+ mStopRecording = false;
+}
+
+AudioCapture::~AudioCapture() {
+ if (mOutFileFd > 0) close(mOutFileFd);
+ stop();
+}
+
+status_t AudioCapture::create() {
+ if (mState != REC_NO_INIT) return INVALID_OPERATION;
+ // get Min Frame Count
+ size_t minFrameCount;
+ status_t status =
+ AudioRecord::getMinFrameCount(&minFrameCount, mSampleRate, mFormat, mChannelMask);
+ if (NO_ERROR != status) return status;
+ // Limit notificationFrames basing on client bufferSize
+ const int samplesPerFrame = audio_channel_count_from_in_mask(mChannelMask);
+ const int bytesPerSample = audio_bytes_per_sample(mFormat);
+ mNotificationFrames = mMaxBytesPerCallback / (samplesPerFrame * bytesPerSample);
+ // select frameCount to be at least minFrameCount
+ mFrameCount = 2 * mNotificationFrames;
+ while (mFrameCount < minFrameCount) {
+ mFrameCount += mNotificationFrames;
+ }
+ if (mFlags & AUDIO_INPUT_FLAG_FAST) {
+ ALOGW("Overriding all previous computations");
+ mFrameCount = 0;
+ mNotificationFrames = 0;
+ }
+ mNumFramesToRecord = (mSampleRate * 0.25); // record .25 sec
+ std::string packageName{"AudioCapture"};
+ AttributionSourceState attributionSource;
+ attributionSource.packageName = packageName;
+ attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
+ attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
+ attributionSource.token = sp<BBinder>::make();
+ if (mTransferType == AudioRecord::TRANSFER_OBTAIN) {
+ if (mSampleRate == 48000) { // test all available constructors
+ mRecord = new AudioRecord(mInputSource, mSampleRate, mFormat, mChannelMask,
+ attributionSource, mFrameCount, nullptr /* callback */,
+ mNotificationFrames, mSessionId, mTransferType, mFlags,
+ mAttributes);
+ } else {
+ mRecord = new AudioRecord(attributionSource);
+ status = mRecord->set(mInputSource, mSampleRate, mFormat, mChannelMask, mFrameCount,
+ nullptr /* callback */, 0 /* notificationFrames */,
+ false /* canCallJava */, mSessionId, mTransferType, mFlags,
+ attributionSource.uid, attributionSource.pid, mAttributes);
+ }
+ if (NO_ERROR != status) return status;
+ } else if (mTransferType == AudioRecord::TRANSFER_CALLBACK) {
+ mRecord = new AudioRecord(mInputSource, mSampleRate, mFormat, mChannelMask,
+ attributionSource, mFrameCount, this, mNotificationFrames,
+ mSessionId, mTransferType, mFlags, mAttributes);
+ } else {
+ ALOGE("Test application is not handling transfer type %s",
+ AudioRecord::convertTransferToText(mTransferType));
+ return NO_INIT;
+ }
+ mRecord->setCallerName(packageName);
+ status = mRecord->initCheck();
+ if (NO_ERROR == status) mState = REC_READY;
+ if (mFlags & AUDIO_INPUT_FLAG_FAST) {
+ mFrameCount = mRecord->frameCount();
+ mNotificationFrames = mRecord->getNotificationPeriodInFrames();
+ mMaxBytesPerCallback = mNotificationFrames * samplesPerFrame * bytesPerSample;
+ }
+ return status;
+}
+
+status_t AudioCapture::setRecordDuration(float durationInSec) {
+ if (REC_READY != mState) {
+ return INVALID_OPERATION;
+ }
+ uint32_t sampleRate = mSampleRate == 0 ? mRecord->getSampleRate() : mSampleRate;
+ mNumFramesToRecord = (sampleRate * durationInSec);
+ return OK;
+}
+
+status_t AudioCapture::enableRecordDump() {
+ if (mOutFileFd != -1) {
+ return INVALID_OPERATION;
+ }
+ TemporaryFile tf("/data/local/tmp");
+ tf.DoNotRemove();
+ mOutFileFd = tf.release();
+ mFileName = std::string{tf.path};
+ return OK;
+}
+
+sp<AudioRecord> AudioCapture::getAudioRecordHandle() {
+ return (REC_NO_INIT == mState) ? nullptr : mRecord;
+}
+
+status_t AudioCapture::start(AudioSystem::sync_event_t event, audio_session_t triggerSession) {
+ status_t status;
+ if (REC_READY != mState) {
+ return INVALID_OPERATION;
+ } else {
+ status = mRecord->start(event, triggerSession);
+ if (OK == status) {
+ mState = REC_STARTED;
+ LOG_FATAL_IF(false != mRecord->stopped());
+ }
+ }
+ return status;
+}
+
+status_t AudioCapture::stop() {
+ status_t status = OK;
+ mStopRecording = true;
+ if (mState != REC_STOPPED && mState != REC_NO_INIT) {
+ if (mInputSource != AUDIO_SOURCE_DEFAULT) {
+ bool state = false;
+ status = AudioSystem::isSourceActive(mInputSource, &state);
+ if (status == OK && !state) status = BAD_VALUE;
+ }
+ mRecord->stopAndJoinCallbacks();
+ mState = REC_STOPPED;
+ LOG_FATAL_IF(true != mRecord->stopped());
+ }
+ return status;
+}
+
+status_t AudioCapture::obtainBuffer(RawBuffer& buffer) {
+ if (REC_STARTED != mState) return INVALID_OPERATION;
+ const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+ int counter = 0;
+ size_t nonContig = 0;
+ while (mNumFramesReceived < mNumFramesToRecord) {
+ AudioRecord::Buffer recordBuffer;
+ recordBuffer.frameCount = mNotificationFrames;
+ status_t status = mRecord->obtainBuffer(&recordBuffer, 1, &nonContig);
+ if (OK == status) {
+ const int64_t timestampUs =
+ ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
+ mRecord->getSampleRate();
+ RawBuffer buff{-1, timestampUs, static_cast<int32_t>(recordBuffer.size())};
+ memcpy(buff.mData.get(), recordBuffer.data(), recordBuffer.size());
+ buffer = std::move(buff);
+ mNumFramesReceived += recordBuffer.size() / mRecord->frameSize();
+ mRecord->releaseBuffer(&recordBuffer);
+ counter = 0;
+ } else if (WOULD_BLOCK == status) {
+ // if not received a buffer for MAX_WAIT_TIME_MS, something has gone wrong
+ if (counter == maxTries) return TIMED_OUT;
+ counter++;
+ }
+ }
+ return OK;
+}
+
+status_t AudioCapture::obtainBufferCb(RawBuffer& buffer) {
+ if (REC_STARTED != mState) return INVALID_OPERATION;
+ const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+ int counter = 0;
+ std::unique_lock<std::mutex> lock{mMutex};
+ while (mBuffersReceived.empty() && !mStopRecording && counter < maxTries) {
+ mCondition.wait_for(lock, std::chrono::milliseconds(WAIT_PERIOD_MS));
+ counter++;
+ }
+ if (!mBuffersReceived.empty()) {
+ auto it = mBuffersReceived.begin();
+ buffer = std::move(*it);
+ mBuffersReceived.erase(it);
+ } else {
+ if (!mStopRecording && counter == maxTries) return TIMED_OUT;
+ }
+ return OK;
+}
+
+status_t AudioCapture::audioProcess() {
+ RawBuffer buffer;
+ status_t status = OK;
+ while (mNumFramesReceived < mNumFramesToRecord && status == OK) {
+ if (mTransferType == AudioRecord::TRANSFER_CALLBACK)
+ status = obtainBufferCb(buffer);
+ else
+ status = obtainBuffer(buffer);
+ if (OK == status && mOutFileFd > 0) {
+ const char* ptr = static_cast<const char*>(static_cast<void*>(buffer.mData.get()));
+ write(mOutFileFd, ptr, buffer.mCapacity);
+ }
+ }
+ return OK;
+}
+
+status_t listAudioPorts(std::vector<audio_port_v7>& portsVec) {
+ int attempts = 5;
+ status_t status;
+ unsigned int generation1, generation;
+ unsigned int numPorts = 0;
+ do {
+ if (attempts-- < 0) {
+ status = TIMED_OUT;
+ break;
+ }
+ status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_NONE, &numPorts,
+ nullptr, &generation1);
+ if (status != NO_ERROR) {
+ ALOGE("AudioSystem::listAudioPorts returned error %d", status);
+ break;
+ }
+ portsVec.resize(numPorts);
+ status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_NONE, &numPorts,
+ portsVec.data(), &generation);
+ } while (generation1 != generation && status == NO_ERROR);
+ if (status != NO_ERROR) {
+ numPorts = 0;
+ portsVec.clear();
+ }
+ return status;
+}
+
+status_t getPortById(const audio_port_handle_t portId, audio_port_v7& port) {
+ std::vector<struct audio_port_v7> ports;
+ status_t status = listAudioPorts(ports);
+ if (status != OK) return status;
+ for (auto i = 0; i < ports.size(); i++) {
+ if (ports[i].id == portId) {
+ port = ports[i];
+ return OK;
+ }
+ }
+ return BAD_VALUE;
+}
+
+status_t getPortByAttributes(audio_port_role_t role, audio_port_type_t type,
+ audio_devices_t deviceType, const std::string& address,
+ audio_port_v7& port) {
+ std::vector<struct audio_port_v7> ports;
+ status_t status = listAudioPorts(ports);
+ if (status != OK) return status;
+ for (auto i = 0; i < ports.size(); i++) {
+ if (ports[i].role == role && ports[i].type == type &&
+ ports[i].ext.device.type == deviceType &&
+ !strncmp(ports[i].ext.device.address, address.c_str(), AUDIO_DEVICE_MAX_ADDRESS_LEN)) {
+ port = ports[i];
+ return OK;
+ }
+ }
+ return BAD_VALUE;
+}
+
+status_t listAudioPatches(std::vector<struct audio_patch>& patchesVec) {
+ int attempts = 5;
+ status_t status;
+ unsigned int generation1, generation;
+ unsigned int numPatches = 0;
+ do {
+ if (attempts-- < 0) {
+ status = TIMED_OUT;
+ break;
+ }
+ status = AudioSystem::listAudioPatches(&numPatches, nullptr, &generation1);
+ if (status != NO_ERROR) {
+ ALOGE("AudioSystem::listAudioPatches returned error %d", status);
+ break;
+ }
+ patchesVec.resize(numPatches);
+ status = AudioSystem::listAudioPatches(&numPatches, patchesVec.data(), &generation);
+ } while (generation1 != generation && status == NO_ERROR);
+ if (status != NO_ERROR) {
+ numPatches = 0;
+ patchesVec.clear();
+ }
+ return status;
+}
+
+status_t getPatchForOutputMix(audio_io_handle_t audioIo, audio_patch& patch) {
+ std::vector<struct audio_patch> patches;
+ status_t status = listAudioPatches(patches);
+ if (status != OK) return status;
+
+ for (auto i = 0; i < patches.size(); i++) {
+ for (auto j = 0; j < patches[i].num_sources; j++) {
+ if (patches[i].sources[j].type == AUDIO_PORT_TYPE_MIX &&
+ patches[i].sources[j].ext.mix.handle == audioIo) {
+ patch = patches[i];
+ return OK;
+ }
+ }
+ }
+ return BAD_VALUE;
+}
+
+status_t getPatchForInputMix(audio_io_handle_t audioIo, audio_patch& patch) {
+ std::vector<struct audio_patch> patches;
+ status_t status = listAudioPatches(patches);
+ if (status != OK) return status;
+
+ for (auto i = 0; i < patches.size(); i++) {
+ for (auto j = 0; j < patches[i].num_sinks; j++) {
+ if (patches[i].sinks[j].type == AUDIO_PORT_TYPE_MIX &&
+ patches[i].sinks[j].ext.mix.handle == audioIo) {
+ patch = patches[i];
+ return OK;
+ }
+ }
+ }
+ return BAD_VALUE;
+}
+
+bool patchContainsOutputDevice(audio_port_handle_t deviceId, audio_patch patch) {
+ for (auto j = 0; j < patch.num_sinks; j++) {
+ if (patch.sinks[j].type == AUDIO_PORT_TYPE_DEVICE && patch.sinks[j].id == deviceId) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool patchContainsInputDevice(audio_port_handle_t deviceId, audio_patch patch) {
+ for (auto j = 0; j < patch.num_sources; j++) {
+ if (patch.sources[j].type == AUDIO_PORT_TYPE_DEVICE && patch.sources[j].id == deviceId) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool checkPatchPlayback(audio_io_handle_t audioIo, audio_port_handle_t deviceId) {
+ struct audio_patch patch;
+ if (getPatchForOutputMix(audioIo, patch) == OK) {
+ return patchContainsOutputDevice(deviceId, patch);
+ }
+ return false;
+}
+
+bool checkPatchCapture(audio_io_handle_t audioIo, audio_port_handle_t deviceId) {
+ struct audio_patch patch;
+ if (getPatchForInputMix(audioIo, patch) == OK) {
+ return patchContainsInputDevice(deviceId, patch);
+ }
+ return false;
+}
+
+std::string dumpPortConfig(const audio_port_config& port) {
+ std::ostringstream result;
+ std::string deviceInfo;
+ if (port.type == AUDIO_PORT_TYPE_DEVICE) {
+ if (port.ext.device.type & AUDIO_DEVICE_BIT_IN) {
+ InputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
+ } else {
+ OutputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
+ }
+ deviceInfo += std::string(", address = ") + port.ext.device.address;
+ }
+ result << "audio_port_handle_t = " << port.id << ", "
+ << "Role = " << (port.role == AUDIO_PORT_ROLE_SOURCE ? "source" : "sink") << ", "
+ << "Type = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix") << ", "
+ << "deviceInfo = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? deviceInfo : "") << ", "
+ << "config_mask = 0x" << std::hex << port.config_mask << std::dec << ", ";
+ if (port.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
+ result << "sample rate = " << port.sample_rate << ", ";
+ }
+ if (port.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
+ result << "channel mask = " << port.channel_mask << ", ";
+ }
+ if (port.config_mask & AUDIO_PORT_CONFIG_FORMAT) {
+ result << "format = " << port.format << ", ";
+ }
+ result << "input flags = " << port.flags.input << ", ";
+ result << "output flags = " << port.flags.output << ", ";
+ result << "mix io handle = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? 0 : port.ext.mix.handle)
+ << "\n";
+ return result.str();
+}
+
+std::string dumpPatch(const audio_patch& patch) {
+ std::ostringstream result;
+ result << "----------------- Dumping Patch ------------ \n";
+ result << "Patch Handle: " << patch.id << ", sources: " << patch.num_sources
+ << ", sink: " << patch.num_sinks << "\n";
+ audio_port_v7 port;
+ for (uint32_t i = 0; i < patch.num_sources; i++) {
+ result << "----------------- Dumping Source Port Config @ index " << i
+ << " ------------ \n";
+ result << dumpPortConfig(patch.sources[i]);
+ result << "----------------- Dumping Source Port for id " << patch.sources[i].id
+ << " ------------ \n";
+ getPortById(patch.sources[i].id, port);
+ result << dumpPort(port);
+ }
+ for (uint32_t i = 0; i < patch.num_sinks; i++) {
+ result << "----------------- Dumping Sink Port Config @ index " << i << " ------------ \n";
+ result << dumpPortConfig(patch.sinks[i]);
+ result << "----------------- Dumping Sink Port for id " << patch.sinks[i].id
+ << " ------------ \n";
+ getPortById(patch.sinks[i].id, port);
+ result << dumpPort(port);
+ }
+ return result.str();
+}
+
+std::string dumpPort(const audio_port_v7& port) {
+ std::ostringstream result;
+ std::string deviceInfo;
+ if (port.type == AUDIO_PORT_TYPE_DEVICE) {
+ if (port.ext.device.type & AUDIO_DEVICE_BIT_IN) {
+ InputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
+ } else {
+ OutputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
+ }
+ deviceInfo += std::string(", address = ") + port.ext.device.address;
+ }
+ result << "audio_port_handle_t = " << port.id << ", "
+ << "Role = " << (port.role == AUDIO_PORT_ROLE_SOURCE ? "source" : "sink") << ", "
+ << "Type = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix") << ", "
+ << "deviceInfo = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? deviceInfo : "") << ", "
+ << "Name = " << port.name << ", "
+ << "num profiles = " << port.num_audio_profiles << ", "
+ << "mix io handle = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? 0 : port.ext.mix.handle)
+ << ", ";
+ for (int i = 0; i < port.num_audio_profiles; i++) {
+ result << "AudioProfile = " << i << " {";
+ result << "format = " << port.audio_profiles[i].format << ", ";
+ result << "samplerates = ";
+ for (int j = 0; j < port.audio_profiles[i].num_sample_rates; j++) {
+ result << port.audio_profiles[i].sample_rates[j] << ", ";
+ }
+ result << "channelmasks = ";
+ for (int j = 0; j < port.audio_profiles[i].num_channel_masks; j++) {
+ result << "0x" << std::hex << port.audio_profiles[i].channel_masks[j] << std::dec
+ << ", ";
+ }
+ result << "} ";
+ }
+ result << dumpPortConfig(port.active_config);
+ return result.str();
+}
+
+std::string getXmlAttribute(const xmlNode* cur, const char* attribute) {
+ auto charPtr = make_xmlUnique(xmlGetProp(cur, reinterpret_cast<const xmlChar*>(attribute)));
+ if (charPtr == NULL) {
+ return "";
+ }
+ std::string value(reinterpret_cast<const char*>(charPtr.get()));
+ return value;
+}
+
+status_t parse_audio_policy_configuration_xml(std::vector<std::string>& attachedDevices,
+ std::vector<MixPort>& mixPorts,
+ std::vector<Route>& routes) {
+ std::string path = audio_find_readable_configuration_file("audio_policy_configuration.xml");
+ if (path.length() == 0) return UNKNOWN_ERROR;
+ auto doc = make_xmlUnique(xmlParseFile(path.c_str()));
+ if (doc == nullptr) return UNKNOWN_ERROR;
+ xmlNode* root = xmlDocGetRootElement(doc.get());
+ if (root == nullptr) return UNKNOWN_ERROR;
+ if (xmlXIncludeProcess(doc.get()) < 0) return UNKNOWN_ERROR;
+ mixPorts.clear();
+ if (!xmlStrcmp(root->name, reinterpret_cast<const xmlChar*>("audioPolicyConfiguration"))) {
+ std::string raw{getXmlAttribute(root, "version")};
+ for (auto* child = root->xmlChildrenNode; child != nullptr; child = child->next) {
+ if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("modules"))) {
+ xmlNode* root = child;
+ for (auto* child = root->xmlChildrenNode; child != nullptr; child = child->next) {
+ if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("module"))) {
+ xmlNode* root = child;
+ for (auto* child = root->xmlChildrenNode; child != nullptr;
+ child = child->next) {
+ if (!xmlStrcmp(child->name,
+ reinterpret_cast<const xmlChar*>("mixPorts"))) {
+ xmlNode* root = child;
+ for (auto* child = root->xmlChildrenNode; child != nullptr;
+ child = child->next) {
+ if (!xmlStrcmp(child->name,
+ reinterpret_cast<const xmlChar*>("mixPort"))) {
+ MixPort mixPort;
+ xmlNode* root = child;
+ mixPort.name = getXmlAttribute(root, "name");
+ mixPort.role = getXmlAttribute(root, "role");
+ mixPort.flags = getXmlAttribute(root, "flags");
+ if (mixPort.role == "source") mixPorts.push_back(mixPort);
+ }
+ }
+ } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(
+ "attachedDevices"))) {
+ xmlNode* root = child;
+ for (auto* child = root->xmlChildrenNode; child != nullptr;
+ child = child->next) {
+ if (!xmlStrcmp(child->name,
+ reinterpret_cast<const xmlChar*>("item"))) {
+ auto xmlValue = make_xmlUnique(xmlNodeListGetString(
+ child->doc, child->xmlChildrenNode, 1));
+ if (xmlValue == nullptr) {
+ raw = "";
+ } else {
+ raw = reinterpret_cast<const char*>(xmlValue.get());
+ }
+ std::string& value = raw;
+ attachedDevices.push_back(std::move(value));
+ }
+ }
+ } else if (!xmlStrcmp(child->name,
+ reinterpret_cast<const xmlChar*>("routes"))) {
+ xmlNode* root = child;
+ for (auto* child = root->xmlChildrenNode; child != nullptr;
+ child = child->next) {
+ if (!xmlStrcmp(child->name,
+ reinterpret_cast<const xmlChar*>("route"))) {
+ Route route;
+ xmlNode* root = child;
+ route.name = getXmlAttribute(root, "name");
+ route.sources = getXmlAttribute(root, "sources");
+ route.sink = getXmlAttribute(root, "sink");
+ routes.push_back(route);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return OK;
+}
diff --git a/media/libaudioclient/tests/audio_test_utils.h b/media/libaudioclient/tests/audio_test_utils.h
new file mode 100644
index 0000000..90c30c2
--- /dev/null
+++ b/media/libaudioclient/tests/audio_test_utils.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef AUDIO_TEST_UTILS_H_
+#define AUDIO_TEST_UTILS_H_
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <atomic>
+#include <chrono>
+#include <cinttypes>
+#include <deque>
+#include <memory>
+#include <mutex>
+#include <thread>
+
+#include <binder/MemoryDealer.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+#include <media/AidlConversion.h>
+#include <media/AudioRecord.h>
+#include <media/AudioTrack.h>
+
+using namespace android;
+
+struct MixPort {
+ std::string name;
+ std::string role;
+ std::string flags;
+};
+
+struct Route {
+ std::string name;
+ std::string sources;
+ std::string sink;
+};
+
+status_t parse_audio_policy_configuration_xml(std::vector<std::string>& attachedDevices,
+ std::vector<MixPort>& mixPorts,
+ std::vector<Route>& routes);
+status_t listAudioPorts(std::vector<audio_port_v7>& portsVec);
+status_t listAudioPatches(std::vector<struct audio_patch>& patchesVec);
+status_t getPortByAttributes(audio_port_role_t role, audio_port_type_t type,
+ audio_devices_t deviceType, const std::string& address,
+ audio_port_v7& port);
+status_t getPatchForOutputMix(audio_io_handle_t audioIo, audio_patch& patch);
+status_t getPatchForInputMix(audio_io_handle_t audioIo, audio_patch& patch);
+bool patchContainsOutputDevice(audio_port_handle_t deviceId, audio_patch patch);
+bool patchContainsInputDevice(audio_port_handle_t deviceId, audio_patch patch);
+bool checkPatchPlayback(audio_io_handle_t audioIo, audio_port_handle_t deviceId);
+bool checkPatchCapture(audio_io_handle_t audioIo, audio_port_handle_t deviceId);
+std::string dumpPort(const audio_port_v7& port);
+std::string dumpPortConfig(const audio_port_config& port);
+std::string dumpPatch(const audio_patch& patch);
+
+class OnAudioDeviceUpdateNotifier : public AudioSystem::AudioDeviceCallback {
+ public:
+ audio_io_handle_t mAudioIo = AUDIO_IO_HANDLE_NONE;
+ audio_port_handle_t mDeviceId = AUDIO_PORT_HANDLE_NONE;
+ std::mutex mMutex;
+ std::condition_variable mCondition;
+
+ void onAudioDeviceUpdate(audio_io_handle_t audioIo, audio_port_handle_t deviceId);
+ status_t waitForAudioDeviceCb(audio_port_handle_t expDeviceId = AUDIO_PORT_HANDLE_NONE);
+};
+
+// Simple AudioPlayback class.
+class AudioPlayback : public AudioTrack::IAudioTrackCallback {
+ friend sp<AudioPlayback>;
+ AudioPlayback(uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask,
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+ audio_session_t sessionId = AUDIO_SESSION_NONE,
+ AudioTrack::transfer_type transferType = AudioTrack::TRANSFER_SHARED,
+ audio_attributes_t* attributes = nullptr, audio_offload_info_t* info = nullptr);
+
+ public:
+ status_t loadResource(const char* name);
+ status_t create();
+ sp<AudioTrack> getAudioTrackHandle();
+ status_t start();
+ status_t waitForConsumption(bool testSeek = false);
+ status_t fillBuffer();
+ status_t onProcess(bool testSeek = false);
+ virtual void onBufferEnd() override;
+ void stop();
+
+ bool mStopPlaying;
+ std::mutex mMutex;
+ std::condition_variable mCondition;
+
+ enum State {
+ PLAY_NO_INIT,
+ PLAY_READY,
+ PLAY_STARTED,
+ PLAY_STOPPED,
+ };
+
+ private:
+ ~AudioPlayback();
+ const uint32_t mSampleRate;
+ const audio_format_t mFormat;
+ const audio_channel_mask_t mChannelMask;
+ const audio_output_flags_t mFlags;
+ const audio_session_t mSessionId;
+ const AudioTrack::transfer_type mTransferType;
+ const audio_attributes_t* mAttributes;
+ const audio_offload_info_t* mOffloadInfo;
+
+ size_t mBytesUsedSoFar;
+ State mState;
+ size_t mMemCapacity;
+ sp<MemoryDealer> mMemoryDealer;
+ sp<IMemory> mMemory;
+
+ sp<AudioTrack> mTrack;
+};
+
+// hold pcm data sent by AudioRecord
+class RawBuffer {
+ public:
+ RawBuffer(int64_t ptsPipeline = -1, int64_t ptsManual = -1, int32_t capacity = 0);
+
+ std::unique_ptr<uint8_t[]> mData;
+ int64_t mPtsPipeline;
+ int64_t mPtsManual;
+ int32_t mCapacity;
+};
+
+// Simple AudioCapture
+class AudioCapture : public AudioRecord::IAudioRecordCallback {
+ public:
+ AudioCapture(audio_source_t inputSource, uint32_t sampleRate, audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
+ audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
+ AudioRecord::transfer_type transferType = AudioRecord::TRANSFER_CALLBACK,
+ const audio_attributes_t* attributes = nullptr);
+ ~AudioCapture();
+ size_t onMoreData(const AudioRecord::Buffer& buffer) override;
+ void onOverrun() override;
+ void onMarker(uint32_t markerPosition) override;
+ void onNewPos(uint32_t newPos) override;
+ void onNewIAudioRecord() override;
+ status_t create();
+ status_t setRecordDuration(float durationInSec);
+ status_t enableRecordDump();
+ std::string getRecordDumpFileName() const { return mFileName; }
+ sp<AudioRecord> getAudioRecordHandle();
+ status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
+ audio_session_t triggerSession = AUDIO_SESSION_NONE);
+ status_t obtainBufferCb(RawBuffer& buffer);
+ status_t obtainBuffer(RawBuffer& buffer);
+ status_t audioProcess();
+ status_t stop();
+
+ uint32_t mFrameCount;
+ uint32_t mNotificationFrames;
+ int64_t mNumFramesToRecord;
+ int64_t mNumFramesReceived;
+ int64_t mNumFramesLost;
+ uint32_t mMarkerPosition;
+ uint32_t mMarkerPeriod;
+ uint32_t mReceivedCbMarkerAtPosition;
+ uint32_t mReceivedCbMarkerCount;
+ bool mBufferOverrun;
+
+ enum State {
+ REC_NO_INIT,
+ REC_READY,
+ REC_STARTED,
+ REC_STOPPED,
+ };
+
+ private:
+ const audio_source_t mInputSource;
+ const uint32_t mSampleRate;
+ const audio_format_t mFormat;
+ const audio_channel_mask_t mChannelMask;
+ const audio_input_flags_t mFlags;
+ const audio_session_t mSessionId;
+ const AudioRecord::transfer_type mTransferType;
+ const audio_attributes_t* mAttributes;
+
+ size_t mMaxBytesPerCallback = 2048;
+ sp<AudioRecord> mRecord;
+ State mState;
+ bool mStopRecording;
+ std::string mFileName;
+ int mOutFileFd = -1;
+
+ std::mutex mMutex;
+ std::condition_variable mCondition;
+ std::deque<RawBuffer> mBuffersReceived;
+};
+
+#endif // AUDIO_TEST_UTILS_H_
diff --git a/media/libaudioclient/tests/audioclient_serialization_tests.cpp b/media/libaudioclient/tests/audioclient_serialization_tests.cpp
new file mode 100644
index 0000000..ef8500b
--- /dev/null
+++ b/media/libaudioclient/tests/audioclient_serialization_tests.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 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 "AudioClientSerializationUnitTests"
+
+#include <cstdint>
+#include <cstdlib>
+#include <ctime>
+
+#include <gtest/gtest.h>
+
+#include <android_audio_policy_configuration_V7_0-enums.h>
+#include <xsdc/XsdcSupport.h>
+
+#include "audio_test_utils.h"
+
+using namespace android;
+namespace xsd {
+using namespace ::android::audio::policy::configuration::V7_0;
+}
+
+template <typename T, typename X, typename FUNC>
+std::vector<T> getFlags(const xsdc_enum_range<X>& range, const FUNC& func,
+ const std::string& findString = {}) {
+ std::vector<T> vec;
+ for (const auto& xsdEnumVal : range) {
+ T enumVal;
+ std::string enumString = toString(xsdEnumVal);
+ if (enumString.find(findString) != std::string::npos &&
+ func(enumString.c_str(), &enumVal)) {
+ vec.push_back(enumVal);
+ }
+ }
+ return vec;
+}
+
+static const std::vector<audio_usage_t> kUsages =
+ getFlags<audio_usage_t, xsd::AudioUsage, decltype(audio_usage_from_string)>(
+ xsdc_enum_range<xsd::AudioUsage>{}, audio_usage_from_string);
+
+static const std::vector<audio_content_type_t> kContentType =
+ getFlags<audio_content_type_t, xsd::AudioContentType,
+ decltype(audio_content_type_from_string)>(xsdc_enum_range<xsd::AudioContentType>{},
+ audio_content_type_from_string);
+
+static const std::vector<audio_source_t> kInputSources =
+ getFlags<audio_source_t, xsd::AudioSource, decltype(audio_source_from_string)>(
+ xsdc_enum_range<xsd::AudioSource>{}, audio_source_from_string);
+
+static const std::vector<audio_stream_type_t> kStreamtypes =
+ getFlags<audio_stream_type_t, xsd::AudioStreamType,
+ decltype(audio_stream_type_from_string)>(xsdc_enum_range<xsd::AudioStreamType>{},
+ audio_stream_type_from_string);
+
+static const std::vector<uint32_t> kMixMatchRules = {
+ RULE_MATCH_ATTRIBUTE_USAGE,
+ RULE_EXCLUDE_ATTRIBUTE_USAGE,
+ RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET,
+ RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET,
+ RULE_MATCH_UID,
+ RULE_EXCLUDE_UID,
+ RULE_MATCH_USERID,
+ RULE_EXCLUDE_USERID,
+};
+
+// Generates a random string.
+std::string CreateRandomString(size_t n) {
+ std::string data =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789";
+ srand(static_cast<unsigned int>(time(0)));
+ std::string s(n, ' ');
+ for (size_t i = 0; i < n; ++i) {
+ s[i] = data[rand() % data.size()];
+ }
+ return s;
+}
+
+class FillAudioAttributes {
+ public:
+ void fillAudioAttributes(audio_attributes_t& attr);
+
+ unsigned int mSeed;
+};
+
+void FillAudioAttributes::fillAudioAttributes(audio_attributes_t& attr) {
+ attr.content_type = kContentType[rand() % kContentType.size()];
+ attr.usage = kUsages[rand() % kUsages.size()];
+ attr.source = kInputSources[rand() % kInputSources.size()];
+ // attr.flags -> [0, (1 << (CAPTURE_PRIVATE + 1) - 1)]
+ attr.flags = static_cast<audio_flags_mask_t>(rand() & 0x3fff);
+ sprintf(attr.tags, "%s",
+ CreateRandomString((int)rand() % (AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1)).c_str());
+}
+
+class SerializationTest : public FillAudioAttributes, public ::testing::Test {
+ void SetUp() override {
+ mSeed = static_cast<unsigned int>(time(0));
+ srand(mSeed);
+ }
+};
+
+// UNIT TESTS
+TEST_F(SerializationTest, AudioProductStrategyBinderization) {
+ for (int j = 0; j < 512; j++) {
+ const std::string name{"Test APSBinderization for seed::" + std::to_string(mSeed)};
+ std::vector<AudioAttributes> audioattributesvector;
+ for (auto i = 0; i < 16; i++) {
+ audio_attributes_t attributes;
+ fillAudioAttributes(attributes);
+ AudioAttributes audioattributes{static_cast<volume_group_t>(rand()),
+ kStreamtypes[rand() % kStreamtypes.size()], attributes};
+ audioattributesvector.push_back(audioattributes);
+ }
+ product_strategy_t psId = static_cast<product_strategy_t>(rand());
+ AudioProductStrategy aps{name, audioattributesvector, psId};
+
+ Parcel p;
+ EXPECT_EQ(NO_ERROR, aps.writeToParcel(&p)) << name;
+
+ AudioProductStrategy apsCopy;
+ p.setDataPosition(0);
+ EXPECT_EQ(NO_ERROR, apsCopy.readFromParcel(&p)) << name;
+ EXPECT_EQ(apsCopy.getName(), name) << name;
+ EXPECT_EQ(apsCopy.getId(), psId) << name;
+ auto avec = apsCopy.getAudioAttributes();
+ EXPECT_EQ(avec.size(), audioattributesvector.size()) << name;
+ for (int i = 0; i < audioattributesvector.size(); i++) {
+ EXPECT_EQ(avec[i].getGroupId(), audioattributesvector[i].getGroupId()) << name;
+ EXPECT_EQ(avec[i].getStreamType(), audioattributesvector[i].getStreamType()) << name;
+ EXPECT_TRUE(avec[i].getAttributes() == audioattributesvector[i].getAttributes())
+ << name;
+ }
+ }
+}
+
+TEST_F(SerializationTest, AudioVolumeGroupBinderization) {
+ for (int j = 0; j < 512; j++) {
+ const std::string name{"Test AVGBinderization for seed::" + std::to_string(mSeed)};
+ volume_group_t groupId = static_cast<volume_group_t>(rand());
+ std::vector<audio_attributes_t> attributesvector;
+ for (auto i = 0; i < 16; i++) {
+ audio_attributes_t attributes;
+ fillAudioAttributes(attributes);
+ attributesvector.push_back(attributes);
+ }
+ std::vector<audio_stream_type_t> streamsvector;
+ for (auto i = 0; i < 8; i++) {
+ streamsvector.push_back(kStreamtypes[rand() % kStreamtypes.size()]);
+ }
+ AudioVolumeGroup avg{name, groupId, attributesvector, streamsvector};
+
+ Parcel p;
+ EXPECT_EQ(NO_ERROR, avg.writeToParcel(&p));
+
+ AudioVolumeGroup avgCopy;
+ p.setDataPosition(0);
+ EXPECT_EQ(NO_ERROR, avgCopy.readFromParcel(&p)) << name;
+ EXPECT_EQ(avgCopy.getName(), name) << name;
+ EXPECT_EQ(avgCopy.getId(), groupId) << name;
+ auto avec = avgCopy.getAudioAttributes();
+ EXPECT_EQ(avec.size(), attributesvector.size()) << name;
+ for (int i = 0; i < avec.size(); i++) {
+ EXPECT_TRUE(avec[i] == attributesvector[i]) << name;
+ }
+ StreamTypeVector svec = avgCopy.getStreamTypes();
+ EXPECT_EQ(svec.size(), streamsvector.size()) << name;
+ for (int i = 0; i < svec.size(); i++) {
+ EXPECT_EQ(svec[i], streamsvector[i]) << name;
+ }
+ }
+}
+
+TEST_F(SerializationTest, AudioMixBinderization) {
+ for (int j = 0; j < 512; j++) {
+ const std::string msg{"Test AMBinderization for seed::" + std::to_string(mSeed)};
+ std::vector<AudioMixMatchCriterion> criteria;
+ criteria.reserve(16);
+ for (int i = 0; i < 16; i++) {
+ AudioMixMatchCriterion ammc{kUsages[rand() % kUsages.size()],
+ kInputSources[rand() % kInputSources.size()],
+ kMixMatchRules[rand() % kMixMatchRules.size()]};
+ criteria.push_back(ammc);
+ }
+ audio_config_t config{};
+ config.sample_rate = 48000;
+ config.channel_mask = AUDIO_CHANNEL_IN_MONO;
+ config.format = AUDIO_FORMAT_PCM_16_BIT;
+ config.offload_info = AUDIO_INFO_INITIALIZER;
+ config.frame_count = 4800;
+ AudioMix am{criteria,
+ static_cast<uint32_t>(rand()),
+ config,
+ static_cast<uint32_t>(rand()),
+ String8(msg.c_str()),
+ static_cast<uint32_t>(rand())};
+
+ Parcel p;
+ EXPECT_EQ(NO_ERROR, am.writeToParcel(&p)) << msg;
+
+ AudioMix amCopy;
+ p.setDataPosition(0);
+ EXPECT_EQ(NO_ERROR, amCopy.readFromParcel(&p)) << msg;
+ EXPECT_EQ(amCopy.mMixType, am.mMixType) << msg;
+ EXPECT_EQ(amCopy.mFormat.sample_rate, am.mFormat.sample_rate) << msg;
+ EXPECT_EQ(amCopy.mFormat.channel_mask, am.mFormat.channel_mask) << msg;
+ EXPECT_EQ(amCopy.mFormat.format, am.mFormat.format) << msg;
+ EXPECT_EQ(amCopy.mRouteFlags, am.mRouteFlags) << msg;
+ EXPECT_EQ(amCopy.mDeviceAddress, am.mDeviceAddress) << msg;
+ EXPECT_EQ(amCopy.mCbFlags, am.mCbFlags) << msg;
+ EXPECT_EQ(amCopy.mCriteria.size(), am.mCriteria.size()) << msg;
+ for (auto i = 0; i < amCopy.mCriteria.size(); i++) {
+ EXPECT_EQ(amCopy.mCriteria[i].mRule, am.mCriteria[i].mRule) << msg;
+ EXPECT_EQ(amCopy.mCriteria[i].mValue.mUserId, am.mCriteria[i].mValue.mUserId) << msg;
+ }
+ }
+}
+
+using MMCTestParams = std::tuple<audio_usage_t, audio_source_t, uint32_t>;
+
+class MMCParameterizedTest : public FillAudioAttributes,
+ public ::testing::TestWithParam<MMCTestParams> {
+ public:
+ MMCParameterizedTest()
+ : mAudioUsage(std::get<0>(GetParam())),
+ mAudioSource(std::get<1>(GetParam())),
+ mAudioMixMatchRules(std::get<2>(GetParam())){};
+
+ const audio_usage_t mAudioUsage;
+ const audio_source_t mAudioSource;
+ const uint32_t mAudioMixMatchRules;
+
+ void SetUp() override {
+ mSeed = static_cast<unsigned int>(time(0));
+ srand(mSeed);
+ }
+};
+
+TEST_P(MMCParameterizedTest, AudioMixMatchCriterionBinderization) {
+ const std::string msg{"Test AMMCBinderization for seed::" + std::to_string(mSeed)};
+ AudioMixMatchCriterion ammc{mAudioUsage, mAudioSource, mAudioMixMatchRules};
+
+ Parcel p;
+ EXPECT_EQ(NO_ERROR, ammc.writeToParcel(&p)) << msg;
+
+ AudioMixMatchCriterion ammcCopy;
+ p.setDataPosition(0);
+ EXPECT_EQ(NO_ERROR, ammcCopy.readFromParcel(&p)) << msg;
+ EXPECT_EQ(ammcCopy.mRule, ammc.mRule) << msg;
+ EXPECT_EQ(ammcCopy.mValue.mUserId, ammc.mValue.mUserId) << msg;
+}
+
+// audioUsage, audioSource, audioMixMatchRules
+INSTANTIATE_TEST_SUITE_P(SerializationParameterizedTests, MMCParameterizedTest,
+ ::testing::Combine(testing::ValuesIn(kUsages),
+ testing::ValuesIn(kInputSources),
+ testing::ValuesIn(kMixMatchRules)));
+
+using AudioAttributesTestParams = std::tuple<audio_stream_type_t>;
+
+class AudioAttributesParameterizedTest
+ : public FillAudioAttributes,
+ public ::testing::TestWithParam<AudioAttributesTestParams> {
+ public:
+ AudioAttributesParameterizedTest() : mAudioStream(std::get<0>(GetParam())){};
+
+ const audio_stream_type_t mAudioStream;
+
+ void SetUp() override {
+ mSeed = static_cast<unsigned int>(time(0));
+ srand(mSeed);
+ }
+};
+
+TEST_P(AudioAttributesParameterizedTest, AudioAttributesBinderization) {
+ const std::string msg{"Test AABinderization for seed::" + std::to_string(mSeed)};
+ volume_group_t groupId = static_cast<volume_group_t>(rand());
+ audio_stream_type_t stream = mAudioStream;
+ audio_attributes_t attributes;
+ fillAudioAttributes(attributes);
+ AudioAttributes audioattributes{groupId, stream, attributes};
+
+ Parcel p;
+ EXPECT_EQ(NO_ERROR, audioattributes.writeToParcel(&p)) << msg;
+
+ AudioAttributes audioattributesCopy;
+ p.setDataPosition(0);
+ EXPECT_EQ(NO_ERROR, audioattributesCopy.readFromParcel(&p)) << msg;
+ EXPECT_EQ(audioattributesCopy.getGroupId(), audioattributes.getGroupId()) << msg;
+ EXPECT_EQ(audioattributesCopy.getStreamType(), audioattributes.getStreamType()) << msg;
+ EXPECT_TRUE(audioattributesCopy.getAttributes() == attributes) << msg;
+}
+
+// audioStream
+INSTANTIATE_TEST_SUITE_P(SerializationParameterizedTests, AudioAttributesParameterizedTest,
+ ::testing::Combine(testing::ValuesIn(kStreamtypes)));
diff --git a/media/libaudioclient/tests/audioeffect_analyser.cpp b/media/libaudioclient/tests/audioeffect_analyser.cpp
new file mode 100644
index 0000000..94accae
--- /dev/null
+++ b/media/libaudioclient/tests/audioeffect_analyser.cpp
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2022 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 "AudioEffectAnalyser"
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <gtest/gtest.h>
+#include <media/AudioEffect.h>
+#include <system/audio_effects/effect_bassboost.h>
+#include <system/audio_effects/effect_equalizer.h>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "audio_test_utils.h"
+#include "pffft.hpp"
+
+#define CHECK_OK(expr, msg) \
+ mStatus = (expr); \
+ if (OK != mStatus) { \
+ mMsg = (msg); \
+ return; \
+ }
+
+using namespace android;
+
+constexpr float kDefAmplitude = 0.60f;
+
+constexpr float kPlayBackDurationSec = 1.5;
+constexpr float kCaptureDurationSec = 1.0;
+constexpr float kPrimeDurationInSec = 0.5;
+
+// chosen to safely sample largest center freq of eq bands
+constexpr uint32_t kSamplingFrequency = 48000;
+
+// allows no fmt conversion before fft
+constexpr audio_format_t kFormat = AUDIO_FORMAT_PCM_FLOAT;
+
+// playback and capture are done with channel mask configured to mono.
+// effect analysis should not depend on mask, mono makes it easier.
+
+constexpr int kNPointFFT = 16384;
+constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
+
+const char* gPackageName = "AudioEffectAnalyser";
+
+static_assert(kPrimeDurationInSec + 2 * kNPointFFT / kSamplingFrequency < kCaptureDurationSec,
+ "capture at least, prime, pad, nPointFft size of samples");
+static_assert(kPrimeDurationInSec + 2 * kNPointFFT / kSamplingFrequency < kPlayBackDurationSec,
+ "playback needs to be active during capture");
+
+struct CaptureEnv {
+ // input args
+ uint32_t mSampleRate{kSamplingFrequency};
+ audio_format_t mFormat{kFormat};
+ audio_channel_mask_t mChannelMask{AUDIO_CHANNEL_IN_MONO};
+ float mCaptureDuration{kCaptureDurationSec};
+ // output val
+ status_t mStatus{OK};
+ std::string mMsg;
+ std::string mDumpFileName;
+
+ ~CaptureEnv();
+ void capture();
+};
+
+CaptureEnv::~CaptureEnv() {
+ if (!mDumpFileName.empty()) {
+ std::ifstream f(mDumpFileName);
+ if (f.good()) {
+ f.close();
+ remove(mDumpFileName.c_str());
+ }
+ }
+}
+
+void CaptureEnv::capture() {
+ audio_port_v7 port;
+ CHECK_OK(getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port),
+ "Could not find port")
+ const auto capture =
+ sp<AudioCapture>::make(AUDIO_SOURCE_REMOTE_SUBMIX, mSampleRate, mFormat, mChannelMask);
+ CHECK_OK(capture->create(), "record creation failed")
+ CHECK_OK(capture->setRecordDuration(mCaptureDuration), "set record duration failed")
+ CHECK_OK(capture->enableRecordDump(), "enable record dump failed")
+ auto cbCapture = sp<OnAudioDeviceUpdateNotifier>::make();
+ CHECK_OK(capture->getAudioRecordHandle()->addAudioDeviceCallback(cbCapture),
+ "addAudioDeviceCallback failed")
+ CHECK_OK(capture->start(), "start recording failed")
+ CHECK_OK(capture->audioProcess(), "recording process failed")
+ CHECK_OK(cbCapture->waitForAudioDeviceCb(), "audio device callback notification timed out");
+ if (port.id != capture->getAudioRecordHandle()->getRoutedDeviceId()) {
+ CHECK_OK(BAD_VALUE, "Capture NOT routed on expected port")
+ }
+ CHECK_OK(getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port),
+ "Could not find port")
+ CHECK_OK(capture->stop(), "record stop failed")
+ mDumpFileName = capture->getRecordDumpFileName();
+}
+
+struct PlaybackEnv {
+ // input args
+ uint32_t mSampleRate{kSamplingFrequency};
+ audio_format_t mFormat{kFormat};
+ audio_channel_mask_t mChannelMask{AUDIO_CHANNEL_OUT_MONO};
+ audio_session_t mSessionId{AUDIO_SESSION_NONE};
+ std::string mRes;
+ // output val
+ status_t mStatus{OK};
+ std::string mMsg;
+
+ void play();
+};
+
+void PlaybackEnv::play() {
+ const auto ap =
+ sp<AudioPlayback>::make(mSampleRate, mFormat, mChannelMask, AUDIO_OUTPUT_FLAG_NONE,
+ mSessionId, AudioTrack::TRANSFER_OBTAIN);
+ CHECK_OK(ap->loadResource(mRes.c_str()), "Unable to open Resource")
+ const auto cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+ CHECK_OK(ap->create(), "track creation failed")
+ ap->getAudioTrackHandle()->setVolume(1.0f);
+ CHECK_OK(ap->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback),
+ "addAudioDeviceCallback failed")
+ CHECK_OK(ap->start(), "audio track start failed")
+ CHECK_OK(cbPlayback->waitForAudioDeviceCb(), "audio device callback notification timed out")
+ CHECK_OK(ap->onProcess(), "playback process failed")
+ ap->stop();
+}
+
+void generateMultiTone(const std::vector<int>& toneFrequencies, float samplingFrequency,
+ float duration, float amplitude, float* buffer, int numSamples) {
+ int totalFrameCount = (samplingFrequency * duration);
+ int limit = std::min(totalFrameCount, numSamples);
+
+ for (auto i = 0; i < limit; i++) {
+ buffer[i] = 0;
+ for (auto j = 0; j < toneFrequencies.size(); j++) {
+ buffer[i] += sin(2 * M_PI * toneFrequencies[j] * i / samplingFrequency);
+ }
+ buffer[i] *= (amplitude / toneFrequencies.size());
+ }
+}
+
+sp<AudioEffect> createEffect(const effect_uuid_t* type,
+ audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX) {
+ std::string packageName{gPackageName};
+ AttributionSourceState attributionSource;
+ attributionSource.packageName = packageName;
+ attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
+ attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
+ attributionSource.token = sp<BBinder>::make();
+ sp<AudioEffect> effect = sp<AudioEffect>::make(attributionSource);
+ effect->set(type, nullptr, 0, nullptr, sessionId, AUDIO_IO_HANDLE_NONE, {}, false, false);
+ return effect;
+}
+
+void computeFilterGainsAtTones(float captureDuration, int nPointFft, std::vector<int>& binOffsets,
+ float* inputMag, float* gaindB, const char* res,
+ audio_session_t sessionId) {
+ int totalFrameCount = captureDuration * kSamplingFrequency;
+ auto output = pffft::AlignedVector<float>(totalFrameCount);
+ auto fftOutput = pffft::AlignedVector<float>(nPointFft);
+ PlaybackEnv argsP;
+ argsP.mRes = std::string{res};
+ argsP.mSessionId = sessionId;
+ CaptureEnv argsR;
+ argsR.mCaptureDuration = captureDuration;
+ std::thread playbackThread(&PlaybackEnv::play, &argsP);
+ std::thread captureThread(&CaptureEnv::capture, &argsR);
+ captureThread.join();
+ playbackThread.join();
+ ASSERT_EQ(OK, argsR.mStatus) << argsR.mMsg;
+ ASSERT_EQ(OK, argsP.mStatus) << argsP.mMsg;
+ ASSERT_FALSE(argsR.mDumpFileName.empty()) << "recorded not written to file";
+ std::ifstream fin(argsR.mDumpFileName, std::ios::in | std::ios::binary);
+ fin.read((char*)output.data(), totalFrameCount * sizeof(output[0]));
+ fin.close();
+ PFFFT_Setup* handle = pffft_new_setup(nPointFft, PFFFT_REAL);
+ // ignore first few samples. This is to not analyse until audio track is re-routed to remote
+ // submix source, also for the effect filter response to reach steady-state (priming / pruning
+ // samples).
+ int rerouteOffset = kPrimeDurationInSec * kSamplingFrequency;
+ pffft_transform_ordered(handle, output.data() + rerouteOffset, fftOutput.data(), nullptr,
+ PFFFT_FORWARD);
+ pffft_destroy_setup(handle);
+ for (auto i = 0; i < binOffsets.size(); i++) {
+ auto k = binOffsets[i];
+ auto outputMag = sqrt((fftOutput[k * 2] * fftOutput[k * 2]) +
+ (fftOutput[k * 2 + 1] * fftOutput[k * 2 + 1]));
+ gaindB[i] = 20 * log10(outputMag / inputMag[i]);
+ }
+}
+
+std::tuple<int, int> roundToFreqCenteredToFftBin(float binWidth, float freq) {
+ int bin_index = std::round(freq / binWidth);
+ int cfreq = std::round(bin_index * binWidth);
+ return std::make_tuple(bin_index, cfreq);
+}
+
+TEST(AudioEffectTest, CheckEqualizerEffect) {
+ audio_session_t sessionId =
+ (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ sp<AudioEffect> equalizer = createEffect(SL_IID_EQUALIZER, sessionId);
+ ASSERT_EQ(OK, equalizer->initCheck());
+ ASSERT_EQ(NO_ERROR, equalizer->setEnabled(true));
+ if ((equalizer->descriptor().flags & EFFECT_FLAG_HW_ACC_MASK) != 0) {
+ GTEST_SKIP() << "effect processed output inaccessible, skipping test";
+ }
+#define MAX_PARAMS 64
+ uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + MAX_PARAMS];
+ effect_param_t* eqParam = (effect_param_t*)(&buf32);
+
+ // get num of presets
+ eqParam->psize = sizeof(uint32_t);
+ eqParam->vsize = sizeof(uint16_t);
+ *(int32_t*)eqParam->data = EQ_PARAM_GET_NUM_OF_PRESETS;
+ EXPECT_EQ(0, equalizer->getParameter(eqParam));
+ EXPECT_EQ(0, eqParam->status);
+ int numPresets = *((uint16_t*)((int32_t*)eqParam->data + 1));
+
+ // get num of bands
+ eqParam->psize = sizeof(uint32_t);
+ eqParam->vsize = sizeof(uint16_t);
+ *(int32_t*)eqParam->data = EQ_PARAM_NUM_BANDS;
+ EXPECT_EQ(0, equalizer->getParameter(eqParam));
+ EXPECT_EQ(0, eqParam->status);
+ int numBands = *((uint16_t*)((int32_t*)eqParam->data + 1));
+
+ const int totalFrameCount = kSamplingFrequency * kPlayBackDurationSec;
+
+ // get band center frequencies
+ std::vector<int> centerFrequencies;
+ std::vector<int> binOffsets;
+ for (auto i = 0; i < numBands; i++) {
+ eqParam->psize = sizeof(uint32_t) * 2;
+ eqParam->vsize = sizeof(uint32_t);
+ *(int32_t*)eqParam->data = EQ_PARAM_CENTER_FREQ;
+ *((uint16_t*)((int32_t*)eqParam->data + 1)) = i;
+ EXPECT_EQ(0, equalizer->getParameter(eqParam));
+ EXPECT_EQ(0, eqParam->status);
+ float cfreq = *((int32_t*)eqParam->data + 2) / 1000; // milli hz
+ // pick frequency close to bin center frequency
+ auto [bin_index, bin_freq] = roundToFreqCenteredToFftBin(kBinWidth, cfreq);
+ centerFrequencies.push_back(bin_freq);
+ binOffsets.push_back(bin_index);
+ }
+
+ // input for effect module
+ auto input = pffft::AlignedVector<float>(totalFrameCount);
+ generateMultiTone(centerFrequencies, kSamplingFrequency, kPlayBackDurationSec, kDefAmplitude,
+ input.data(), totalFrameCount);
+ auto fftInput = pffft::AlignedVector<float>(kNPointFFT);
+ PFFFT_Setup* handle = pffft_new_setup(kNPointFFT, PFFFT_REAL);
+ pffft_transform_ordered(handle, input.data(), fftInput.data(), nullptr, PFFFT_FORWARD);
+ pffft_destroy_setup(handle);
+ float inputMag[numBands];
+ for (auto i = 0; i < numBands; i++) {
+ auto k = binOffsets[i];
+ inputMag[i] = sqrt((fftInput[k * 2] * fftInput[k * 2]) +
+ (fftInput[k * 2 + 1] * fftInput[k * 2 + 1]));
+ }
+ TemporaryFile tf("/data/local/tmp");
+ close(tf.release());
+ std::ofstream fout(tf.path, std::ios::out | std::ios::binary);
+ fout.write((char*)input.data(), input.size() * sizeof(input[0]));
+ fout.close();
+
+ float expGaindB[numBands], actGaindB[numBands];
+
+ std::string msg = "";
+ int numPresetsOk = 0;
+ for (auto preset = 0; preset < numPresets; preset++) {
+ // set preset
+ eqParam->psize = sizeof(uint32_t);
+ eqParam->vsize = sizeof(uint32_t);
+ *(int32_t*)eqParam->data = EQ_PARAM_CUR_PRESET;
+ *((uint16_t*)((int32_t*)eqParam->data + 1)) = preset;
+ EXPECT_EQ(0, equalizer->setParameter(eqParam));
+ EXPECT_EQ(0, eqParam->status);
+ // get preset gains
+ eqParam->psize = sizeof(uint32_t);
+ eqParam->vsize = (numBands + 1) * sizeof(uint32_t);
+ *(int32_t*)eqParam->data = EQ_PARAM_PROPERTIES;
+ EXPECT_EQ(0, equalizer->getParameter(eqParam));
+ EXPECT_EQ(0, eqParam->status);
+ t_equalizer_settings* settings =
+ reinterpret_cast<t_equalizer_settings*>((int32_t*)eqParam->data + 1);
+ EXPECT_EQ(preset, settings->curPreset);
+ EXPECT_EQ(numBands, settings->numBands);
+ for (auto i = 0; i < numBands; i++) {
+ expGaindB[i] = ((int16_t)settings->bandLevels[i]) / 100.0f; // gain in milli bels
+ }
+ memset(actGaindB, 0, sizeof(actGaindB));
+ ASSERT_NO_FATAL_FAILURE(computeFilterGainsAtTones(kCaptureDurationSec, kNPointFFT,
+ binOffsets, inputMag, actGaindB, tf.path,
+ sessionId));
+ bool isOk = true;
+ for (auto i = 0; i < numBands - 1; i++) {
+ auto diffA = expGaindB[i] - expGaindB[i + 1];
+ auto diffB = actGaindB[i] - actGaindB[i + 1];
+ if (diffA == 0 && fabs(diffA - diffB) > 1.0f) {
+ msg += (android::base::StringPrintf(
+ "For eq preset : %d, between bands %d and %d, expected relative gain is : "
+ "%f, got relative gain is : %f, error : %f \n",
+ preset, i, i + 1, diffA, diffB, diffA - diffB));
+ isOk = false;
+ } else if (diffA * diffB < 0) {
+ msg += (android::base::StringPrintf(
+ "For eq preset : %d, between bands %d and %d, expected relative gain and "
+ "seen relative gain are of opposite signs \n. Expected relative gain is : "
+ "%f, seen relative gain is : %f \n",
+ preset, i, i + 1, diffA, diffB));
+ isOk = false;
+ }
+ }
+ if (isOk) numPresetsOk++;
+ }
+ EXPECT_EQ(numPresetsOk, numPresets) << msg;
+}
+
+TEST(AudioEffectTest, CheckBassBoostEffect) {
+ audio_session_t sessionId =
+ (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ sp<AudioEffect> bassboost = createEffect(SL_IID_BASSBOOST, sessionId);
+ ASSERT_EQ(OK, bassboost->initCheck());
+ ASSERT_EQ(NO_ERROR, bassboost->setEnabled(true));
+ if ((bassboost->descriptor().flags & EFFECT_FLAG_HW_ACC_MASK) != 0) {
+ GTEST_SKIP() << "effect processed output inaccessible, skipping test";
+ }
+ int32_t buf32[sizeof(effect_param_t) / sizeof(int32_t) + MAX_PARAMS];
+ effect_param_t* bbParam = (effect_param_t*)(&buf32);
+
+ bbParam->psize = sizeof(int32_t);
+ bbParam->vsize = sizeof(int32_t);
+ *(int32_t*)bbParam->data = BASSBOOST_PARAM_STRENGTH_SUPPORTED;
+ EXPECT_EQ(0, bassboost->getParameter(bbParam));
+ EXPECT_EQ(0, bbParam->status);
+ bool strengthSupported = *((int32_t*)bbParam->data + 1);
+
+ const int totalFrameCount = kSamplingFrequency * kPlayBackDurationSec;
+
+ // selecting bass frequency, speech tone (for relative gain)
+ std::vector<int> testFrequencies{100, 1200};
+ std::vector<int> binOffsets;
+ for (auto i = 0; i < testFrequencies.size(); i++) {
+ // pick frequency close to bin center frequency
+ auto [bin_index, bin_freq] = roundToFreqCenteredToFftBin(kBinWidth, testFrequencies[i]);
+ testFrequencies[i] = bin_freq;
+ binOffsets.push_back(bin_index);
+ }
+
+ // input for effect module
+ auto input = pffft::AlignedVector<float>(totalFrameCount);
+ generateMultiTone(testFrequencies, kSamplingFrequency, kPlayBackDurationSec, kDefAmplitude,
+ input.data(), totalFrameCount);
+ auto fftInput = pffft::AlignedVector<float>(kNPointFFT);
+ PFFFT_Setup* handle = pffft_new_setup(kNPointFFT, PFFFT_REAL);
+ pffft_transform_ordered(handle, input.data(), fftInput.data(), nullptr, PFFFT_FORWARD);
+ pffft_destroy_setup(handle);
+ float inputMag[testFrequencies.size()];
+ for (auto i = 0; i < testFrequencies.size(); i++) {
+ auto k = binOffsets[i];
+ inputMag[i] = sqrt((fftInput[k * 2] * fftInput[k * 2]) +
+ (fftInput[k * 2 + 1] * fftInput[k * 2 + 1]));
+ }
+ TemporaryFile tf("/data/local/tmp");
+ close(tf.release());
+ std::ofstream fout(tf.path, std::ios::out | std::ios::binary);
+ fout.write((char*)input.data(), input.size() * sizeof(input[0]));
+ fout.close();
+
+ float gainWithOutFilter[testFrequencies.size()];
+ memset(gainWithOutFilter, 0, sizeof(gainWithOutFilter));
+ ASSERT_NO_FATAL_FAILURE(computeFilterGainsAtTones(kCaptureDurationSec, kNPointFFT, binOffsets,
+ inputMag, gainWithOutFilter, tf.path,
+ AUDIO_SESSION_OUTPUT_MIX));
+ float diffA = gainWithOutFilter[0] - gainWithOutFilter[1];
+ float prevGain = -100.f;
+ for (auto strength = 150; strength < 1000; strength += strengthSupported ? 150 : 1000) {
+ // configure filter strength
+ if (strengthSupported) {
+ bbParam->psize = sizeof(int32_t);
+ bbParam->vsize = sizeof(int16_t);
+ *(int32_t*)bbParam->data = BASSBOOST_PARAM_STRENGTH;
+ *((int16_t*)((int32_t*)bbParam->data + 1)) = strength;
+ EXPECT_EQ(0, bassboost->setParameter(bbParam));
+ EXPECT_EQ(0, bbParam->status);
+ }
+ float gainWithFilter[testFrequencies.size()];
+ memset(gainWithFilter, 0, sizeof(gainWithFilter));
+ ASSERT_NO_FATAL_FAILURE(computeFilterGainsAtTones(kCaptureDurationSec, kNPointFFT,
+ binOffsets, inputMag, gainWithFilter,
+ tf.path, sessionId));
+ float diffB = gainWithFilter[0] - gainWithFilter[1];
+ EXPECT_GT(diffB, diffA) << "bassboost effect not seen";
+ EXPECT_GE(diffB, prevGain) << "increase in boost strength causing fall in gain";
+ prevGain = diffB;
+ }
+}
diff --git a/media/libaudioclient/tests/audioeffect_tests.cpp b/media/libaudioclient/tests/audioeffect_tests.cpp
new file mode 100644
index 0000000..e6149e4
--- /dev/null
+++ b/media/libaudioclient/tests/audioeffect_tests.cpp
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 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 "AudioEffectUnitTests"
+
+#include <gtest/gtest.h>
+#include <media/AudioEffect.h>
+#include <system/audio_effects/effect_hapticgenerator.h>
+#include <system/audio_effects/effect_spatializer.h>
+#include <system/audio_effects/effect_visualizer.h>
+
+#include "audio_test_utils.h"
+
+using namespace android;
+
+class AudioEffectCallback : public AudioEffect::IAudioEffectCallback {
+ public:
+ bool receivedFramesProcessed = false;
+
+ void onFramesProcessed(int32_t framesProcessed) override {
+ ALOGE("number of frames processed %d", framesProcessed);
+ receivedFramesProcessed = true;
+ }
+};
+
+static constexpr int kDefaultInputEffectPriority = -1;
+static constexpr int kDefaultOutputEffectPriority = 0;
+
+static const char* gPackageName = "AudioEffectTest";
+
+bool doesDeviceSupportLowLatencyMode(std::vector<struct audio_port_v7>& ports) {
+ for (const auto& port : ports) {
+ if (port.role == AUDIO_PORT_ROLE_SOURCE && port.type == AUDIO_PORT_TYPE_MIX) {
+ if ((port.active_config.flags.output & AUDIO_OUTPUT_FLAG_FAST) != 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+sp<AudioEffect> createEffect(const effect_uuid_t* type, const effect_uuid_t* uuid = nullptr,
+ int priority = 0, audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
+ const wp<AudioEffectCallback>& callback = nullptr) {
+ std::string packageName{gPackageName};
+ AttributionSourceState attributionSource;
+ attributionSource.packageName = packageName;
+ attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
+ attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
+ attributionSource.token = sp<BBinder>::make();
+ sp<AudioEffect> effect = new AudioEffect(attributionSource);
+ effect->set(type, uuid, priority, callback, sessionId, AUDIO_IO_HANDLE_NONE, {}, false,
+ (callback != nullptr));
+ return effect;
+}
+
+status_t isEffectExistsOnAudioSession(const effect_uuid_t* type, const effect_uuid_t* uuid,
+ int priority, audio_session_t sessionId) {
+ sp<AudioEffect> effect = createEffect(type, uuid, priority, sessionId);
+ return effect->initCheck();
+}
+
+bool isEffectDefaultOnRecord(const effect_uuid_t* type, const effect_uuid_t* uuid,
+ const sp<AudioRecord>& audioRecord) {
+ effect_descriptor_t descriptors[AudioEffect::kMaxPreProcessing];
+ uint32_t numEffects = AudioEffect::kMaxPreProcessing;
+ status_t ret = AudioEffect::queryDefaultPreProcessing(audioRecord->getSessionId(), descriptors,
+ &numEffects);
+ if (ret != OK) {
+ return false;
+ }
+ for (int i = 0; i < numEffects; i++) {
+ if ((memcmp(&descriptors[i].type, type, sizeof(effect_uuid_t)) == 0) &&
+ (memcmp(&descriptors[i].uuid, uuid, sizeof(effect_uuid_t)) == 0)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void listEffectsAvailable(std::vector<effect_descriptor_t>& descriptors) {
+ uint32_t numEffects = 0;
+ ASSERT_EQ(NO_ERROR, AudioEffect::queryNumberEffects(&numEffects));
+ for (auto i = 0; i < numEffects; i++) {
+ effect_descriptor_t des;
+ ASSERT_EQ(NO_ERROR, AudioEffect::queryEffect(i, &des));
+ descriptors.push_back(des);
+ }
+}
+
+bool isPreprocessing(effect_descriptor_t& descriptor) {
+ return ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC);
+}
+
+bool isInsert(effect_descriptor_t& descriptor) {
+ return ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT);
+}
+
+bool isAux(effect_descriptor_t& descriptor) {
+ return ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY);
+}
+
+bool isPostproc(effect_descriptor_t& descriptor) {
+ return ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC);
+}
+
+bool isFastCompatible(effect_descriptor_t& descriptor) {
+ return !(((descriptor.flags & EFFECT_FLAG_HW_ACC_MASK) == 0) &&
+ ((descriptor.flags & EFFECT_FLAG_NO_PROCESS) == 0));
+}
+
+bool isSpatializer(effect_descriptor_t& descriptor) {
+ return (memcmp(&descriptor.type, FX_IID_SPATIALIZER, sizeof(effect_uuid_t)) == 0);
+}
+
+bool isHapticGenerator(effect_descriptor_t& descriptor) {
+ return (memcmp(&descriptor.type, FX_IID_HAPTICGENERATOR, sizeof(effect_uuid_t)) == 0);
+}
+
+std::tuple<std::string, std::string> typeAndUuidToString(const effect_descriptor_t& desc) {
+ char type[512];
+ AudioEffect::guidToString(&desc.type, type, sizeof(type));
+ char uuid[512];
+ AudioEffect::guidToString(&desc.uuid, uuid, sizeof(uuid));
+ return std::make_tuple(type, uuid);
+}
+
+// UNIT TESTS
+TEST(AudioEffectTest, getEffectDescriptor) {
+ effect_uuid_t randomType = {
+ 0x81781c08, 0x93dd, 0x11ec, 0xb909, {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+ effect_uuid_t randomUuid = {
+ 0x653730e1, 0x1be1, 0x438e, 0xa35a, {0xfc, 0x9b, 0xa1, 0x2a, 0x5e, 0xc9}};
+ effect_uuid_t empty = EFFECT_UUID_INITIALIZER;
+
+ effect_descriptor_t descriptor;
+ EXPECT_EQ(NAME_NOT_FOUND, AudioEffect::getEffectDescriptor(&randomUuid, &randomType,
+ EFFECT_FLAG_TYPE_MASK, &descriptor));
+
+ std::vector<effect_descriptor_t> descriptors;
+ ASSERT_NO_FATAL_FAILURE(listEffectsAvailable(descriptors));
+
+ for (auto i = 0; i < descriptors.size(); i++) {
+ EXPECT_EQ(NO_ERROR,
+ AudioEffect::getEffectDescriptor(&descriptors[i].uuid, &descriptors[i].type,
+ EFFECT_FLAG_TYPE_MASK, &descriptor));
+ EXPECT_EQ(0, memcmp(&descriptor, &descriptors[i], sizeof(effect_uuid_t)));
+ }
+ // negative tests
+ if (descriptors.size() > 0) {
+ EXPECT_EQ(BAD_VALUE,
+ AudioEffect::getEffectDescriptor(&descriptors[0].uuid, &descriptors[0].type,
+ EFFECT_FLAG_TYPE_MASK, nullptr));
+ }
+ EXPECT_EQ(BAD_VALUE, AudioEffect::getEffectDescriptor(nullptr, nullptr,
+ EFFECT_FLAG_TYPE_PRE_PROC, &descriptor));
+ EXPECT_EQ(BAD_VALUE, AudioEffect::getEffectDescriptor(&empty, &randomType,
+ EFFECT_FLAG_TYPE_MASK, nullptr));
+ EXPECT_EQ(BAD_VALUE, AudioEffect::getEffectDescriptor(nullptr, &randomType,
+ EFFECT_FLAG_TYPE_POST_PROC, &descriptor));
+ EXPECT_EQ(BAD_VALUE, AudioEffect::getEffectDescriptor(&randomUuid, nullptr,
+ EFFECT_FLAG_TYPE_INSERT, &descriptor));
+}
+
+TEST(AudioEffectTest, DISABLED_GetSetParameterForEffect) {
+ sp<AudioEffect> visualizer = createEffect(SL_IID_VISUALIZATION);
+ status_t status = visualizer->initCheck();
+ ASSERT_TRUE(status == NO_ERROR || status == ALREADY_EXISTS) << "Init check error";
+ ASSERT_EQ(NO_ERROR, visualizer->setEnabled(true)) << "visualizer not enabled";
+
+ uint32_t buf32[3][sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+ effect_param_t* vis_none = (effect_param_t*)(buf32[0]);
+ effect_param_t* vis_rms = (effect_param_t*)(buf32[1]);
+ effect_param_t* vis_tmp = (effect_param_t*)(buf32[2]);
+
+ // Visualizer::setMeasurementMode()
+ vis_none->psize = sizeof(uint32_t);
+ vis_none->vsize = sizeof(uint32_t);
+ *(int32_t*)vis_none->data = VISUALIZER_PARAM_MEASUREMENT_MODE;
+ *((int32_t*)vis_none->data + 1) = MEASUREMENT_MODE_NONE;
+ EXPECT_EQ(NO_ERROR, visualizer->setParameter(vis_none))
+ << "setMeasurementMode doesn't report success";
+
+ // Visualizer::getMeasurementMode()
+ vis_tmp->psize = sizeof(uint32_t);
+ vis_tmp->vsize = sizeof(uint32_t);
+ *(int32_t*)vis_tmp->data = VISUALIZER_PARAM_MEASUREMENT_MODE;
+ *((int32_t*)vis_tmp->data + 1) = 23;
+ EXPECT_EQ(NO_ERROR, visualizer->getParameter(vis_tmp))
+ << "getMeasurementMode doesn't report success";
+ EXPECT_EQ(*((int32_t*)vis_tmp->data + 1), *((int32_t*)vis_none->data + 1))
+ << "target mode does not match set mode";
+
+ // Visualizer::setMeasurementModeDeferred()
+ vis_rms->psize = sizeof(uint32_t);
+ vis_rms->vsize = sizeof(uint32_t);
+ *(int32_t*)vis_rms->data = VISUALIZER_PARAM_MEASUREMENT_MODE;
+ *((int32_t*)vis_rms->data + 1) = MEASUREMENT_MODE_PEAK_RMS;
+ EXPECT_EQ(NO_ERROR, visualizer->setParameterDeferred(vis_rms))
+ << "setMeasurementModeDeferred doesn't report success";
+
+ *((int32_t*)vis_tmp->data + 1) = 23;
+ EXPECT_EQ(NO_ERROR, visualizer->getParameter(vis_tmp))
+ << "getMeasurementMode doesn't report success";
+ EXPECT_EQ(*((int32_t*)vis_tmp->data + 1), *((int32_t*)vis_none->data + 1))
+ << "target mode does not match set mode";
+
+ // setParameterCommit
+ EXPECT_EQ(NO_ERROR, visualizer->setParameterCommit())
+ << "setMeasurementModeCommit does not report success";
+
+ // validate Params
+ *((int32_t*)vis_tmp->data + 1) = 23;
+ EXPECT_EQ(NO_ERROR, visualizer->getParameter(vis_tmp))
+ << "getMeasurementMode doesn't report success";
+ EXPECT_EQ(*((int32_t*)vis_tmp->data + 1), *((int32_t*)vis_rms->data + 1))
+ << "target mode does not match set mode";
+}
+
+TEST(AudioEffectTest, ManageSourceDefaultEffects) {
+ int32_t selectedEffect = -1;
+
+ const uint32_t sampleRate = 44100;
+ const audio_format_t format = AUDIO_FORMAT_PCM_16_BIT;
+ const audio_channel_mask_t channelMask = AUDIO_CHANNEL_IN_STEREO;
+ sp<AudioCapture> capture = nullptr;
+
+ std::vector<effect_descriptor_t> descriptors;
+ ASSERT_NO_FATAL_FAILURE(listEffectsAvailable(descriptors));
+ for (auto i = 0; i < descriptors.size(); i++) {
+ if (isPreprocessing(descriptors[i])) {
+ capture = new AudioCapture(AUDIO_SOURCE_MIC, sampleRate, format, channelMask);
+ ASSERT_NE(capture, nullptr) << "Unable to create Record Application";
+ EXPECT_EQ(NO_ERROR, capture->create());
+ EXPECT_EQ(NO_ERROR, capture->start());
+ if (!isEffectDefaultOnRecord(&descriptors[i].type, &descriptors[i].uuid,
+ capture->getAudioRecordHandle())) {
+ selectedEffect = i;
+ break;
+ }
+ }
+ }
+ if (selectedEffect == -1) GTEST_SKIP() << " expected at least one preprocessing effect";
+
+ effect_uuid_t* selectedEffectType = &descriptors[selectedEffect].type;
+ effect_uuid_t* selectedEffectUuid = &descriptors[selectedEffect].uuid;
+ auto [type, uuid] = typeAndUuidToString(descriptors[selectedEffect]);
+ capture = new AudioCapture(AUDIO_SOURCE_MIC, sampleRate, format, channelMask);
+ ASSERT_NE(capture, nullptr) << "Unable to create Record Application";
+ EXPECT_EQ(NO_ERROR, capture->create());
+ EXPECT_EQ(NO_ERROR, capture->start());
+ EXPECT_FALSE(isEffectDefaultOnRecord(selectedEffectType, selectedEffectUuid,
+ capture->getAudioRecordHandle()))
+ << "Effect should not have been default on record. " << type;
+ EXPECT_EQ(NO_ERROR,
+ isEffectExistsOnAudioSession(selectedEffectType, selectedEffectUuid,
+ kDefaultInputEffectPriority - 1,
+ capture->getAudioRecordHandle()->getSessionId()))
+ << "Effect should not have been added. " << type;
+ EXPECT_EQ(OK, capture->audioProcess());
+ EXPECT_EQ(OK, capture->stop());
+
+ String16 name{gPackageName};
+ audio_unique_id_t effectId;
+ status_t status = AudioEffect::addSourceDefaultEffect(type.c_str(), name, uuid.c_str(),
+ kDefaultInputEffectPriority,
+ AUDIO_SOURCE_MIC, &effectId);
+ EXPECT_EQ(NO_ERROR, status) << "Adding default effect failed: " << type;
+
+ capture = new AudioCapture(AUDIO_SOURCE_MIC, sampleRate, format, channelMask);
+ ASSERT_NE(capture, nullptr) << "Unable to create Record Application";
+ EXPECT_EQ(NO_ERROR, capture->create());
+ EXPECT_EQ(NO_ERROR, capture->start());
+ EXPECT_TRUE(isEffectDefaultOnRecord(selectedEffectType, selectedEffectUuid,
+ capture->getAudioRecordHandle()))
+ << "Effect should have been default on record. " << type;
+ EXPECT_EQ(ALREADY_EXISTS,
+ isEffectExistsOnAudioSession(selectedEffectType, selectedEffectUuid,
+ kDefaultInputEffectPriority - 1,
+ capture->getAudioRecordHandle()->getSessionId()))
+ << "Effect should have been added. " << type;
+ EXPECT_EQ(OK, capture->audioProcess());
+ EXPECT_EQ(OK, capture->stop());
+
+ status = AudioEffect::removeSourceDefaultEffect(effectId);
+ EXPECT_EQ(NO_ERROR, status);
+ capture = new AudioCapture(AUDIO_SOURCE_MIC, sampleRate, format, channelMask);
+ ASSERT_NE(capture, nullptr) << "Unable to create Record Application";
+ EXPECT_EQ(NO_ERROR, capture->create());
+ EXPECT_EQ(NO_ERROR, capture->start());
+ EXPECT_FALSE(isEffectDefaultOnRecord(selectedEffectType, selectedEffectUuid,
+ capture->getAudioRecordHandle()))
+ << "Effect should not have been default on record. " << type;
+ EXPECT_EQ(NO_ERROR,
+ isEffectExistsOnAudioSession(selectedEffectType, selectedEffectUuid,
+ kDefaultInputEffectPriority - 1,
+ capture->getAudioRecordHandle()->getSessionId()))
+ << "Effect should not have been added. " << type;
+ EXPECT_EQ(OK, capture->audioProcess());
+ EXPECT_EQ(OK, capture->stop());
+}
+
+TEST(AudioEffectTest, AuxEffectSanityTest) {
+ int32_t selectedEffect = -1;
+ std::vector<effect_descriptor_t> descriptors;
+ ASSERT_NO_FATAL_FAILURE(listEffectsAvailable(descriptors));
+ for (auto i = 0; i < descriptors.size(); i++) {
+ if (isAux(descriptors[i])) {
+ selectedEffect = i;
+ break;
+ }
+ }
+ if (selectedEffect == -1) GTEST_SKIP() << "expected at least one aux effect";
+ effect_uuid_t* selectedEffectType = &descriptors[selectedEffect].type;
+ effect_uuid_t* selectedEffectUuid = &descriptors[selectedEffect].uuid;
+ auto [type, uuid] = typeAndUuidToString(descriptors[selectedEffect]);
+ String16 name{gPackageName};
+ audio_session_t sessionId =
+ (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ sp<AudioEffect> audioEffect = createEffect(selectedEffectType, selectedEffectUuid,
+ kDefaultInputEffectPriority, sessionId);
+ EXPECT_EQ(NO_INIT, audioEffect->initCheck())
+ << "error, creating auxiliary effect (" << type << ") on session id " << (int)sessionId
+ << " successful ";
+ audio_unique_id_t id;
+ status_t status = AudioEffect::addStreamDefaultEffect(
+ type.c_str(), name, uuid.c_str(), kDefaultOutputEffectPriority, AUDIO_USAGE_MEDIA, &id);
+ if (status == NO_ERROR) {
+ EXPECT_EQ(NO_ERROR, AudioEffect::removeStreamDefaultEffect(id));
+ EXPECT_NE(NO_ERROR, status) << "error, adding auxiliary effect (" << type
+ << ") as stream default effect is successful";
+ }
+}
+
+class AudioPlaybackEffectTest : public ::testing::TestWithParam<bool> {
+ public:
+ AudioPlaybackEffectTest() : mSelectFastMode(GetParam()){};
+
+ const bool mSelectFastMode;
+
+ bool mIsFastCompatibleEffect;
+ effect_uuid_t mType;
+ effect_uuid_t mUuid;
+ std::string mTypeStr;
+ std::string mUuidStr;
+
+ void SetUp() override {
+ if (mSelectFastMode) {
+ std::vector<struct audio_port_v7> ports;
+ ASSERT_EQ(OK, listAudioPorts(ports));
+ if (!doesDeviceSupportLowLatencyMode(ports)) {
+ GTEST_SKIP() << "device does not support low latency mode";
+ }
+ }
+
+ int32_t selectedEffect = -1;
+ std::vector<effect_descriptor_t> descriptors;
+ ASSERT_NO_FATAL_FAILURE(listEffectsAvailable(descriptors));
+ for (auto i = 0; i < descriptors.size(); i++) {
+ if (isSpatializer(descriptors[i])) continue;
+ if (isHapticGenerator(descriptors[i]) && !AudioSystem::isHapticPlaybackSupported())
+ continue;
+ if (!isInsert(descriptors[i])) continue;
+ selectedEffect = i;
+ mIsFastCompatibleEffect = isFastCompatible(descriptors[i]);
+ // in fast mode, pick fast compatible effect if available
+ if (mSelectFastMode == mIsFastCompatibleEffect) break;
+ }
+ if (selectedEffect == -1) {
+ GTEST_SKIP() << "expected at least one valid effect";
+ }
+
+ mType = descriptors[selectedEffect].type;
+ mUuid = descriptors[selectedEffect].uuid;
+ std::tie(mTypeStr, mUuidStr) = typeAndUuidToString(descriptors[selectedEffect]);
+ }
+};
+
+TEST_P(AudioPlaybackEffectTest, StreamDefaultEffectTest) {
+ SCOPED_TRACE(testing::Message()
+ << "\n selected effect type is :: " << mTypeStr
+ << "\n selected effect uuid is :: " << mUuidStr
+ << "\n audiotrack output flag : " << (mSelectFastMode ? "fast" : "default")
+ << "\n audio effect is fast compatible : "
+ << (mIsFastCompatibleEffect ? "yes" : "no"));
+
+ bool compatCheck = !mSelectFastMode || (mSelectFastMode && mIsFastCompatibleEffect);
+
+ // create track
+ audio_attributes_t attributes;
+ attributes.usage = AUDIO_USAGE_MEDIA;
+ attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+ auto playback = sp<AudioPlayback>::make(
+ 0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ mSelectFastMode ? AUDIO_OUTPUT_FLAG_FAST : AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE,
+ AudioTrack::TRANSFER_SHARED, &attributes);
+ ASSERT_NE(nullptr, playback);
+ ASSERT_EQ(NO_ERROR, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"));
+ EXPECT_EQ(NO_ERROR, playback->create());
+ EXPECT_EQ(NO_ERROR, playback->start());
+ EXPECT_EQ(compatCheck ? NO_ERROR : NO_INIT,
+ isEffectExistsOnAudioSession(&mType, &mUuid, kDefaultOutputEffectPriority - 1,
+ playback->getAudioTrackHandle()->getSessionId()))
+ << "Effect should not have been added. " << mTypeStr;
+ EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
+ playback->stop();
+ playback.clear();
+
+ String16 name{gPackageName};
+ audio_unique_id_t id;
+ status_t status = AudioEffect::addStreamDefaultEffect(mTypeStr.c_str(), name, mUuidStr.c_str(),
+ kDefaultOutputEffectPriority,
+ AUDIO_USAGE_MEDIA, &id);
+ EXPECT_EQ(NO_ERROR, status) << "Adding default effect failed: " << mTypeStr;
+
+ playback = sp<AudioPlayback>::make(
+ 0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ mSelectFastMode ? AUDIO_OUTPUT_FLAG_FAST : AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE,
+ AudioTrack::TRANSFER_SHARED, &attributes);
+ ASSERT_NE(nullptr, playback);
+ ASSERT_EQ(NO_ERROR, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"));
+ EXPECT_EQ(NO_ERROR, playback->create());
+ EXPECT_EQ(NO_ERROR, playback->start());
+ // If effect chosen is not compatible with the session, then effect won't be applied
+ EXPECT_EQ(compatCheck ? ALREADY_EXISTS : NO_INIT,
+ isEffectExistsOnAudioSession(&mType, &mUuid, kDefaultOutputEffectPriority - 1,
+ playback->getAudioTrackHandle()->getSessionId()))
+ << "Effect should have been added. " << mTypeStr;
+ EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
+ if (mSelectFastMode) {
+ EXPECT_EQ(AUDIO_OUTPUT_FLAG_FAST,
+ playback->getAudioTrackHandle()->getFlags() & AUDIO_OUTPUT_FLAG_FAST);
+ }
+ playback->stop();
+ playback.clear();
+
+ status = AudioEffect::removeStreamDefaultEffect(id);
+ EXPECT_EQ(NO_ERROR, status);
+ playback = sp<AudioPlayback>::make(
+ 0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ mSelectFastMode ? AUDIO_OUTPUT_FLAG_FAST : AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE,
+ AudioTrack::TRANSFER_SHARED, &attributes);
+ ASSERT_NE(nullptr, playback);
+ ASSERT_EQ(NO_ERROR, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"));
+ EXPECT_EQ(NO_ERROR, playback->create());
+ EXPECT_EQ(NO_ERROR, playback->start());
+ EXPECT_EQ(compatCheck ? NO_ERROR : NO_INIT,
+ isEffectExistsOnAudioSession(&mType, &mUuid, kDefaultOutputEffectPriority - 1,
+ playback->getAudioTrackHandle()->getSessionId()))
+ << "Effect should not have been added. " << mTypeStr;
+ EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
+ playback->stop();
+ playback.clear();
+}
+
+TEST_P(AudioPlaybackEffectTest, CheckOutputFlagCompatibility) {
+ SCOPED_TRACE(testing::Message()
+ << "\n selected effect type is :: " << mTypeStr
+ << "\n selected effect uuid is :: " << mUuidStr
+ << "\n audiotrack output flag : " << (mSelectFastMode ? "fast" : "default")
+ << "\n audio effect is fast compatible : "
+ << (mIsFastCompatibleEffect ? "yes" : "no"));
+
+ audio_attributes_t attributes;
+ attributes.usage = AUDIO_USAGE_MEDIA;
+ attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+ audio_session_t sessionId =
+ (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ sp<AudioEffectCallback> cb = sp<AudioEffectCallback>::make();
+ sp<AudioEffect> audioEffect =
+ createEffect(&mType, &mUuid, kDefaultOutputEffectPriority, sessionId, cb);
+ ASSERT_EQ(OK, audioEffect->initCheck());
+ ASSERT_EQ(NO_ERROR, audioEffect->setEnabled(true));
+ auto playback = sp<AudioPlayback>::make(
+ 0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_MONO,
+ mSelectFastMode ? AUDIO_OUTPUT_FLAG_FAST : AUDIO_OUTPUT_FLAG_NONE, sessionId,
+ AudioTrack::TRANSFER_SHARED, &attributes);
+ ASSERT_NE(nullptr, playback);
+ ASSERT_EQ(NO_ERROR, playback->loadResource("/data/local/tmp/bbb_1ch_8kHz_s16le.raw"));
+ EXPECT_EQ(NO_ERROR, playback->create());
+ EXPECT_EQ(NO_ERROR, playback->start());
+
+ EXPECT_EQ(ALREADY_EXISTS, isEffectExistsOnAudioSession(
+ &mType, &mUuid, kDefaultOutputEffectPriority - 1, sessionId))
+ << "Effect should have been added. " << mTypeStr;
+ if (mSelectFastMode) {
+ EXPECT_EQ(mIsFastCompatibleEffect ? AUDIO_OUTPUT_FLAG_FAST : 0,
+ playback->getAudioTrackHandle()->getFlags() & AUDIO_OUTPUT_FLAG_FAST);
+ }
+ EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
+ EXPECT_EQ(NO_ERROR, playback->getAudioTrackHandle()->attachAuxEffect(0));
+ playback->stop();
+ playback.clear();
+ EXPECT_TRUE(cb->receivedFramesProcessed)
+ << "AudioEffect frames processed callback not received";
+}
+
+INSTANTIATE_TEST_SUITE_P(EffectParameterizedTests, AudioPlaybackEffectTest, ::testing::Bool());
+
+TEST(AudioEffectTest, TestHapticEffect) {
+ if (!AudioSystem::isHapticPlaybackSupported())
+ GTEST_SKIP() << "Haptic playback is not supported";
+ int32_t selectedEffect = -1;
+ std::vector<effect_descriptor_t> descriptors;
+ ASSERT_NO_FATAL_FAILURE(listEffectsAvailable(descriptors));
+ for (auto i = 0; i < descriptors.size(); i++) {
+ if (!isHapticGenerator(descriptors[i])) continue;
+ selectedEffect = i;
+ break;
+ }
+ if (selectedEffect == -1) GTEST_SKIP() << "expected at least one valid effect";
+
+ effect_uuid_t* selectedEffectType = &descriptors[selectedEffect].type;
+ effect_uuid_t* selectedEffectUuid = &descriptors[selectedEffect].uuid;
+ auto [type, uuid] = typeAndUuidToString(descriptors[selectedEffect]);
+
+ SCOPED_TRACE(testing::Message() << "\n selected effect type is :: " << type
+ << "\n selected effect uuid is :: " << uuid);
+
+ audio_attributes_t attributes;
+ attributes.usage = AUDIO_USAGE_MEDIA;
+ attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+ audio_session_t sessionId =
+ (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ sp<AudioEffectCallback> cb = sp<AudioEffectCallback>::make();
+ sp<AudioEffect> audioEffect = createEffect(selectedEffectType, selectedEffectUuid,
+ kDefaultOutputEffectPriority, sessionId, cb);
+ ASSERT_EQ(OK, audioEffect->initCheck());
+ ASSERT_EQ(NO_ERROR, audioEffect->setEnabled(true));
+ auto playback = sp<AudioPlayback>::make(0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_OUT_STEREO, AUDIO_OUTPUT_FLAG_NONE,
+ sessionId, AudioTrack::TRANSFER_SHARED, &attributes);
+ ASSERT_NE(nullptr, playback);
+ ASSERT_EQ(NO_ERROR, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"));
+ EXPECT_EQ(NO_ERROR, playback->create());
+ EXPECT_EQ(NO_ERROR, playback->start());
+ EXPECT_TRUE(isEffectExistsOnAudioSession(selectedEffectType, selectedEffectUuid,
+ kDefaultOutputEffectPriority - 1, sessionId))
+ << "Effect should have been added. " << type;
+ EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
+ playback->stop();
+ playback.clear();
+ EXPECT_TRUE(cb->receivedFramesProcessed)
+ << "AudioEffect frames processed callback not received";
+}
diff --git a/media/libaudioclient/tests/audiorecord_tests.cpp b/media/libaudioclient/tests/audiorecord_tests.cpp
new file mode 100644
index 0000000..8c63a6d
--- /dev/null
+++ b/media/libaudioclient/tests/audiorecord_tests.cpp
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 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 "AudioRecordTest"
+
+#include <gtest/gtest.h>
+
+#include "audio_test_utils.h"
+
+using namespace android;
+
+class AudioRecordTest : public ::testing::Test {
+ public:
+ virtual void SetUp() override {
+ mAC = new AudioCapture(AUDIO_SOURCE_DEFAULT, 44100, AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_IN_FRONT);
+ ASSERT_NE(nullptr, mAC);
+ ASSERT_EQ(OK, mAC->create()) << "record creation failed";
+ }
+
+ virtual void TearDown() override {
+ if (mAC) ASSERT_EQ(OK, mAC->stop());
+ }
+
+ sp<AudioCapture> mAC;
+};
+
+class AudioRecordCreateTest
+ : public ::testing::TestWithParam<
+ std::tuple<uint32_t, audio_format_t, audio_channel_mask_t, audio_input_flags_t,
+ audio_session_t, audio_source_t>> {
+ public:
+ AudioRecordCreateTest()
+ : mSampleRate(std::get<0>(GetParam())),
+ mFormat(std::get<1>(GetParam())),
+ mChannelMask(std::get<2>(GetParam())),
+ mFlags(std::get<3>(GetParam())),
+ mSessionId(std::get<4>(GetParam())),
+ mInputSource(std::get<5>(GetParam())){};
+
+ const uint32_t mSampleRate;
+ const audio_format_t mFormat;
+ const audio_channel_mask_t mChannelMask;
+ const audio_input_flags_t mFlags;
+ const audio_session_t mSessionId;
+ const audio_source_t mInputSource;
+ const AudioRecord::transfer_type mTransferType = AudioRecord::TRANSFER_OBTAIN;
+
+ sp<AudioCapture> mAC;
+
+ virtual void SetUp() override {
+ mAC = new AudioCapture(mInputSource, mSampleRate, mFormat, mChannelMask, mFlags, mSessionId,
+ mTransferType);
+ ASSERT_NE(nullptr, mAC);
+ ASSERT_EQ(OK, mAC->create()) << "record creation failed";
+ }
+
+ virtual void TearDown() override {
+ if (mAC) ASSERT_EQ(OK, mAC->stop());
+ }
+};
+
+TEST_F(AudioRecordTest, TestSimpleRecord) {
+ EXPECT_EQ(OK, mAC->start()) << "start recording failed";
+ EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+}
+
+TEST_F(AudioRecordTest, TestAudioCbNotifier) {
+ EXPECT_EQ(BAD_VALUE, mAC->getAudioRecordHandle()->addAudioDeviceCallback(nullptr));
+ sp<OnAudioDeviceUpdateNotifier> cb = sp<OnAudioDeviceUpdateNotifier>::make();
+ sp<OnAudioDeviceUpdateNotifier> cbOld = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, mAC->getAudioRecordHandle()->addAudioDeviceCallback(cbOld));
+ EXPECT_EQ(INVALID_OPERATION, mAC->getAudioRecordHandle()->addAudioDeviceCallback(cbOld));
+ EXPECT_EQ(OK, mAC->getAudioRecordHandle()->addAudioDeviceCallback(cb));
+ EXPECT_EQ(OK, mAC->start()) << "record creation failed";
+ EXPECT_EQ(OK, cb->waitForAudioDeviceCb());
+ EXPECT_EQ(AUDIO_IO_HANDLE_NONE, cbOld->mAudioIo);
+ EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, cbOld->mDeviceId);
+ EXPECT_NE(AUDIO_IO_HANDLE_NONE, cb->mAudioIo);
+ EXPECT_NE(AUDIO_PORT_HANDLE_NONE, cb->mDeviceId);
+ EXPECT_EQ(BAD_VALUE, mAC->getAudioRecordHandle()->removeAudioDeviceCallback(nullptr));
+ EXPECT_EQ(INVALID_OPERATION, mAC->getAudioRecordHandle()->removeAudioDeviceCallback(cbOld));
+ EXPECT_EQ(OK, mAC->getAudioRecordHandle()->removeAudioDeviceCallback(cb));
+ mAC->stop();
+}
+
+TEST_F(AudioRecordTest, TestEventRecordTrackPause) {
+ const auto playback = sp<AudioPlayback>::make(
+ 8000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_MONO);
+ ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_1ch_8kHz_s16le.raw"))
+ << "Unable to open Resource";
+ EXPECT_EQ(OK, playback->create()) << "AudioTrack Creation failed";
+ audio_session_t audioTrackSession = playback->getAudioTrackHandle()->getSessionId();
+ EXPECT_EQ(OK, mAC->start(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE, audioTrackSession))
+ << "record creation failed";
+ EXPECT_EQ(OK, playback->start());
+ RawBuffer buffer;
+ status_t status = mAC->obtainBufferCb(buffer);
+ EXPECT_EQ(status, TIMED_OUT) << "Not expecting any callbacks until track sends Sync event";
+ playback->getAudioTrackHandle()->pause();
+ EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+ playback->stop();
+}
+
+TEST_F(AudioRecordTest, TestEventRecordTrackStop) {
+ const auto playback = sp<AudioPlayback>::make(
+ 8000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_MONO);
+ ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_1ch_8kHz_s16le.raw"))
+ << "Unable to open Resource";
+ EXPECT_EQ(OK, playback->create()) << "AudioTrack Creation failed";
+ audio_session_t audioTrackSession = playback->getAudioTrackHandle()->getSessionId();
+ EXPECT_EQ(OK, mAC->start(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE, audioTrackSession))
+ << "record creation failed";
+ EXPECT_EQ(OK, playback->start());
+ RawBuffer buffer;
+ status_t status = mAC->obtainBufferCb(buffer);
+ EXPECT_EQ(status, TIMED_OUT) << "Not expecting any callbacks until track sends Sync event";
+ playback->stop();
+ EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+}
+
+TEST_F(AudioRecordTest, TestGetSetMarker) {
+ mAC->mMarkerPosition = (mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1);
+ EXPECT_EQ(OK, mAC->getAudioRecordHandle()->setMarkerPosition(mAC->mMarkerPosition))
+ << "setMarkerPosition() failed";
+ uint32_t marker;
+ EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getMarkerPosition(&marker))
+ << "getMarkerPosition() failed";
+ EXPECT_EQ(OK, mAC->start()) << "start recording failed";
+ EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+ EXPECT_EQ(marker, mAC->mMarkerPosition)
+ << "configured marker and received marker are different";
+ EXPECT_EQ(mAC->mReceivedCbMarkerAtPosition, mAC->mMarkerPosition)
+ << "configured marker and received cb marker are different";
+}
+
+TEST_F(AudioRecordTest, TestGetSetMarkerPeriodical) {
+ mAC->mMarkerPeriod = (mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1);
+ EXPECT_EQ(OK, mAC->getAudioRecordHandle()->setPositionUpdatePeriod(mAC->mMarkerPeriod))
+ << "setPositionUpdatePeriod() failed";
+ uint32_t marker;
+ EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPositionUpdatePeriod(&marker))
+ << "getPositionUpdatePeriod() failed";
+ EXPECT_EQ(OK, mAC->start()) << "start recording failed";
+ EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+ EXPECT_EQ(marker, mAC->mMarkerPeriod) << "configured marker and received marker are different";
+ EXPECT_EQ(mAC->mReceivedCbMarkerCount, mAC->mNumFramesToRecord / mAC->mMarkerPeriod)
+ << "configured marker and received cb marker are different";
+}
+
+TEST_F(AudioRecordTest, TestGetPosition) {
+ uint32_t position;
+ EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPosition(&position)) << "getPosition() failed";
+ EXPECT_EQ(0, position);
+ EXPECT_EQ(OK, mAC->start()) << "start recording failed";
+ EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+ EXPECT_EQ(OK, mAC->stop());
+ EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPosition(&position)) << "getPosition() failed";
+}
+
+// TODO: Add checkPatchCapture(), verify the information of patch via dumpPort() and dumpPatch()
+TEST_P(AudioRecordCreateTest, TestCreateRecord) {
+ EXPECT_EQ(mFormat, mAC->getAudioRecordHandle()->format());
+ EXPECT_EQ(audio_channel_count_from_in_mask(mChannelMask),
+ mAC->getAudioRecordHandle()->channelCount());
+ if (mAC->mFrameCount != 0)
+ EXPECT_LE(mAC->mFrameCount, mAC->getAudioRecordHandle()->frameCount());
+ EXPECT_EQ(mInputSource, mAC->getAudioRecordHandle()->inputSource());
+ if (mSampleRate != 0) EXPECT_EQ(mSampleRate, mAC->getAudioRecordHandle()->getSampleRate());
+ if (mSessionId != AUDIO_SESSION_NONE)
+ EXPECT_EQ(mSessionId, mAC->getAudioRecordHandle()->getSessionId());
+ if (mTransferType != AudioRecord::TRANSFER_CALLBACK) {
+ uint32_t marker;
+ mAC->mMarkerPosition = (mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1);
+ EXPECT_EQ(INVALID_OPERATION,
+ mAC->getAudioRecordHandle()->setMarkerPosition(mAC->mMarkerPosition));
+ EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getMarkerPosition(&marker));
+ EXPECT_EQ(INVALID_OPERATION,
+ mAC->getAudioRecordHandle()->setPositionUpdatePeriod(mAC->mMarkerPosition));
+ EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPositionUpdatePeriod(&marker));
+ }
+ EXPECT_EQ(OK, mAC->start()) << "start recording failed";
+ EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+}
+
+// for port primary input
+INSTANTIATE_TEST_SUITE_P(AudioRecordPrimaryInput, AudioRecordCreateTest,
+ ::testing::Combine(::testing::Values(8000, 11025, 12000, 16000, 22050,
+ 24000, 32000, 44100, 48000),
+ ::testing::Values(AUDIO_FORMAT_PCM_8_24_BIT),
+ ::testing::Values(AUDIO_CHANNEL_IN_MONO,
+ AUDIO_CHANNEL_IN_STEREO,
+ AUDIO_CHANNEL_IN_FRONT_BACK),
+ ::testing::Values(AUDIO_INPUT_FLAG_NONE),
+ ::testing::Values(AUDIO_SESSION_NONE),
+ ::testing::Values(AUDIO_SOURCE_DEFAULT)));
+
+// for port fast input
+INSTANTIATE_TEST_SUITE_P(AudioRecordFastInput, AudioRecordCreateTest,
+ ::testing::Combine(::testing::Values(8000, 11025, 12000, 16000, 22050,
+ 24000, 32000, 44100, 48000),
+ ::testing::Values(AUDIO_FORMAT_PCM_8_24_BIT),
+ ::testing::Values(AUDIO_CHANNEL_IN_MONO,
+ AUDIO_CHANNEL_IN_STEREO,
+ AUDIO_CHANNEL_IN_FRONT_BACK),
+ ::testing::Values(AUDIO_INPUT_FLAG_FAST),
+ ::testing::Values(AUDIO_SESSION_NONE),
+ ::testing::Values(AUDIO_SOURCE_DEFAULT)));
+
+// misc
+INSTANTIATE_TEST_SUITE_P(AudioRecordMiscInput, AudioRecordCreateTest,
+ ::testing::Combine(::testing::Values(48000),
+ ::testing::Values(AUDIO_FORMAT_PCM_16_BIT),
+ ::testing::Values(AUDIO_CHANNEL_IN_MONO),
+ ::testing::Values(AUDIO_INPUT_FLAG_NONE),
+ ::testing::Values(AUDIO_SESSION_NONE),
+ ::testing::Values(AUDIO_SOURCE_MIC,
+ AUDIO_SOURCE_CAMCORDER,
+ AUDIO_SOURCE_VOICE_RECOGNITION,
+ AUDIO_SOURCE_VOICE_COMMUNICATION,
+ AUDIO_SOURCE_UNPROCESSED)));
diff --git a/media/libaudioclient/tests/audiorouting_tests.cpp b/media/libaudioclient/tests/audiorouting_tests.cpp
new file mode 100644
index 0000000..19d1abc
--- /dev/null
+++ b/media/libaudioclient/tests/audiorouting_tests.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 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
+
+#include <cutils/properties.h>
+#include <gtest/gtest.h>
+#include <string.h>
+
+#include "audio_test_utils.h"
+
+using namespace android;
+
+// UNIT TEST
+TEST(AudioTrackTest, TestPerformanceMode) {
+ std::vector<struct audio_port_v7> ports;
+ ASSERT_EQ(OK, listAudioPorts(ports));
+ audio_output_flags_t output_flags[] = {AUDIO_OUTPUT_FLAG_FAST, AUDIO_OUTPUT_FLAG_DEEP_BUFFER};
+ audio_flags_mask_t flags[] = {AUDIO_FLAG_LOW_LATENCY, AUDIO_FLAG_DEEP_BUFFER};
+ bool hasFlag = false;
+ for (int i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+ hasFlag = false;
+ for (const auto& port : ports) {
+ if (port.role == AUDIO_PORT_ROLE_SOURCE && port.type == AUDIO_PORT_TYPE_MIX) {
+ if ((port.active_config.flags.output & output_flags[i]) != 0) {
+ hasFlag = true;
+ break;
+ }
+ }
+ }
+ if (!hasFlag) continue;
+ audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+ attributes.usage = AUDIO_USAGE_MEDIA;
+ attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+ attributes.flags = flags[i];
+ sp<AudioPlayback> ap = sp<AudioPlayback>::make(0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_OUT_STEREO,
+ AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE,
+ AudioTrack::TRANSFER_OBTAIN, &attributes);
+ ASSERT_NE(nullptr, ap);
+ ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+ << "Unable to open Resource";
+ EXPECT_EQ(OK, ap->create()) << "track creation failed";
+ sp<OnAudioDeviceUpdateNotifier> cb = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, ap->getAudioTrackHandle()->addAudioDeviceCallback(cb));
+ EXPECT_EQ(OK, ap->start()) << "audio track start failed";
+ EXPECT_EQ(OK, ap->onProcess());
+ EXPECT_EQ(OK, cb->waitForAudioDeviceCb());
+ EXPECT_TRUE(checkPatchPlayback(cb->mAudioIo, cb->mDeviceId));
+ EXPECT_NE(0, ap->getAudioTrackHandle()->getFlags() & output_flags[i]);
+ audio_patch patch;
+ EXPECT_EQ(OK, getPatchForOutputMix(cb->mAudioIo, patch));
+ for (auto j = 0; j < patch.num_sources; j++) {
+ if (patch.sources[j].type == AUDIO_PORT_TYPE_MIX &&
+ patch.sources[j].ext.mix.handle == cb->mAudioIo) {
+ if ((patch.sources[j].flags.output & output_flags[i]) == 0) {
+ ADD_FAILURE() << "expected output flag " << output_flags[i] << " is absent";
+ std::cerr << dumpPortConfig(patch.sources[j]);
+ }
+ }
+ }
+ ap->stop();
+ }
+}
+
+TEST(AudioTrackTest, DefaultRoutingTest) {
+ audio_port_v7 port;
+ if (OK != getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port)) {
+ GTEST_SKIP() << "remote submix in device not connected";
+ }
+
+ // create record instance
+ sp<AudioCapture> capture = sp<AudioCapture>::make(
+ AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO);
+ ASSERT_NE(nullptr, capture);
+ EXPECT_EQ(OK, capture->create()) << "record creation failed";
+ sp<OnAudioDeviceUpdateNotifier> cbCapture = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, capture->getAudioRecordHandle()->addAudioDeviceCallback(cbCapture));
+
+ // create playback instance
+ sp<AudioPlayback> playback = sp<AudioPlayback>::make(
+ 48000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE);
+ ASSERT_NE(nullptr, playback);
+ ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+ << "Unable to open Resource";
+ EXPECT_EQ(OK, playback->create()) << "track creation failed";
+ sp<OnAudioDeviceUpdateNotifier> cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, playback->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback));
+
+ // capture should be routed to submix in port
+ EXPECT_EQ(OK, capture->start()) << "start recording failed";
+ EXPECT_EQ(OK, cbCapture->waitForAudioDeviceCb());
+ EXPECT_EQ(port.id, capture->getAudioRecordHandle()->getRoutedDeviceId())
+ << "Capture NOT routed on expected port";
+
+ // capture start should create submix out port
+ status_t status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port);
+ EXPECT_EQ(OK, status) << "Could not find port";
+
+ // playback should be routed to submix out as long as capture is active
+ EXPECT_EQ(OK, playback->start()) << "audio track start failed";
+ EXPECT_EQ(OK, cbPlayback->waitForAudioDeviceCb());
+ EXPECT_EQ(port.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
+ << "Playback NOT routed on expected port";
+
+ capture->stop();
+ playback->stop();
+}
+
+class AudioRoutingTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ audio_port_v7 port;
+ if (OK != getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port)) {
+ GTEST_SKIP() << "remote submix in device not connected";
+ }
+ uint32_t mixType = MIX_TYPE_PLAYERS;
+ uint32_t mixFlag = MIX_ROUTE_FLAG_LOOP_BACK;
+ audio_devices_t deviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+ AudioMixMatchCriterion criterion(AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT,
+ RULE_MATCH_ATTRIBUTE_USAGE);
+ std::vector<AudioMixMatchCriterion> criteria{criterion};
+ audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+ config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ config.format = AUDIO_FORMAT_PCM_16_BIT;
+ config.sample_rate = 48000;
+ AudioMix mix(criteria, mixType, config, mixFlag, String8{mAddress.c_str()}, 0);
+ mix.mDeviceType = deviceType;
+ mMixes.push(mix);
+ if (OK == AudioSystem::registerPolicyMixes(mMixes, true)) {
+ mPolicyMixRegistered = true;
+ }
+ ASSERT_TRUE(mPolicyMixRegistered) << "register policy mix failed";
+ }
+
+ void TearDown() override {
+ if (mPolicyMixRegistered) {
+ EXPECT_EQ(OK, AudioSystem::registerPolicyMixes(mMixes, false));
+ }
+ }
+
+ bool mPolicyMixRegistered{false};
+ std::string mAddress{"mix_1"};
+ Vector<AudioMix> mMixes;
+};
+
+TEST_F(AudioRoutingTest, ConcurrentDynamicRoutingTest) {
+ audio_port_v7 port, port_mix;
+ // expect legacy submix in port to be connected
+ status_t status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port);
+ EXPECT_EQ(OK, status) << "Could not find port";
+
+ // as policy mix is registered, expect submix in port with mAddress to be connected
+ status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, mAddress, port_mix);
+ EXPECT_EQ(OK, status) << "Could not find port";
+
+ // create playback instance
+ sp<AudioPlayback> playback = sp<AudioPlayback>::make(
+ 48000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE, AudioTrack::TRANSFER_OBTAIN);
+ ASSERT_NE(nullptr, playback);
+ ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+ << "Unable to open Resource";
+ EXPECT_EQ(OK, playback->create()) << "track creation failed";
+ sp<OnAudioDeviceUpdateNotifier> cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, playback->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback));
+
+ // create capture instances on different ports
+ sp<AudioCapture> captureA = sp<AudioCapture>::make(
+ AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO);
+ ASSERT_NE(nullptr, captureA);
+ EXPECT_EQ(OK, captureA->create()) << "record creation failed";
+ sp<OnAudioDeviceUpdateNotifier> cbCaptureA = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, captureA->getAudioRecordHandle()->addAudioDeviceCallback(cbCaptureA));
+
+ audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
+ attr.source = AUDIO_SOURCE_REMOTE_SUBMIX;
+ sprintf(attr.tags, "addr=%s", mAddress.c_str());
+ sp<AudioCapture> captureB = sp<AudioCapture>::make(
+ AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
+ AUDIO_INPUT_FLAG_NONE, AUDIO_SESSION_ALLOCATE, AudioRecord::TRANSFER_CALLBACK, &attr);
+ ASSERT_NE(nullptr, captureB);
+ EXPECT_EQ(OK, captureB->create()) << "record creation failed";
+ sp<OnAudioDeviceUpdateNotifier> cbCaptureB = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, captureB->getAudioRecordHandle()->addAudioDeviceCallback(cbCaptureB));
+
+ // launch
+ EXPECT_EQ(OK, captureA->start()) << "start recording failed";
+ EXPECT_EQ(OK, cbCaptureA->waitForAudioDeviceCb());
+ EXPECT_EQ(port.id, captureA->getAudioRecordHandle()->getRoutedDeviceId())
+ << "Capture NOT routed on expected port";
+
+ EXPECT_EQ(OK, captureB->start()) << "start recording failed";
+ EXPECT_EQ(OK, cbCaptureB->waitForAudioDeviceCb());
+ EXPECT_EQ(port_mix.id, captureB->getAudioRecordHandle()->getRoutedDeviceId())
+ << "Capture NOT routed on expected port";
+
+ // as record started, expect submix out ports to be connected
+ status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port);
+ EXPECT_EQ(OK, status) << "unexpected submix out port found";
+
+ status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mAddress, port_mix);
+ EXPECT_EQ(OK, status) << "Could not find port";
+
+ // check if playback routed to desired port
+ EXPECT_EQ(OK, playback->start());
+ EXPECT_EQ(OK, cbPlayback->waitForAudioDeviceCb());
+ EXPECT_EQ(port_mix.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
+ << "Playback NOT routed on expected port";
+
+ captureB->stop();
+
+ // check if mAddress submix out is disconnected as capture session is stopped
+ status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mAddress, port_mix);
+ EXPECT_NE(OK, status) << "unexpected submix in port found";
+
+ // check if legacy submix out is connected
+ status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port);
+ EXPECT_EQ(OK, status) << "port not found";
+
+ // unregister policy
+ EXPECT_EQ(OK, AudioSystem::registerPolicyMixes(mMixes, false));
+ mPolicyMixRegistered = false;
+
+ // as policy mix is unregistered, expect submix in port with mAddress to be disconnected
+ status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, mAddress, port_mix);
+ EXPECT_NE(OK, status) << "unexpected submix in port found";
+
+ playback->onProcess();
+ // as captureA is active, it should re route to legacy submix
+ EXPECT_EQ(OK, cbPlayback->waitForAudioDeviceCb(port.id));
+ EXPECT_EQ(port.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
+ << "Playback NOT routed on expected port";
+
+ captureA->stop();
+ playback->stop();
+}
diff --git a/media/libaudioclient/tests/audiosystem_tests.cpp b/media/libaudioclient/tests/audiosystem_tests.cpp
new file mode 100644
index 0000000..682f43e
--- /dev/null
+++ b/media/libaudioclient/tests/audiosystem_tests.cpp
@@ -0,0 +1,581 @@
+/*
+ * Copyright (C) 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_TAG "AudioSystemTest"
+
+#include <string.h>
+
+#include <gtest/gtest.h>
+#include <media/IAudioFlinger.h>
+#include <utils/Log.h>
+
+#include "audio_test_utils.h"
+
+using namespace android;
+
+void anyPatchContainsInputDevice(audio_port_handle_t deviceId, bool& res) {
+ std::vector<struct audio_patch> patches;
+ status_t status = listAudioPatches(patches);
+ ASSERT_EQ(OK, status);
+ res = false;
+ for (const auto& patch : patches) {
+ if (patchContainsInputDevice(deviceId, patch)) {
+ res = true;
+ return;
+ }
+ }
+}
+
+class AudioSystemTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ mAF = AudioSystem::get_audio_flinger();
+ ASSERT_NE(mAF, nullptr) << "Permission denied";
+ }
+
+ void TearDown() override {
+ if (mPlayback) {
+ mPlayback->stop();
+ mCbPlayback.clear();
+ mPlayback.clear();
+ }
+ if (mCapture) {
+ mCapture->stop();
+ mCbRecord.clear();
+ mCapture.clear();
+ }
+ }
+
+ void createPlaybackSession(void);
+ void createRecordSession(void);
+
+ sp<IAudioFlinger> mAF;
+ sp<AudioPlayback> mPlayback;
+ sp<OnAudioDeviceUpdateNotifier> mCbPlayback;
+ sp<AudioCapture> mCapture;
+ sp<OnAudioDeviceUpdateNotifier> mCbRecord;
+};
+
+void AudioSystemTest::createPlaybackSession(void) {
+ audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+ attributes.usage = AUDIO_USAGE_MEDIA;
+ attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+ mPlayback = sp<AudioPlayback>::make(48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ AUDIO_OUTPUT_FLAG_FAST, AUDIO_SESSION_NONE,
+ AudioTrack::TRANSFER_SHARED, &attributes);
+ ASSERT_NE(nullptr, mPlayback);
+ ASSERT_EQ(NO_ERROR, mPlayback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"));
+ EXPECT_EQ(NO_ERROR, mPlayback->create());
+ mCbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, mPlayback->getAudioTrackHandle()->addAudioDeviceCallback(mCbPlayback));
+ EXPECT_EQ(NO_ERROR, mPlayback->start());
+ EXPECT_EQ(OK, mPlayback->onProcess());
+ EXPECT_EQ(OK, mCbPlayback->waitForAudioDeviceCb());
+}
+
+void AudioSystemTest::createRecordSession(void) {
+ mCapture = new AudioCapture(AUDIO_SOURCE_DEFAULT, 44100, AUDIO_FORMAT_PCM_8_24_BIT,
+ AUDIO_CHANNEL_IN_MONO, AUDIO_INPUT_FLAG_FAST);
+ ASSERT_NE(nullptr, mCapture);
+ ASSERT_EQ(OK, mCapture->create()) << "record creation failed";
+ mCbRecord = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, mCapture->getAudioRecordHandle()->addAudioDeviceCallback(mCbRecord));
+ EXPECT_EQ(OK, mCapture->start()) << "record creation failed";
+ EXPECT_EQ(OK, mCbRecord->waitForAudioDeviceCb());
+}
+
+// UNIT TESTS
+TEST_F(AudioSystemTest, CheckServerSideValues) {
+ ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+ EXPECT_GT(mAF->sampleRate(mCbPlayback->mAudioIo), 0);
+ EXPECT_NE(mAF->format(mCbPlayback->mAudioIo), AUDIO_FORMAT_INVALID);
+ EXPECT_GT(mAF->frameCount(mCbPlayback->mAudioIo), 0);
+ size_t frameCountHal, frameCountHalCache;
+ frameCountHal = mAF->frameCountHAL(mCbPlayback->mAudioIo);
+ EXPECT_GT(frameCountHal, 0);
+ EXPECT_EQ(OK, AudioSystem::getFrameCountHAL(mCbPlayback->mAudioIo, &frameCountHalCache));
+ EXPECT_EQ(frameCountHal, frameCountHalCache);
+ EXPECT_GT(mAF->latency(mCbPlayback->mAudioIo), 0);
+ // client side latency is at least server side latency
+ EXPECT_LE(mAF->latency(mCbPlayback->mAudioIo), mPlayback->getAudioTrackHandle()->latency());
+
+ ASSERT_NO_FATAL_FAILURE(createRecordSession());
+ EXPECT_GT(mAF->sampleRate(mCbRecord->mAudioIo), 0);
+ // EXPECT_NE(mAF->format(mCbRecord->mAudioIo), AUDIO_FORMAT_INVALID);
+ EXPECT_GT(mAF->frameCount(mCbRecord->mAudioIo), 0);
+ EXPECT_GT(mAF->frameCountHAL(mCbRecord->mAudioIo), 0);
+ frameCountHal = mAF->frameCountHAL(mCbRecord->mAudioIo);
+ EXPECT_GT(frameCountHal, 0);
+ EXPECT_EQ(OK, AudioSystem::getFrameCountHAL(mCbRecord->mAudioIo, &frameCountHalCache));
+ EXPECT_EQ(frameCountHal, frameCountHalCache);
+ // EXPECT_GT(mAF->latency(mCbRecord->mAudioIo), 0);
+ // client side latency is at least server side latency
+ // EXPECT_LE(mAF->latency(mCbRecord->mAudioIo), mCapture->getAudioRecordHandle()->latency());
+
+ EXPECT_GT(AudioSystem::getPrimaryOutputSamplingRate(), 0); // first fast mixer sample rate
+ EXPECT_GT(AudioSystem::getPrimaryOutputFrameCount(), 0); // fast mixer frame count
+}
+
+TEST_F(AudioSystemTest, GetSetMasterVolume) {
+ ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+ float origVol, tstVol;
+ EXPECT_EQ(NO_ERROR, AudioSystem::getMasterVolume(&origVol));
+ float newVol;
+ if (origVol + 0.2f > 1.0f) {
+ newVol = origVol - 0.2f;
+ } else {
+ newVol = origVol + 0.2f;
+ }
+ EXPECT_EQ(NO_ERROR, AudioSystem::setMasterVolume(newVol));
+ EXPECT_EQ(NO_ERROR, AudioSystem::getMasterVolume(&tstVol));
+ EXPECT_EQ(newVol, tstVol);
+ EXPECT_EQ(NO_ERROR, AudioSystem::setMasterVolume(origVol));
+ EXPECT_EQ(NO_ERROR, AudioSystem::getMasterVolume(&tstVol));
+ EXPECT_EQ(origVol, tstVol);
+}
+
+TEST_F(AudioSystemTest, GetSetMasterMute) {
+ ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+ bool origMuteState, tstMuteState;
+ EXPECT_EQ(NO_ERROR, AudioSystem::getMasterMute(&origMuteState));
+ EXPECT_EQ(NO_ERROR, AudioSystem::setMasterMute(!origMuteState));
+ EXPECT_EQ(NO_ERROR, AudioSystem::getMasterMute(&tstMuteState));
+ EXPECT_EQ(!origMuteState, tstMuteState);
+ EXPECT_EQ(NO_ERROR, AudioSystem::setMasterMute(origMuteState));
+ EXPECT_EQ(NO_ERROR, AudioSystem::getMasterMute(&tstMuteState));
+ EXPECT_EQ(origMuteState, tstMuteState);
+}
+
+TEST_F(AudioSystemTest, GetSetMicMute) {
+ ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+ bool origMuteState, tstMuteState;
+ EXPECT_EQ(NO_ERROR, AudioSystem::isMicrophoneMuted(&origMuteState));
+ EXPECT_EQ(NO_ERROR, AudioSystem::muteMicrophone(!origMuteState));
+ EXPECT_EQ(NO_ERROR, AudioSystem::isMicrophoneMuted(&tstMuteState));
+ EXPECT_EQ(!origMuteState, tstMuteState);
+ EXPECT_EQ(NO_ERROR, AudioSystem::muteMicrophone(origMuteState));
+ EXPECT_EQ(NO_ERROR, AudioSystem::isMicrophoneMuted(&tstMuteState));
+ EXPECT_EQ(origMuteState, tstMuteState);
+}
+
+TEST_F(AudioSystemTest, GetSetMasterBalance) {
+ ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+ float origBalance, tstBalance;
+ EXPECT_EQ(OK, AudioSystem::getMasterBalance(&origBalance));
+ float newBalance;
+ if (origBalance + 0.2f > 1.0f) {
+ newBalance = origBalance - 0.2f;
+ } else {
+ newBalance = origBalance + 0.2f;
+ }
+ EXPECT_EQ(OK, AudioSystem::setMasterBalance(newBalance));
+ EXPECT_EQ(OK, AudioSystem::getMasterBalance(&tstBalance));
+ EXPECT_EQ(newBalance, tstBalance);
+ EXPECT_EQ(OK, AudioSystem::setMasterBalance(origBalance));
+ EXPECT_EQ(OK, AudioSystem::getMasterBalance(&tstBalance));
+ EXPECT_EQ(origBalance, tstBalance);
+}
+
+TEST_F(AudioSystemTest, GetStreamVolume) {
+ ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+ float origStreamVol;
+ EXPECT_EQ(NO_ERROR, AudioSystem::getStreamVolume(AUDIO_STREAM_MUSIC, &origStreamVol,
+ mCbPlayback->mAudioIo));
+}
+
+TEST_F(AudioSystemTest, GetStreamMute) {
+ ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+ bool origMuteState;
+ EXPECT_EQ(NO_ERROR, AudioSystem::getStreamMute(AUDIO_STREAM_MUSIC, &origMuteState));
+}
+
+TEST_F(AudioSystemTest, StartAndStopAudioSource) {
+ std::vector<struct audio_port_v7> ports;
+ audio_port_config sourcePortConfig;
+ audio_attributes_t attributes = AudioSystem::streamTypeToAttributes(AUDIO_STREAM_MUSIC);
+ audio_port_handle_t sourcePortHandle = AUDIO_PORT_HANDLE_NONE;
+
+ status_t status = listAudioPorts(ports);
+ ASSERT_EQ(OK, status);
+ if (ports.empty()) {
+ GTEST_SKIP() << "No ports returned by the audio system";
+ }
+
+ bool sourceFound = false;
+ for (const auto& port : ports) {
+ if (port.role != AUDIO_PORT_ROLE_SOURCE || port.type != AUDIO_PORT_TYPE_DEVICE) continue;
+ if (port.ext.device.type != AUDIO_DEVICE_IN_FM_TUNER) continue;
+ sourceFound = true;
+ sourcePortConfig = port.active_config;
+
+ bool patchFound;
+
+ // start audio source.
+ status_t ret =
+ AudioSystem::startAudioSource(&sourcePortConfig, &attributes, &sourcePortHandle);
+ EXPECT_EQ(OK, ret) << "AudioSystem::startAudioSource for source "
+ << audio_device_to_string(port.ext.device.type) << " failed";
+ if (ret != OK) continue;
+
+ // verify that patch is established by the source port.
+ ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(port.id, patchFound));
+ EXPECT_EQ(true, patchFound);
+ EXPECT_NE(sourcePortHandle, AUDIO_PORT_HANDLE_NONE);
+
+ if (sourcePortHandle != AUDIO_PORT_HANDLE_NONE) {
+ ret = AudioSystem::stopAudioSource(sourcePortHandle);
+ EXPECT_EQ(OK, ret) << "AudioSystem::stopAudioSource failed for handle "
+ << sourcePortHandle;
+ }
+
+ // verify that no source port patch exists.
+ ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(port.id, patchFound));
+ EXPECT_EQ(false, patchFound);
+ }
+ if (!sourceFound) {
+ GTEST_SKIP() << "No ports suitable for testing";
+ }
+}
+
+TEST_F(AudioSystemTest, CreateAndReleaseAudioPatch) {
+ status_t status;
+ struct audio_patch audioPatch;
+ std::vector<struct audio_port_v7> ports;
+ audio_patch_handle_t audioPatchHandle = AUDIO_PATCH_HANDLE_NONE;
+
+ bool patchFound = false;
+ audio_port_v7 sourcePort{};
+ audio_port_v7 sinkPort{};
+
+ audioPatch.id = 0;
+ audioPatch.num_sources = 1;
+ audioPatch.num_sinks = 1;
+
+ status = listAudioPorts(ports);
+ ASSERT_EQ(OK, status);
+ if (ports.empty()) {
+ GTEST_SKIP() << "No output devices returned by the audio system";
+ }
+
+ for (const auto& port : ports) {
+ if (port.role == AUDIO_PORT_ROLE_SOURCE && port.type == AUDIO_PORT_TYPE_DEVICE) {
+ sourcePort = port;
+ }
+ if (port.role == AUDIO_PORT_ROLE_SINK && port.type == AUDIO_PORT_TYPE_DEVICE &&
+ port.ext.device.type == AUDIO_DEVICE_OUT_SPEAKER) {
+ sinkPort = port;
+ }
+ }
+
+ audioPatch.sources[0] = sourcePort.active_config;
+ audioPatch.sinks[0] = sinkPort.active_config;
+
+ status = AudioSystem::createAudioPatch(&audioPatch, &audioPatchHandle);
+ EXPECT_EQ(OK, status) << "AudioSystem::createAudiopatch failed between source "
+ << sourcePort.ext.device.address << " and sink "
+ << sinkPort.ext.device.address;
+
+ // verify that patch is established between source and the sink.
+ ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(sourcePort.id, patchFound));
+ EXPECT_EQ(true, patchFound);
+
+ EXPECT_NE(AUDIO_PORT_HANDLE_NONE, audioPatchHandle);
+ status = AudioSystem::releaseAudioPatch(audioPatchHandle);
+ EXPECT_EQ(OK, status) << "AudioSystem::releaseAudioPatch failed between source "
+ << sourcePort.ext.device.address << " and sink "
+ << sinkPort.ext.device.address;
+
+ // verify that no patch is established between source and the sink after releaseAudioPatch.
+ ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(sourcePort.id, patchFound));
+ EXPECT_EQ(false, patchFound);
+}
+
+TEST_F(AudioSystemTest, GetAudioPort) {
+ std::vector<struct audio_port_v7> ports;
+ status_t status = listAudioPorts(ports);
+ ASSERT_EQ(OK, status);
+ for (const auto& port : ports) {
+ audio_port_v7 portTest{.id = port.id};
+ EXPECT_EQ(OK, AudioSystem::getAudioPort(&portTest));
+ EXPECT_TRUE(audio_ports_v7_are_equal(&portTest, &port));
+ }
+}
+
+TEST_F(AudioSystemTest, TestPhoneState) {
+ uid_t uid = getuid();
+ EXPECT_EQ(OK, AudioSystem::setPhoneState(AUDIO_MODE_RINGTONE, uid));
+ audio_mode_t state = AudioSystem::getPhoneState();
+ EXPECT_EQ(AUDIO_MODE_RINGTONE, state);
+ EXPECT_EQ(OK, AudioSystem::setPhoneState(AUDIO_MODE_IN_COMMUNICATION, uid));
+ state = AudioSystem::getPhoneState();
+ EXPECT_EQ(AUDIO_MODE_IN_COMMUNICATION, state);
+ EXPECT_EQ(OK, AudioSystem::setPhoneState(AUDIO_MODE_NORMAL, uid));
+ state = AudioSystem::getPhoneState();
+ EXPECT_EQ(AUDIO_MODE_NORMAL, state);
+}
+
+TEST_F(AudioSystemTest, GetDirectProfilesForAttributes) {
+ std::vector<audio_profile> audioProfiles;
+ audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+ attributes.usage = AUDIO_USAGE_MEDIA;
+ attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+ EXPECT_EQ(BAD_VALUE, AudioSystem::getDirectProfilesForAttributes(nullptr, nullptr));
+ EXPECT_EQ(BAD_VALUE, AudioSystem::getDirectProfilesForAttributes(nullptr, &audioProfiles));
+ EXPECT_EQ(BAD_VALUE, AudioSystem::getDirectProfilesForAttributes(&attributes, nullptr));
+ EXPECT_EQ(NO_ERROR, AudioSystem::getDirectProfilesForAttributes(&attributes, &audioProfiles));
+}
+
+bool isPublicStrategy(const AudioProductStrategy& strategy) {
+ bool result = true;
+ for (auto& attribute : strategy.getAudioAttributes()) {
+ if (attribute.getAttributes() == AUDIO_ATTRIBUTES_INITIALIZER &&
+ (uint32_t(attribute.getStreamType()) >= AUDIO_STREAM_PUBLIC_CNT)) {
+ result = false;
+ break;
+ }
+ }
+ return result;
+}
+
+TEST_F(AudioSystemTest, DevicesForRoleAndStrategy) {
+ std::vector<struct audio_port_v7> ports;
+ status_t status = listAudioPorts(ports);
+ ASSERT_EQ(OK, status);
+
+ std::vector<struct audio_port_v7> devicePorts;
+ for (const auto& port : ports) {
+ if (port.type == AUDIO_PORT_TYPE_DEVICE && audio_is_output_device(port.ext.device.type)) {
+ devicePorts.push_back(port);
+ }
+ }
+ if (devicePorts.empty()) {
+ GTEST_SKIP() << "No output devices returned by the audio system";
+ }
+
+ AudioProductStrategyVector strategies;
+ EXPECT_EQ(OK, AudioSystem::listAudioProductStrategies(strategies));
+ if (strategies.empty()) {
+ GTEST_SKIP() << "No strategies returned by the audio system";
+ }
+
+ audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+ attributes.usage = AUDIO_USAGE_MEDIA;
+
+ bool hasStrategyForMedia = false;
+ AudioProductStrategy mediaStrategy;
+ for (const auto& strategy : strategies) {
+ if (!isPublicStrategy(strategy)) continue;
+
+ for (const auto& att : strategy.getAudioAttributes()) {
+ if (strategy.attributesMatches(att.getAttributes(), attributes)) {
+ hasStrategyForMedia = true;
+ mediaStrategy = strategy;
+ break;
+ }
+ }
+ }
+
+ if (!hasStrategyForMedia) {
+ GTEST_SKIP() << "No strategies returned for music media";
+ }
+
+ AudioDeviceTypeAddrVector devices;
+ EXPECT_EQ(BAD_VALUE, AudioSystem::getDevicesForRoleAndStrategy(PRODUCT_STRATEGY_NONE,
+ DEVICE_ROLE_PREFERRED, devices));
+ EXPECT_EQ(BAD_VALUE, AudioSystem::getDevicesForRoleAndStrategy(mediaStrategy.getId(),
+ DEVICE_ROLE_NONE, devices));
+ status = AudioSystem::getDevicesForRoleAndStrategy(mediaStrategy.getId(), DEVICE_ROLE_PREFERRED,
+ devices);
+ if (status == NAME_NOT_FOUND) {
+ AudioDeviceTypeAddrVector outputDevices;
+ for (const auto& port : devicePorts) {
+ if (port.ext.device.type == AUDIO_DEVICE_OUT_SPEAKER) {
+ const AudioDeviceTypeAddr outputDevice(port.ext.device.type,
+ port.ext.device.address);
+ outputDevices.push_back(outputDevice);
+ }
+ }
+ EXPECT_EQ(OK, AudioSystem::setDevicesRoleForStrategy(mediaStrategy.getId(),
+ DEVICE_ROLE_PREFERRED, outputDevices));
+ EXPECT_EQ(OK, AudioSystem::getDevicesForRoleAndStrategy(mediaStrategy.getId(),
+ DEVICE_ROLE_PREFERRED, devices));
+ EXPECT_EQ(devices, outputDevices);
+ EXPECT_EQ(OK, AudioSystem::removeDevicesRoleForStrategy(mediaStrategy.getId(),
+ DEVICE_ROLE_PREFERRED));
+ EXPECT_EQ(NAME_NOT_FOUND, AudioSystem::getDevicesForRoleAndStrategy(
+ mediaStrategy.getId(), DEVICE_ROLE_PREFERRED, devices));
+ }
+}
+
+TEST_F(AudioSystemTest, VolumeIndexForAttributes) {
+ AudioVolumeGroupVector groups;
+ EXPECT_EQ(OK, AudioSystem::listAudioVolumeGroups(groups));
+ for (const auto& group : groups) {
+ if (group.getAudioAttributes().empty()) continue;
+ const audio_attributes_t attr = group.getAudioAttributes()[0];
+ if (attr == AUDIO_ATTRIBUTES_INITIALIZER) continue;
+ audio_stream_type_t streamType = AudioSystem::attributesToStreamType(attr);
+ if (streamType >= AUDIO_STREAM_PUBLIC_CNT) continue;
+
+ volume_group_t vg;
+ EXPECT_EQ(OK, AudioSystem::getVolumeGroupFromAudioAttributes(attr, vg));
+ EXPECT_EQ(group.getId(), vg);
+
+ int index;
+ EXPECT_EQ(OK,
+ AudioSystem::getVolumeIndexForAttributes(attr, index, AUDIO_DEVICE_OUT_SPEAKER));
+
+ int indexTest;
+ EXPECT_EQ(OK, AudioSystem::getStreamVolumeIndex(streamType, &indexTest,
+ AUDIO_DEVICE_OUT_SPEAKER));
+ EXPECT_EQ(index, indexTest);
+ }
+}
+
+TEST_F(AudioSystemTest, DevicesRoleForCapturePreset) {
+ std::vector<struct audio_port_v7> ports;
+ status_t status = listAudioPorts(ports);
+ ASSERT_EQ(OK, status);
+
+ if (ports.empty()) {
+ GTEST_SKIP() << "No ports returned by the audio system";
+ }
+
+ audio_devices_t inDeviceA = AUDIO_DEVICE_IN_BUILTIN_MIC;
+ audio_devices_t inDeviceB = AUDIO_DEVICE_IN_BUILTIN_MIC;
+ for (const auto& port : ports) {
+ if (port.role != AUDIO_PORT_ROLE_SOURCE || port.type != AUDIO_PORT_TYPE_DEVICE) continue;
+ if (port.ext.device.type == inDeviceA) continue;
+ inDeviceB = port.ext.device.type;
+ break;
+ }
+ const audio_source_t audioSource = AUDIO_SOURCE_MIC;
+ const device_role_t role = DEVICE_ROLE_PREFERRED;
+ const AudioDeviceTypeAddr inputDevice(inDeviceA, "");
+ const AudioDeviceTypeAddrVector inputDevices = {inputDevice};
+ const AudioDeviceTypeAddr outputDevice(AUDIO_DEVICE_OUT_SPEAKER, "");
+ const AudioDeviceTypeAddrVector outputDevices = {outputDevice};
+
+ // Test invalid device when setting
+ EXPECT_EQ(BAD_VALUE,
+ AudioSystem::setDevicesRoleForCapturePreset(audioSource, role, outputDevices));
+ EXPECT_EQ(BAD_VALUE,
+ AudioSystem::addDevicesRoleForCapturePreset(audioSource, role, outputDevices));
+ EXPECT_EQ(BAD_VALUE,
+ AudioSystem::removeDevicesRoleForCapturePreset(audioSource, role, outputDevices));
+
+ // Test invalid role
+ AudioDeviceTypeAddrVector devices;
+ EXPECT_EQ(BAD_VALUE, AudioSystem::getDevicesForRoleAndCapturePreset(audioSource,
+ DEVICE_ROLE_NONE, devices));
+ EXPECT_EQ(BAD_VALUE, AudioSystem::setDevicesRoleForCapturePreset(audioSource, DEVICE_ROLE_NONE,
+ inputDevices));
+ EXPECT_EQ(BAD_VALUE, AudioSystem::addDevicesRoleForCapturePreset(audioSource, DEVICE_ROLE_NONE,
+ inputDevices));
+ EXPECT_EQ(BAD_VALUE, AudioSystem::removeDevicesRoleForCapturePreset(
+ audioSource, DEVICE_ROLE_NONE, inputDevices));
+ EXPECT_EQ(BAD_VALUE,
+ AudioSystem::clearDevicesRoleForCapturePreset(audioSource, DEVICE_ROLE_NONE));
+
+ // Without setting, call get/remove/clear must fail
+ EXPECT_EQ(NAME_NOT_FOUND,
+ AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+ EXPECT_TRUE(devices.empty());
+ EXPECT_EQ(NAME_NOT_FOUND,
+ AudioSystem::removeDevicesRoleForCapturePreset(audioSource, role, devices));
+ EXPECT_EQ(NAME_NOT_FOUND, AudioSystem::clearDevicesRoleForCapturePreset(audioSource, role));
+
+ // Test set/get devices role
+ EXPECT_EQ(NO_ERROR,
+ AudioSystem::setDevicesRoleForCapturePreset(audioSource, role, inputDevices));
+ ASSERT_EQ(NO_ERROR, AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+ EXPECT_EQ(devices, inputDevices);
+
+ // Test setting will change the previously set devices
+ const AudioDeviceTypeAddr inputDevice2 = AudioDeviceTypeAddr(inDeviceB, "");
+ AudioDeviceTypeAddrVector inputDevices2 = {inputDevice2};
+ EXPECT_EQ(NO_ERROR,
+ AudioSystem::setDevicesRoleForCapturePreset(audioSource, role, inputDevices2));
+ devices.clear();
+ EXPECT_EQ(NO_ERROR, AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+ EXPECT_EQ(devices, inputDevices2);
+
+ // Test add devices
+ EXPECT_EQ(NO_ERROR,
+ AudioSystem::addDevicesRoleForCapturePreset(audioSource, role, inputDevices));
+ devices.clear();
+ EXPECT_EQ(NO_ERROR, AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+ EXPECT_EQ(2, devices.size());
+ EXPECT_TRUE(std::find(devices.begin(), devices.end(), inputDevice) != devices.end());
+ EXPECT_TRUE(std::find(devices.begin(), devices.end(), inputDevice2) != devices.end());
+
+ // Test remove devices
+ EXPECT_EQ(NO_ERROR,
+ AudioSystem::removeDevicesRoleForCapturePreset(audioSource, role, inputDevices));
+ devices.clear();
+ EXPECT_EQ(NO_ERROR, AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+ EXPECT_EQ(devices, inputDevices2);
+
+ // Test remove devices that are not set as the device role
+ EXPECT_EQ(BAD_VALUE,
+ AudioSystem::removeDevicesRoleForCapturePreset(audioSource, role, inputDevices));
+
+ // Test clear devices
+ EXPECT_EQ(NO_ERROR, AudioSystem::clearDevicesRoleForCapturePreset(audioSource, role));
+ devices.clear();
+ EXPECT_EQ(NAME_NOT_FOUND,
+ AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+
+ AudioDeviceTypeAddrVector inputDevices3 = {inputDevice, inputDevice2};
+ EXPECT_EQ(NO_ERROR,
+ AudioSystem::setDevicesRoleForCapturePreset(audioSource, role, inputDevices3));
+ devices.clear();
+ EXPECT_EQ(NO_ERROR, AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+ EXPECT_EQ(2, devices.size());
+ EXPECT_TRUE(std::find(devices.begin(), devices.end(), inputDevice) != devices.end());
+ EXPECT_TRUE(std::find(devices.begin(), devices.end(), inputDevice2) != devices.end());
+ EXPECT_EQ(NO_ERROR, AudioSystem::clearDevicesRoleForCapturePreset(audioSource, role));
+}
+
+TEST_F(AudioSystemTest, UidDeviceAffinities) {
+ uid_t uid = getuid();
+
+ // Test invalid device for example audio_is_input_device
+ AudioDeviceTypeAddr inputDevice(AUDIO_DEVICE_IN_BUILTIN_MIC, "");
+ AudioDeviceTypeAddrVector inputDevices = {inputDevice};
+ EXPECT_EQ(BAD_VALUE, AudioSystem::setUidDeviceAffinities(uid, inputDevices));
+
+ // Test valid device for example audio_is_output_device
+ AudioDeviceTypeAddr outputDevice(AUDIO_DEVICE_OUT_SPEAKER, "");
+ AudioDeviceTypeAddrVector outputDevices = {outputDevice};
+ EXPECT_EQ(NO_ERROR, AudioSystem::setUidDeviceAffinities(uid, outputDevices));
+ EXPECT_EQ(NO_ERROR, AudioSystem::removeUidDeviceAffinities(uid));
+}
+
+TEST_F(AudioSystemTest, UserIdDeviceAffinities) {
+ int userId = 200;
+
+ // Test invalid device for example audio_is_input_device
+ AudioDeviceTypeAddr inputDevice(AUDIO_DEVICE_IN_BUILTIN_MIC, "");
+ AudioDeviceTypeAddrVector inputDevices = {inputDevice};
+ EXPECT_EQ(BAD_VALUE, AudioSystem::setUserIdDeviceAffinities(userId, inputDevices));
+
+ // Test valid device for ezample audio_is_output_device
+ AudioDeviceTypeAddr outputDevice(AUDIO_DEVICE_OUT_SPEAKER, "");
+ AudioDeviceTypeAddrVector outputDevices = {outputDevice};
+ EXPECT_EQ(NO_ERROR, AudioSystem::setUserIdDeviceAffinities(userId, outputDevices));
+ EXPECT_EQ(NO_ERROR, AudioSystem::removeUserIdDeviceAffinities(userId));
+}
diff --git a/media/libaudioclient/tests/audiotrack_tests.cpp b/media/libaudioclient/tests/audiotrack_tests.cpp
new file mode 100644
index 0000000..8daba0a
--- /dev/null
+++ b/media/libaudioclient/tests/audiotrack_tests.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 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
+
+#include <gtest/gtest.h>
+
+#include "audio_test_utils.h"
+
+using namespace android;
+
+TEST(AudioTrackTest, TestPlayTrack) {
+ const auto ap = sp<AudioPlayback>::make(44100 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_OUT_STEREO, AUDIO_OUTPUT_FLAG_NONE,
+ AUDIO_SESSION_NONE, AudioTrack::TRANSFER_OBTAIN);
+ ASSERT_NE(nullptr, ap);
+ ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+ << "Unable to open Resource";
+ EXPECT_EQ(OK, ap->create()) << "track creation failed";
+ EXPECT_EQ(OK, ap->start()) << "audio track start failed";
+ EXPECT_EQ(OK, ap->onProcess());
+ ap->stop();
+}
+
+TEST(AudioTrackTest, TestSeek) {
+ const auto ap = sp<AudioPlayback>::make(
+ 44100 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO);
+ ASSERT_NE(nullptr, ap);
+ ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+ << "Unable to open Resource";
+ EXPECT_EQ(OK, ap->create()) << "track creation failed";
+ EXPECT_EQ(OK, ap->start()) << "audio track start failed";
+ EXPECT_EQ(OK, ap->onProcess(true));
+ ap->stop();
+}
+
+TEST(AudioTrackTest, OffloadOrDirectPlayback) {
+ audio_offload_info_t info = AUDIO_INFO_INITIALIZER;
+ info.sample_rate = 44100;
+ info.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ info.format = AUDIO_FORMAT_MP3;
+ info.stream_type = AUDIO_STREAM_MUSIC;
+ info.bit_rate = 192;
+ info.duration_us = 120 * 1000000; // 120 sec
+
+ audio_config_base_t config = {/* .sample_rate = */ info.sample_rate,
+ /* .channel_mask = */ info.channel_mask,
+ /* .format = */ AUDIO_FORMAT_PCM_16_BIT};
+ audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+ attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+ attributes.usage = AUDIO_USAGE_MEDIA;
+ attributes.flags = AUDIO_FLAG_NONE;
+
+ if (!AudioTrack::isDirectOutputSupported(config, attributes) &&
+ AUDIO_OFFLOAD_NOT_SUPPORTED == AudioSystem::getOffloadSupport(info)) {
+ GTEST_SKIP() << "offload or direct playback is not supported";
+ }
+ sp<AudioPlayback> ap = nullptr;
+ if (AUDIO_OFFLOAD_NOT_SUPPORTED != AudioSystem::getOffloadSupport(info)) {
+ ap = sp<AudioPlayback>::make(info.sample_rate, info.format, info.channel_mask,
+ AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD, AUDIO_SESSION_NONE,
+ AudioTrack::TRANSFER_OBTAIN, nullptr, &info);
+ } else {
+ ap = sp<AudioPlayback>::make(config.sample_rate, config.format, config.channel_mask,
+ AUDIO_OUTPUT_FLAG_DIRECT, AUDIO_SESSION_NONE,
+ AudioTrack::TRANSFER_OBTAIN);
+ }
+ ASSERT_NE(nullptr, ap);
+ EXPECT_EQ(OK, ap->create()) << "track creation failed";
+ audio_dual_mono_mode_t mode;
+ if (OK != ap->getAudioTrackHandle()->getDualMonoMode(&mode)) {
+ std::cerr << "no dual mono presentation is available" << std::endl;
+ }
+ if (OK != ap->getAudioTrackHandle()->setDualMonoMode(AUDIO_DUAL_MONO_MODE_LR)) {
+ std::cerr << "no dual mono presentation is available" << std::endl;
+ } else {
+ EXPECT_EQ(OK, ap->getAudioTrackHandle()->getDualMonoMode(&mode));
+ EXPECT_EQ(AUDIO_DUAL_MONO_MODE_LR, mode);
+ }
+ float leveldB;
+ if (OK != ap->getAudioTrackHandle()->getAudioDescriptionMixLevel(&leveldB)) {
+ std::cerr << "Audio Description mixing is unavailable" << std::endl;
+ }
+ if (OK != ap->getAudioTrackHandle()->setAudioDescriptionMixLevel(3.14f)) {
+ std::cerr << "Audio Description mixing is unavailable" << std::endl;
+ } else {
+ EXPECT_EQ(OK, ap->getAudioTrackHandle()->getAudioDescriptionMixLevel(&leveldB));
+ EXPECT_EQ(3.14f, leveldB);
+ }
+ AudioPlaybackRate audioRate;
+ audioRate = ap->getAudioTrackHandle()->getPlaybackRate();
+ std::cerr << "playback speed :: " << audioRate.mSpeed << std::endl
+ << "playback pitch :: " << audioRate.mPitch << std::endl;
+ audioRate.mSpeed = 2.0f;
+ audioRate.mPitch = 2.0f;
+ audioRate.mStretchMode = AUDIO_TIMESTRETCH_STRETCH_VOICE;
+ audioRate.mFallbackMode = AUDIO_TIMESTRETCH_FALLBACK_MUTE;
+ EXPECT_TRUE(isAudioPlaybackRateValid(audioRate));
+ if (OK != ap->getAudioTrackHandle()->setPlaybackRate(audioRate)) {
+ std::cerr << "unable to set playback rate parameters" << std::endl;
+ } else {
+ AudioPlaybackRate audioRateLocal;
+ audioRateLocal = ap->getAudioTrackHandle()->getPlaybackRate();
+ EXPECT_TRUE(isAudioPlaybackRateEqual(audioRate, audioRateLocal));
+ }
+ ap->stop();
+}
+
+TEST(AudioTrackTest, TestAudioCbNotifier) {
+ const auto ap = sp<AudioPlayback>::make(0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_OUT_STEREO, AUDIO_OUTPUT_FLAG_FAST,
+ AUDIO_SESSION_NONE, AudioTrack::TRANSFER_SHARED);
+ ASSERT_NE(nullptr, ap);
+ ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+ << "Unable to open Resource";
+ EXPECT_EQ(OK, ap->create()) << "track creation failed";
+ EXPECT_EQ(BAD_VALUE, ap->getAudioTrackHandle()->addAudioDeviceCallback(nullptr));
+ sp<OnAudioDeviceUpdateNotifier> cb = sp<OnAudioDeviceUpdateNotifier>::make();
+ sp<OnAudioDeviceUpdateNotifier> cbOld = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, ap->getAudioTrackHandle()->addAudioDeviceCallback(cbOld));
+ EXPECT_EQ(INVALID_OPERATION, ap->getAudioTrackHandle()->addAudioDeviceCallback(cbOld));
+ EXPECT_EQ(OK, ap->getAudioTrackHandle()->addAudioDeviceCallback(cb));
+ EXPECT_EQ(OK, ap->start()) << "audio track start failed";
+ EXPECT_EQ(OK, ap->onProcess());
+ EXPECT_EQ(OK, cb->waitForAudioDeviceCb());
+ EXPECT_EQ(AUDIO_IO_HANDLE_NONE, cbOld->mAudioIo);
+ EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, cbOld->mDeviceId);
+ EXPECT_NE(AUDIO_IO_HANDLE_NONE, cb->mAudioIo);
+ EXPECT_NE(AUDIO_PORT_HANDLE_NONE, cb->mDeviceId);
+ EXPECT_EQ(cb->mAudioIo, ap->getAudioTrackHandle()->getOutput());
+ EXPECT_EQ(cb->mDeviceId, ap->getAudioTrackHandle()->getRoutedDeviceId());
+ String8 keys;
+ keys = ap->getAudioTrackHandle()->getParameters(keys);
+ if (!keys.isEmpty()) {
+ std::cerr << "track parameters :: " << keys << std::endl;
+ }
+ EXPECT_TRUE(checkPatchPlayback(cb->mAudioIo, cb->mDeviceId));
+ EXPECT_EQ(BAD_VALUE, ap->getAudioTrackHandle()->removeAudioDeviceCallback(nullptr));
+ EXPECT_EQ(INVALID_OPERATION, ap->getAudioTrackHandle()->removeAudioDeviceCallback(cbOld));
+ EXPECT_EQ(OK, ap->getAudioTrackHandle()->removeAudioDeviceCallback(cb));
+ ap->stop();
+}
+
+class AudioTrackCreateTest
+ : public ::testing::TestWithParam<std::tuple<uint32_t, audio_format_t, audio_channel_mask_t,
+ audio_output_flags_t, audio_session_t>> {
+ public:
+ AudioTrackCreateTest()
+ : mSampleRate(std::get<0>(GetParam())),
+ mFormat(std::get<1>(GetParam())),
+ mChannelMask(std::get<2>(GetParam())),
+ mFlags(std::get<3>(GetParam())),
+ mSessionId(std::get<4>(GetParam())){};
+
+ const uint32_t mSampleRate;
+ const audio_format_t mFormat;
+ const audio_channel_mask_t mChannelMask;
+ const audio_output_flags_t mFlags;
+ const audio_session_t mSessionId;
+
+ sp<AudioPlayback> mAP;
+
+ virtual void SetUp() override {
+ mAP = sp<AudioPlayback>::make(mSampleRate, mFormat, mChannelMask, mFlags,
+ mSessionId);
+ ASSERT_NE(nullptr, mAP);
+ ASSERT_EQ(OK, mAP->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+ << "Unable to open Resource";
+ ASSERT_EQ(OK, mAP->create()) << "track creation failed";
+ }
+
+ virtual void TearDown() override {
+ if (mAP) mAP->stop();
+ }
+};
+
+TEST_P(AudioTrackCreateTest, TestCreateTrack) {
+ EXPECT_EQ(mFormat, mAP->getAudioTrackHandle()->format());
+ EXPECT_EQ(audio_channel_count_from_out_mask(mChannelMask),
+ mAP->getAudioTrackHandle()->channelCount());
+ if (mSampleRate != 0) EXPECT_EQ(mSampleRate, mAP->getAudioTrackHandle()->getSampleRate());
+ if (mSessionId != AUDIO_SESSION_NONE)
+ EXPECT_EQ(mSessionId, mAP->getAudioTrackHandle()->getSessionId());
+ EXPECT_EQ(mSampleRate, mAP->getAudioTrackHandle()->getOriginalSampleRate());
+ EXPECT_EQ(OK, mAP->start()) << "audio track start failed";
+ EXPECT_EQ(OK, mAP->onProcess());
+}
+
+// sampleRate, format, channelMask, flags, sessionId
+INSTANTIATE_TEST_SUITE_P(
+ AudioTrackParameterizedTest, AudioTrackCreateTest,
+ ::testing::Combine(::testing::Values(48000), ::testing::Values(AUDIO_FORMAT_PCM_16_BIT),
+ ::testing::Values(AUDIO_CHANNEL_OUT_STEREO),
+ ::testing::Values(AUDIO_OUTPUT_FLAG_NONE,
+ AUDIO_OUTPUT_FLAG_PRIMARY | AUDIO_OUTPUT_FLAG_FAST,
+ AUDIO_OUTPUT_FLAG_RAW | AUDIO_OUTPUT_FLAG_FAST,
+ AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
+ ::testing::Values(AUDIO_SESSION_NONE)));
diff --git a/media/libaudioclient/tests/bbb_1ch_8kHz_s16le.raw b/media/libaudioclient/tests/bbb_1ch_8kHz_s16le.raw
new file mode 100644
index 0000000..2d1e4bf
--- /dev/null
+++ b/media/libaudioclient/tests/bbb_1ch_8kHz_s16le.raw
Binary files differ
diff --git a/media/libaudioclient/tests/bbb_2ch_24kHz_s16le.raw b/media/libaudioclient/tests/bbb_2ch_24kHz_s16le.raw
new file mode 100644
index 0000000..c8ac5f7
--- /dev/null
+++ b/media/libaudioclient/tests/bbb_2ch_24kHz_s16le.raw
Binary files differ
diff --git a/media/libaudioclient/tests/test_create_audiorecord.cpp b/media/libaudioclient/tests/test_create_audiorecord.cpp
index 2e0883b..277110b 100644
--- a/media/libaudioclient/tests/test_create_audiorecord.cpp
+++ b/media/libaudioclient/tests/test_create_audiorecord.cpp
@@ -29,14 +29,13 @@
#define NUM_ARGUMENTS 8
#define VERSION_VALUE "1.0"
-#define PACKAGE_NAME "AudioRecord test"
+#define PACKAGE_NAME "AudioRecord test"
namespace android {
using android::content::AttributionSourceState;
-int testRecord(FILE *inputFile, int outputFileFd)
-{
+int testRecord(FILE* inputFile, int outputFileFd) {
char line[MAX_INPUT_FILE_LINE_LENGTH];
uint32_t testCount = 0;
Vector<String16> args;
@@ -47,11 +46,9 @@
attributionSource.token = sp<BBinder>::make();
if (inputFile == nullptr) {
- sp<AudioRecord> record = new AudioRecord(AUDIO_SOURCE_DEFAULT,
- 0 /* sampleRate */,
- AUDIO_FORMAT_DEFAULT,
- AUDIO_CHANNEL_IN_MONO,
- attributionSource);
+ sp<AudioRecord> record =
+ new AudioRecord(AUDIO_SOURCE_DEFAULT, 0 /* sampleRate */, AUDIO_FORMAT_DEFAULT,
+ AUDIO_CHANNEL_IN_MONO, attributionSource);
if (record == 0 || record->initCheck() != NO_ERROR) {
write(outputFileFd, "Error creating AudioRecord\n",
sizeof("Error creating AudioRecord\n"));
@@ -80,11 +77,10 @@
char statusStr[MAX_OUTPUT_FILE_LINE_LENGTH];
bool fast = false;
- if (sscanf(line, " %u %x %x %zu %d %x %u %u",
- &sampleRate, &format, &channelMask,
- &frameCount, ¬ificationFrames,
- &flags, &sessionId, &inputSource) != NUM_ARGUMENTS) {
- fprintf(stderr, "Malformed line for test #%u in input file\n", testCount+1);
+ if (sscanf(line, " %u %x %x %zu %d %x %u %u", &sampleRate, &format, &channelMask,
+ &frameCount, ¬ificationFrames, &flags, &sessionId,
+ &inputSource) != NUM_ARGUMENTS) {
+ fprintf(stderr, "Malformed line for test #%u in input file\n", testCount + 1);
ret = 1;
continue;
}
@@ -100,21 +96,10 @@
sp<AudioRecord> record = new AudioRecord(attributionSource);
const auto emptyCallback = sp<AudioRecord::IAudioRecordCallback>::make();
- record->set(AUDIO_SOURCE_DEFAULT,
- sampleRate,
- format,
- channelMask,
- frameCount,
- fast ? emptyCallback : nullptr,
- notificationFrames,
- false,
- sessionId,
- fast ? AudioRecord::TRANSFER_CALLBACK : AudioRecord::TRANSFER_DEFAULT,
- flags,
- getuid(),
- getpid(),
- &attributes,
- AUDIO_PORT_HANDLE_NONE);
+ record->set(AUDIO_SOURCE_DEFAULT, sampleRate, format, channelMask, frameCount,
+ fast ? emptyCallback : nullptr, notificationFrames, false, sessionId,
+ fast ? AudioRecord::TRANSFER_CALLBACK : AudioRecord::TRANSFER_DEFAULT, flags,
+ getuid(), getpid(), &attributes, AUDIO_PORT_HANDLE_NONE);
status = record->initCheck();
sprintf(statusStr, "\n#### Test %u status %d\n", testCount, status);
write(outputFileFd, statusStr, strlen(statusStr));
@@ -126,11 +111,8 @@
return ret;
}
-}; // namespace android
+}; // namespace android
-
-int main(int argc, char **argv)
-{
+int main(int argc, char** argv) {
return android::main(argc, argv, android::testRecord);
}
-
diff --git a/media/libaudioclient/tests/test_create_audiotrack.cpp b/media/libaudioclient/tests/test_create_audiotrack.cpp
index e7231d3..4e09e21 100644
--- a/media/libaudioclient/tests/test_create_audiotrack.cpp
+++ b/media/libaudioclient/tests/test_create_audiotrack.cpp
@@ -32,18 +32,15 @@
namespace android {
-int testTrack(FILE *inputFile, int outputFileFd)
-{
+int testTrack(FILE* inputFile, int outputFileFd) {
char line[MAX_INPUT_FILE_LINE_LENGTH];
uint32_t testCount = 0;
Vector<String16> args;
int ret = 0;
if (inputFile == nullptr) {
- sp<AudioTrack> track = new AudioTrack(AUDIO_STREAM_DEFAULT,
- 0 /* sampleRate */,
- AUDIO_FORMAT_DEFAULT,
- AUDIO_CHANNEL_OUT_STEREO);
+ sp<AudioTrack> track = new AudioTrack(AUDIO_STREAM_DEFAULT, 0 /* sampleRate */,
+ AUDIO_FORMAT_DEFAULT, AUDIO_CHANNEL_OUT_STEREO);
if (track == 0 || track->initCheck() != NO_ERROR) {
write(outputFileFd, "Error creating AudioTrack\n",
sizeof("Error creating AudioTrack\n"));
@@ -78,11 +75,10 @@
bool offload = false;
bool fast = false;
- if (sscanf(line, " %u %x %x %zu %d %u %x %u %u %u",
- &sampleRate, &format, &channelMask,
- &frameCount, ¬ificationFrames, &useSharedBuffer,
- &flags, &sessionId, &usage, &contentType) != NUM_ARGUMENTS) {
- fprintf(stderr, "Malformed line for test #%u in input file\n", testCount+1);
+ if (sscanf(line, " %u %x %x %zu %d %u %x %u %u %u", &sampleRate, &format, &channelMask,
+ &frameCount, ¬ificationFrames, &useSharedBuffer, &flags, &sessionId, &usage,
+ &contentType) != NUM_ARGUMENTS) {
+ fprintf(stderr, "Malformed line for test #%u in input file\n", testCount + 1);
ret = 1;
continue;
}
@@ -90,7 +86,7 @@
if (useSharedBuffer != 0) {
size_t heapSize = audio_channel_count_from_out_mask(channelMask) *
- audio_bytes_per_sample(format) * frameCount;
+ audio_bytes_per_sample(format) * frameCount;
heap = new MemoryDealer(heapSize, "AudioTrack Heap Base");
sharedBuffer = heap->allocate(heapSize);
frameCount = 0;
@@ -111,25 +107,13 @@
attributes.usage = usage;
sp<AudioTrack> track = new AudioTrack();
const auto emptyCallback = sp<AudioTrack::IAudioTrackCallback>::make();
- track->set(AUDIO_STREAM_DEFAULT,
- sampleRate,
- format,
- channelMask,
- frameCount,
- flags,
- (fast || offload) ? emptyCallback : nullptr,
- notificationFrames,
- sharedBuffer,
- false,
- sessionId,
- ((fast && sharedBuffer == 0) || offload) ?
- AudioTrack::TRANSFER_CALLBACK : AudioTrack::TRANSFER_DEFAULT,
- offload ? &offloadInfo : nullptr,
- AttributionSourceState(),
- &attributes,
- false,
- 1.0f,
- AUDIO_PORT_HANDLE_NONE);
+ track->set(AUDIO_STREAM_DEFAULT, sampleRate, format, channelMask, frameCount, flags,
+ (fast || offload) ? emptyCallback : nullptr, notificationFrames, sharedBuffer,
+ false, sessionId,
+ ((fast && sharedBuffer == 0) || offload) ? AudioTrack::TRANSFER_CALLBACK
+ : AudioTrack::TRANSFER_DEFAULT,
+ offload ? &offloadInfo : nullptr, AttributionSourceState(), &attributes, false,
+ 1.0f, AUDIO_PORT_HANDLE_NONE);
status = track->initCheck();
sprintf(statusStr, "\n#### Test %u status %d\n", testCount, status);
write(outputFileFd, statusStr, strlen(statusStr));
@@ -141,11 +125,8 @@
return ret;
}
-}; // namespace android
+}; // namespace android
-
-int main(int argc, char **argv)
-{
+int main(int argc, char** argv) {
return android::main(argc, argv, android::testTrack);
}
-
diff --git a/media/libaudioclient/tests/test_create_utils.cpp b/media/libaudioclient/tests/test_create_utils.cpp
index caf5227..c2c2e8b 100644
--- a/media/libaudioclient/tests/test_create_utils.cpp
+++ b/media/libaudioclient/tests/test_create_utils.cpp
@@ -23,10 +23,10 @@
namespace android {
-int readLine(FILE *inputFile, char *line, int size) {
+int readLine(FILE* inputFile, char* line, int size) {
int ret = 0;
while (true) {
- char *str = fgets(line, size, inputFile);
+ char* str = fgets(line, size, inputFile);
if (str == nullptr) {
ret = -1;
break;
@@ -42,8 +42,7 @@
return ret;
}
-bool checkVersion(FILE *inputFile, const char *version)
-{
+bool checkVersion(FILE* inputFile, const char* version) {
char line[MAX_INPUT_FILE_LINE_LENGTH];
char versionKey[MAX_INPUT_FILE_LINE_LENGTH];
char versionValue[MAX_INPUT_FILE_LINE_LENGTH];
@@ -68,9 +67,8 @@
return true;
}
-int main(int argc, char **argv, test_func_t testFunc)
-{
- FILE *inputFile = nullptr;
+int main(int argc, char** argv, test_func_t testFunc) {
+ FILE* inputFile = nullptr;
int outputFileFd = STDOUT_FILENO;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int ret = 0;
@@ -96,7 +94,7 @@
if (strcmp(*argv, "-o") == 0) {
argv++;
if (*argv) {
- outputFileFd = open(*argv, O_WRONLY|O_CREAT, mode);
+ outputFileFd = open(*argv, O_WRONLY | O_CREAT, mode);
if (outputFileFd < 0) {
ret = 1;
}
@@ -126,5 +124,4 @@
return ret;
}
-}; // namespace android
-
+}; // namespace android
diff --git a/media/libaudioclient/tests/test_create_utils.h b/media/libaudioclient/tests/test_create_utils.h
index 9a6f9fa..110baf7 100644
--- a/media/libaudioclient/tests/test_create_utils.h
+++ b/media/libaudioclient/tests/test_create_utils.h
@@ -27,13 +27,12 @@
namespace android {
-int readLine(FILE *inputFile, char *line, int size);
+int readLine(FILE* inputFile, char* line, int size);
-bool checkVersion(FILE *inputFile, const char *version);
+bool checkVersion(FILE* inputFile, const char* version);
+typedef int (*test_func_t)(FILE* inputFile, int outputFileFd);
-typedef int (*test_func_t)(FILE *inputFile, int outputFileFd);
+int main(int argc, char** argv, test_func_t testFunc);
-int main(int argc, char **argv, test_func_t testFunc);
-
-}; // namespace android
+}; // namespace android
diff --git a/media/libaudioclient/tests/trackplayerbase_tests.cpp b/media/libaudioclient/tests/trackplayerbase_tests.cpp
new file mode 100644
index 0000000..c9b704d
--- /dev/null
+++ b/media/libaudioclient/tests/trackplayerbase_tests.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 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_TAG "TrackPlayerBaseTest"
+
+#include <gtest/gtest.h>
+
+#include <media/TrackPlayerBase.h>
+
+using namespace android;
+using namespace android::media;
+
+class TrackPlayer : public TrackPlayerBase, public AudioTrack::IAudioTrackCallback {
+ public:
+ // methods protected in base class
+ using TrackPlayerBase::playerPause;
+ using TrackPlayerBase::playerSetVolume;
+ using TrackPlayerBase::playerStart;
+ using TrackPlayerBase::playerStop;
+};
+
+class TrackPlayerBaseTest
+ : public ::testing::TestWithParam<std::tuple<double, double, uint32_t, uint32_t>> {
+ public:
+ TrackPlayerBaseTest()
+ : mDuration(std::get<0>(GetParam())),
+ mPulseFreq(std::get<1>(GetParam())),
+ mChannelCount(std::get<2>(GetParam())),
+ mSampleRate(std::get<3>(GetParam())){};
+
+ virtual void SetUp() override {
+ mFrameCount = mDuration * mSampleRate;
+ audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(mChannelCount);
+ sp<AudioTrack> track = new AudioTrack(mStreamType, mSampleRate, mFormat, channelMask,
+ mFrameCount, mFlags, nullptr /* callback */,
+ 0 /* notificationFrames */, AUDIO_SESSION_NONE);
+ ASSERT_EQ(track->initCheck(), NO_ERROR);
+
+ mPlayer = new TrackPlayer();
+ mPlayer->init(track.get(), mPlayer, PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA,
+ AUDIO_SESSION_NONE);
+ sp<AudioTrack> playerTrack = mPlayer->mAudioTrack;
+ ASSERT_EQ(playerTrack->initCheck(), NO_ERROR);
+
+ mBufferSize = mFrameCount * playerTrack->frameSize();
+ mBuffer.resize(mBufferSize, 0);
+
+ // populate buffer
+ ASSERT_NE(mPulseFreq, 0);
+ int32_t nPulseSamples = mSampleRate / mPulseFreq;
+ int32_t pulseSize = nPulseSamples * playerTrack->frameSize();
+
+ int32_t marker = 0;
+ while (marker + pulseSize <= mBufferSize) {
+ memset(mBuffer.data() + marker, 127, pulseSize / 2);
+ marker += pulseSize;
+ }
+ }
+
+ void playBuffer() {
+ bool blocking = true;
+ ssize_t nbytes = mPlayer->mAudioTrack->write(mBuffer.data(), mBufferSize, blocking);
+ EXPECT_EQ(nbytes, mBufferSize) << "Did not write all data in blocking mode";
+ }
+
+ const double mDuration; // seconds
+ sp<TrackPlayer> mPlayer;
+
+ private:
+ const double mPulseFreq;
+ const uint32_t mChannelCount;
+ const uint32_t mSampleRate;
+
+ const audio_format_t mFormat = AUDIO_FORMAT_PCM_16_BIT;
+ const audio_output_flags_t mFlags = AUDIO_OUTPUT_FLAG_NONE;
+ const audio_stream_type_t mStreamType = AUDIO_STREAM_MUSIC;
+
+ int32_t mBufferSize;
+ int32_t mFrameCount;
+ std::vector<uint8_t> mBuffer;
+};
+
+class PlaybackTestParam : public TrackPlayerBaseTest {};
+
+TEST_P(PlaybackTestParam, PlaybackTest) {
+ // no-op implementation
+ EXPECT_TRUE(mPlayer->setStartDelayMs(0).isOk());
+
+ ASSERT_EQ(mPlayer->playerStart(), NO_ERROR);
+ ASSERT_NO_FATAL_FAILURE(playBuffer());
+ EXPECT_EQ(mPlayer->playerStop(), NO_ERROR);
+}
+
+INSTANTIATE_TEST_SUITE_P(TrackPlayerTest, PlaybackTestParam,
+ ::testing::Values(std::make_tuple(2.5, 25.0, 2, 48000)));
+
+class ChangeVolumeTestParam : public TrackPlayerBaseTest {};
+
+TEST_P(ChangeVolumeTestParam, ChangeVolumeTest) {
+ float volume = 1.0f;
+ (void)mPlayer->setPlayerVolume(volume / 2, volume);
+
+ ASSERT_TRUE(mPlayer->start().isOk());
+ ASSERT_EQ(mPlayer->playerSetVolume(), NO_ERROR);
+
+ ASSERT_NO_FATAL_FAILURE(playBuffer());
+
+ EXPECT_TRUE(mPlayer->stop().isOk());
+
+ std::vector<float> setVol = {0.95f, 0.05f, 0.5f, 0.25f, -1.0f, 1.0f, 1.0f};
+ std::vector<float> setPan = {0.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.5f, -0.5f};
+
+ ASSERT_TRUE(mPlayer->start().isOk());
+
+ for (int32_t i = 0; i < setVol.size(); i++) {
+ EXPECT_TRUE(mPlayer->setVolume(setVol[i]).isOk());
+ EXPECT_TRUE(mPlayer->setPan(setPan[i]).isOk());
+ ASSERT_NO_FATAL_FAILURE(playBuffer());
+ }
+ EXPECT_TRUE(mPlayer->stop().isOk());
+}
+
+INSTANTIATE_TEST_SUITE_P(TrackPlayerTest, ChangeVolumeTestParam,
+ ::testing::Values(std::make_tuple(1.0, 100.0, 1, 24000)));
+
+class PauseTestParam : public TrackPlayerBaseTest {};
+
+TEST_P(PauseTestParam, PauseTest) {
+ ASSERT_EQ(mPlayer->playerStart(), NO_ERROR);
+ ASSERT_NO_FATAL_FAILURE(playBuffer());
+
+ ASSERT_EQ(mPlayer->playerPause(), NO_ERROR);
+ ASSERT_EQ(mPlayer->playerStart(), NO_ERROR);
+
+ ASSERT_NO_FATAL_FAILURE(playBuffer());
+
+ EXPECT_EQ(mPlayer->playerStop(), NO_ERROR);
+
+ for (int32_t i = 0; i < 5; i++) {
+ ASSERT_TRUE(mPlayer->start().isOk());
+ ASSERT_NO_FATAL_FAILURE(playBuffer());
+ ASSERT_TRUE(mPlayer->pause().isOk());
+ }
+ EXPECT_TRUE(mPlayer->stop().isOk());
+}
+
+INSTANTIATE_TEST_SUITE_P(TrackPlayerTest, PauseTestParam,
+ ::testing::Values(std::make_tuple(1.0, 75.0, 2, 24000)));
diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp
index 159f898..c758fcd 100644
--- a/media/libaudiofoundation/Android.bp
+++ b/media/libaudiofoundation/Android.bp
@@ -18,21 +18,22 @@
export_include_dirs: ["include"],
header_libs: [
- "libaudioclient_aidl_conversion_util",
+ "libaudio_aidl_conversion_common_util_cpp",
"libaudio_system_headers",
"libmedia_helper_headers",
],
export_header_lib_headers: [
- "libaudioclient_aidl_conversion_util",
+ "libaudio_aidl_conversion_common_util_cpp",
"libaudio_system_headers",
"libmedia_helper_headers",
],
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_export_static",
+ ],
static_libs: [
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
],
export_static_lib_headers: [
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
],
host_supported: true,
@@ -57,8 +58,11 @@
"DeviceDescriptorBase.cpp",
],
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_export_shared",
+ ],
+
shared_libs: [
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
"libaudioclient_aidl_conversion",
"libaudioutils",
@@ -70,7 +74,6 @@
],
export_shared_lib_headers: [
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
"libaudioclient_aidl_conversion",
],
diff --git a/media/libaudiofoundation/AudioContainers.cpp b/media/libaudiofoundation/AudioContainers.cpp
index 0a8188f..202a400 100644
--- a/media/libaudiofoundation/AudioContainers.cpp
+++ b/media/libaudiofoundation/AudioContainers.cpp
@@ -77,6 +77,13 @@
return audioDeviceOutLeAudioUnicastSet;
}
+const DeviceTypeSet& getAudioDeviceOutLeAudioBroadcastSet() {
+ static const DeviceTypeSet audioDeviceOutLeAudioUnicastSet = DeviceTypeSet(
+ std::begin(AUDIO_DEVICE_OUT_BLE_BROADCAST_ARRAY),
+ std::end(AUDIO_DEVICE_OUT_BLE_BROADCAST_ARRAY));
+ return audioDeviceOutLeAudioUnicastSet;
+}
+
std::string deviceTypesToString(const DeviceTypeSet &deviceTypes) {
if (deviceTypes.empty()) {
return "Empty device types";
diff --git a/media/libaudiofoundation/AudioPort.cpp b/media/libaudiofoundation/AudioPort.cpp
index 4513323..6e05abc 100644
--- a/media/libaudiofoundation/AudioPort.cpp
+++ b/media/libaudiofoundation/AudioPort.cpp
@@ -222,7 +222,7 @@
mExtraAudioDescriptors == other->getExtraAudioDescriptors();
}
-status_t AudioPort::writeToParcelable(media::AudioPort* parcelable) const {
+status_t AudioPort::writeToParcelable(media::AudioPortFw* parcelable) const {
parcelable->hal.name = mName;
parcelable->sys.type = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_port_type_t_AudioPortType(mType));
@@ -249,7 +249,7 @@
return OK;
}
-status_t AudioPort::readFromParcelable(const media::AudioPort& parcelable) {
+status_t AudioPort::readFromParcelable(const media::AudioPortFw& parcelable) {
mName = parcelable.hal.name;
mType = VALUE_OR_RETURN_STATUS(
aidl2legacy_AudioPortType_audio_port_type_t(parcelable.sys.type));
diff --git a/media/libaudiofoundation/DeviceDescriptorBase.cpp b/media/libaudiofoundation/DeviceDescriptorBase.cpp
index 5ffbffc..9ffc75b 100644
--- a/media/libaudiofoundation/DeviceDescriptorBase.cpp
+++ b/media/libaudiofoundation/DeviceDescriptorBase.cpp
@@ -174,7 +174,7 @@
return false;
}
-status_t DeviceDescriptorBase::writeToParcelable(media::AudioPort* parcelable) const {
+status_t DeviceDescriptorBase::writeToParcelable(media::AudioPortFw* parcelable) const {
AudioPort::writeToParcelable(parcelable);
AudioPortConfig::writeToParcelable(&parcelable->sys.activeConfig.hal, useInputChannelMask());
parcelable->hal.id = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(mId));
@@ -186,17 +186,17 @@
deviceExt.encodedFormats = VALUE_OR_RETURN_STATUS(
convertContainer<std::vector<media::audio::common::AudioFormatDescription>>(
mEncodedFormats, legacy2aidl_audio_format_t_AudioFormatDescription));
+ deviceExt.encapsulationModes = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_AudioEncapsulationMode_mask(mEncapsulationModes));
+ deviceExt.encapsulationMetadataTypes = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_AudioEncapsulationMetadataType_mask(mEncapsulationMetadataTypes));
UNION_SET(parcelable->hal.ext, device, deviceExt);
media::AudioPortDeviceExtSys deviceSys;
- deviceSys.encapsulationModes = VALUE_OR_RETURN_STATUS(
- legacy2aidl_AudioEncapsulationMode_mask(mEncapsulationModes));
- deviceSys.encapsulationMetadataTypes = VALUE_OR_RETURN_STATUS(
- legacy2aidl_AudioEncapsulationMetadataType_mask(mEncapsulationMetadataTypes));
UNION_SET(parcelable->sys.ext, device, deviceSys);
return OK;
}
-status_t DeviceDescriptorBase::readFromParcelable(const media::AudioPort& parcelable) {
+status_t DeviceDescriptorBase::readFromParcelable(const media::AudioPortFw& parcelable) {
if (parcelable.sys.type != media::AudioPortType::DEVICE) {
return BAD_VALUE;
}
@@ -214,12 +214,12 @@
mEncodedFormats = VALUE_OR_RETURN_STATUS(
convertContainer<FormatVector>(deviceExt.encodedFormats,
aidl2legacy_AudioFormatDescription_audio_format_t));
+ mEncapsulationModes = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioEncapsulationMode_mask(deviceExt.encapsulationModes));
+ mEncapsulationMetadataTypes = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioEncapsulationMetadataType_mask(deviceExt.encapsulationMetadataTypes));
media::AudioPortDeviceExtSys deviceSys = VALUE_OR_RETURN_STATUS(
UNION_GET(parcelable.sys.ext, device));
- mEncapsulationModes = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioEncapsulationMode_mask(deviceSys.encapsulationModes));
- mEncapsulationMetadataTypes = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioEncapsulationMetadataType_mask(deviceSys.encapsulationMetadataTypes));
return OK;
}
@@ -245,7 +245,7 @@
}
ConversionResult<sp<DeviceDescriptorBase>>
-aidl2legacy_DeviceDescriptorBase(const media::AudioPort& aidl) {
+aidl2legacy_DeviceDescriptorBase(const media::AudioPortFw& aidl) {
sp<DeviceDescriptorBase> result = new DeviceDescriptorBase(AUDIO_DEVICE_NONE);
status_t status = result->readFromParcelable(aidl);
if (status != OK) {
@@ -254,9 +254,9 @@
return result;
}
-ConversionResult<media::AudioPort>
+ConversionResult<media::AudioPortFw>
legacy2aidl_DeviceDescriptorBase(const sp<DeviceDescriptorBase>& legacy) {
- media::AudioPort aidl;
+ media::AudioPortFw aidl;
status_t status = legacy->writeToParcelable(&aidl);
if (status != OK) {
return base::unexpected(status);
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index b6e6c84..3f79ea2 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -42,6 +42,7 @@
const DeviceTypeSet& getAudioDeviceInAllUsbSet();
const DeviceTypeSet& getAudioDeviceOutAllBleSet();
const DeviceTypeSet& getAudioDeviceOutLeAudioUnicastSet();
+const DeviceTypeSet& getAudioDeviceOutLeAudioBroadcastSet();
template<typename T>
static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) {
@@ -66,6 +67,9 @@
for (const auto &channel : channelMasks) {
if (audio_channel_mask_out_to_in(channel) != AUDIO_CHANNEL_INVALID) {
inMaskSet.insert(audio_channel_mask_out_to_in(channel));
+ } else if (audio_channel_mask_get_representation(channel)
+ == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+ inMaskSet.insert(channel);
}
}
return inMaskSet;
@@ -76,6 +80,9 @@
for (const auto &channel : channelMasks) {
if (audio_channel_mask_in_to_out(channel) != AUDIO_CHANNEL_INVALID) {
outMaskSet.insert(audio_channel_mask_in_to_out(channel));
+ } else if (audio_channel_mask_get_representation(channel)
+ == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+ outMaskSet.insert(channel);
}
}
return outMaskSet;
diff --git a/media/libaudiofoundation/include/media/AudioPort.h b/media/libaudiofoundation/include/media/AudioPort.h
index d6a098f..77e58ed 100644
--- a/media/libaudiofoundation/include/media/AudioPort.h
+++ b/media/libaudiofoundation/include/media/AudioPort.h
@@ -19,8 +19,8 @@
#include <string>
#include <type_traits>
-#include <android/media/AudioPort.h>
-#include <android/media/AudioPortConfig.h>
+#include <android/media/AudioPortFw.h>
+#include <android/media/AudioPortConfigFw.h>
#include <android/media/audio/common/ExtraAudioDescriptor.h>
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
@@ -72,7 +72,7 @@
AudioProfileVector &getAudioProfiles() { return mProfiles; }
void setExtraAudioDescriptors(
- const std::vector<media::audio::common::ExtraAudioDescriptor> extraAudioDescriptors) {
+ const std::vector<media::audio::common::ExtraAudioDescriptor>& extraAudioDescriptors) {
mExtraAudioDescriptors = extraAudioDescriptors;
}
std::vector<media::audio::common::ExtraAudioDescriptor> &getExtraAudioDescriptors() {
@@ -118,8 +118,8 @@
bool equals(const sp<AudioPort>& other) const;
- status_t writeToParcelable(media::AudioPort* parcelable) const;
- status_t readFromParcelable(const media::AudioPort& parcelable);
+ status_t writeToParcelable(media::AudioPortFw* parcelable) const;
+ status_t readFromParcelable(const media::AudioPortFw& parcelable);
AudioGains mGains; // gain controllers
// Maximum number of input or output streams that can be simultaneously
diff --git a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
index 1f0c768..501831d 100644
--- a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
+++ b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
@@ -18,7 +18,7 @@
#include <vector>
-#include <android/media/AudioPort.h>
+#include <android/media/AudioPortFw.h>
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
#include <media/AudioContainers.h>
@@ -53,7 +53,7 @@
// AudioPortConfig
virtual sp<AudioPort> getAudioPort() const {
- return static_cast<AudioPort*>(const_cast<DeviceDescriptorBase*>(this));
+ return sp<AudioPort>::fromExisting(const_cast<DeviceDescriptorBase*>(this));
}
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
@@ -79,8 +79,8 @@
bool equals(const sp<DeviceDescriptorBase>& other) const;
- status_t writeToParcelable(media::AudioPort* parcelable) const;
- status_t readFromParcelable(const media::AudioPort& parcelable);
+ status_t writeToParcelable(media::AudioPortFw* parcelable) const;
+ status_t readFromParcelable(const media::AudioPortFw& parcelable);
protected:
AudioDeviceTypeAddr mDeviceTypeAddr;
@@ -116,8 +116,8 @@
// Conversion routines, according to AidlConversion.h conventions.
ConversionResult<sp<DeviceDescriptorBase>>
-aidl2legacy_DeviceDescriptorBase(const media::AudioPort& aidl);
-ConversionResult<media::AudioPort>
+aidl2legacy_DeviceDescriptorBase(const media::AudioPortFw& aidl);
+ConversionResult<media::AudioPortFw>
legacy2aidl_DeviceDescriptorBase(const sp<DeviceDescriptorBase>& legacy);
} // namespace android
diff --git a/media/libaudiofoundation/tests/Android.bp b/media/libaudiofoundation/tests/Android.bp
index 3f1fbea..2f4aee0 100644
--- a/media/libaudiofoundation/tests/Android.bp
+++ b/media/libaudiofoundation/tests/Android.bp
@@ -10,6 +10,9 @@
cc_test {
name: "audiofoundation_parcelable_test",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_static",
+ ],
shared_libs: [
"libbase",
"libbinder",
@@ -18,9 +21,9 @@
],
static_libs: [
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
"libaudioclient_aidl_conversion",
+ "libaudio_aidl_conversion_common_cpp",
"libaudiofoundation",
"libstagefright_foundation",
],
diff --git a/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp b/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
index 50d8dc8..e315858 100644
--- a/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
+++ b/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
@@ -117,7 +117,7 @@
audioPort->setGains(getAudioGainsForTest());
audioPort->setAudioProfiles(getAudioProfileVectorForTest());
- media::AudioPort parcelable;
+ media::AudioPortFw parcelable;
ASSERT_EQ(NO_ERROR, audioPort->writeToParcelable(&parcelable));
sp<AudioPort> audioPortFromParcel = new AudioPort(
"", AUDIO_PORT_TYPE_NONE, AUDIO_PORT_ROLE_NONE);
@@ -152,7 +152,7 @@
ASSERT_EQ(desc->setEncapsulationMetadataTypes(
AUDIO_ENCAPSULATION_METADATA_TYPE_ALL_POSITION_BITS), NO_ERROR);
- media::AudioPort parcelable;
+ media::AudioPortFw parcelable;
ASSERT_EQ(NO_ERROR, desc->writeToParcelable(&parcelable));
sp<DeviceDescriptorBase> descFromParcel = new DeviceDescriptorBase(AUDIO_DEVICE_NONE);
ASSERT_EQ(NO_ERROR, descFromParcel->readFromParcelable(parcelable));
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 5f63e8d..f47dd0b 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -13,7 +13,7 @@
srcs: [
"DevicesFactoryHalInterface.cpp",
"EffectsFactoryHalInterface.cpp",
- "FactoryHalHidl.cpp",
+ "FactoryHal.cpp",
],
cflags: [
@@ -28,10 +28,12 @@
"libaudiohal@6.0",
"libaudiohal@7.0",
"libaudiohal@7.1",
+ "libaudiohal@aidl",
],
shared_libs: [
"audioclient-types-aidl-cpp",
+ "libbinder_ndk",
"libdl",
"libhidlbase",
"liblog",
@@ -41,6 +43,7 @@
header_libs: [
"libaudiohal_headers",
"libbase_headers",
+ "liberror_headers",
"libmediautils_headers",
]
}
@@ -65,15 +68,11 @@
header_libs: [
"libaudiohal_headers"
- ]
+ ],
}
cc_library_headers {
name: "libaudiohal_headers",
export_include_dirs: ["include"],
-
- // This is needed because the stream interface includes media/MicrophoneInfo.h
- header_libs: ["av-headers"],
- export_header_lib_headers: ["av-headers"],
}
diff --git a/media/libaudiohal/DevicesFactoryHalInterface.cpp b/media/libaudiohal/DevicesFactoryHalInterface.cpp
index 5ad26fc..adce681 100644
--- a/media/libaudiohal/DevicesFactoryHalInterface.cpp
+++ b/media/libaudiohal/DevicesFactoryHalInterface.cpp
@@ -14,19 +14,14 @@
* limitations under the License.
*/
-#include <string>
-
#include <media/audiohal/DevicesFactoryHalInterface.h>
-#include <media/audiohal/FactoryHalHidl.h>
+#include <media/audiohal/FactoryHal.h>
namespace android {
// static
sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
- using namespace std::string_literals;
- return createPreferredImpl<DevicesFactoryHalInterface>(
- std::make_pair("android.hardware.audio"s, "IDevicesFactory"s),
- std::make_pair("android.hardware.audio.effect"s, "IEffectsFactory"s));
+ return createPreferredImpl<DevicesFactoryHalInterface>(true /* isCore */);
}
} // namespace android
diff --git a/media/libaudiohal/EffectsFactoryHalInterface.cpp b/media/libaudiohal/EffectsFactoryHalInterface.cpp
index 8a28f64..3a05f21 100644
--- a/media/libaudiohal/EffectsFactoryHalInterface.cpp
+++ b/media/libaudiohal/EffectsFactoryHalInterface.cpp
@@ -14,19 +14,14 @@
* limitations under the License.
*/
-#include <string>
-
#include <media/audiohal/EffectsFactoryHalInterface.h>
-#include <media/audiohal/FactoryHalHidl.h>
+#include <media/audiohal/FactoryHal.h>
namespace android {
// static
sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
- using namespace std::string_literals;
- return createPreferredImpl<EffectsFactoryHalInterface>(
- std::make_pair("android.hardware.audio.effect"s, "IEffectsFactory"s),
- std::make_pair("android.hardware.audio"s, "IDevicesFactory"s));
+ return createPreferredImpl<EffectsFactoryHalInterface>(false /* isCore */);
}
// static
diff --git a/media/libaudiohal/FactoryHal.cpp b/media/libaudiohal/FactoryHal.cpp
new file mode 100644
index 0000000..f88915d
--- /dev/null
+++ b/media/libaudiohal/FactoryHal.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2022 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 <map>
+#include <memory>
+#define LOG_TAG "FactoryHal"
+
+#include <algorithm>
+#include <array>
+#include <cstddef>
+#include <dlfcn.h>
+#include <utility>
+
+#include <android/binder_manager.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
+#include <hidl/Status.h>
+#include <utils/Log.h>
+
+#include "include/media/audiohal/AudioHalVersionInfo.h"
+#include "include/media/audiohal/FactoryHal.h"
+
+namespace android::detail {
+
+namespace {
+
+using ::android::detail::AudioHalVersionInfo;
+
+// The pair of the interface's package name and the interface name,
+// e.g. <"android.hardware.audio", "IDevicesFactory"> for HIDL, <"android.hardware.audio.core",
+// "IModule"> for AIDL.
+// Splitting is used for easier construction of versioned names (FQNs).
+using InterfaceName = std::pair<std::string, std::string>;
+
+/**
+ * Supported HAL versions, from most recent to least recent.
+ * This list need to keep sync with AudioHalVersionInfo.VERSIONS in
+ * media/java/android/media/AudioHalVersionInfo.java.
+ */
+static const std::array<AudioHalVersionInfo, 5> sAudioHALVersions = {
+ // TODO: remove this comment to get AIDL
+ // AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, 1, 0),
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 1),
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 0),
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0),
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 5, 0),
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 4, 0),
+};
+
+static const std::map<AudioHalVersionInfo::Type, InterfaceName> sDevicesHALInterfaces = {
+ {AudioHalVersionInfo::Type::AIDL, std::make_pair("android.hardware.audio.core", "IModule")},
+ {AudioHalVersionInfo::Type::HIDL,
+ std::make_pair("android.hardware.audio", "IDevicesFactory")},
+};
+
+static const std::map<AudioHalVersionInfo::Type, InterfaceName> sEffectsHALInterfaces = {
+ {AudioHalVersionInfo::Type::AIDL,
+ std::make_pair("android.hardware.audio.effect", "IFactory")},
+ {AudioHalVersionInfo::Type::HIDL,
+ std::make_pair("android.hardware.audio.effect", "IEffectsFactory")},
+};
+
+bool createHalService(const AudioHalVersionInfo& version, bool isDevice, void** rawInterface) {
+ const std::string libName = "libaudiohal@" + version.toVersionString() + ".so";
+ const std::string factoryFunctionName =
+ isDevice ? "createIDevicesFactory" : "createIEffectsFactory";
+ constexpr int dlMode = RTLD_LAZY;
+ void* handle = nullptr;
+ dlerror(); // clear
+ handle = dlopen(libName.c_str(), dlMode);
+ if (handle == nullptr) {
+ const char* error = dlerror();
+ ALOGE("Failed to dlopen %s: %s", libName.c_str(),
+ error != nullptr ? error : "unknown error");
+ return false;
+ }
+ void* (*factoryFunction)();
+ *(void **)(&factoryFunction) = dlsym(handle, factoryFunctionName.c_str());
+ if (!factoryFunction) {
+ const char* error = dlerror();
+ ALOGE("Factory function %s not found in library %s: %s",
+ factoryFunctionName.c_str(), libName.c_str(),
+ error != nullptr ? error : "unknown error");
+ dlclose(handle);
+ return false;
+ }
+ *rawInterface = (*factoryFunction)();
+ ALOGW_IF(!*rawInterface, "Factory function %s from %s returned nullptr",
+ factoryFunctionName.c_str(), libName.c_str());
+ return true;
+}
+
+bool hasAidlHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
+ const std::string name = interface.first + "." + interface.second + "/default";
+ const bool isDeclared = AServiceManager_isDeclared(name.c_str());
+ if (!isDeclared) {
+ ALOGW("%s %s: false", __func__, name.c_str());
+ return false;
+ }
+ ALOGI("%s %s: true, version %s", __func__, name.c_str(), version.toString().c_str());
+ return true;
+}
+
+bool hasHidlHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
+ using ::android::hidl::manager::V1_0::IServiceManager;
+ sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
+ if (!sm) {
+ ALOGW("Failed to obtain HIDL ServiceManager");
+ return false;
+ }
+ // Since audio HAL doesn't support multiple clients, avoid instantiating
+ // the interface right away. Instead, query the transport type for it.
+ using ::android::hardware::Return;
+ using Transport = IServiceManager::Transport;
+ const std::string fqName =
+ interface.first + "@" + version.toVersionString() + "::" + interface.second;
+ const std::string instance = "default";
+ Return<Transport> transport = sm->getTransport(fqName, instance);
+ if (!transport.isOk()) {
+ ALOGW("Failed to obtain transport type for %s/%s: %s",
+ fqName.c_str(), instance.c_str(), transport.description().c_str());
+ return false;
+ }
+ return transport != Transport::EMPTY;
+}
+
+bool hasHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
+ auto halType = version.getType();
+ if (halType == AudioHalVersionInfo::Type::AIDL) {
+ return hasAidlHalService(interface, version);
+ } else if (halType == AudioHalVersionInfo::Type::HIDL) {
+ return hasHidlHalService(interface, version);
+ } else {
+ ALOGE("HalType not supported %s", version.toString().c_str());
+ return false;
+ }
+}
+
+} // namespace
+
+void *createPreferredImpl(bool isDevice) {
+ auto findMostRecentVersion = [](const auto& iMap) {
+ return std::find_if(sAudioHALVersions.begin(), sAudioHALVersions.end(),
+ [iMap](const auto& v) {
+ auto iface = iMap.find(v.getType());
+ return hasHalService(iface->second, v);
+ });
+ };
+
+ auto interfaceMap = isDevice ? sDevicesHALInterfaces : sEffectsHALInterfaces;
+ auto siblingInterfaceMap = isDevice ? sEffectsHALInterfaces : sDevicesHALInterfaces;
+ auto ifaceVersionIt = findMostRecentVersion(interfaceMap);
+ auto siblingVersionIt = findMostRecentVersion(siblingInterfaceMap);
+ if (ifaceVersionIt != sAudioHALVersions.end() && siblingVersionIt != sAudioHALVersions.end() &&
+ // same HAL type (HIDL/AIDL) and same major version
+ ifaceVersionIt->getType() == siblingVersionIt->getType() &&
+ ifaceVersionIt->getMajorVersion() == siblingVersionIt->getMajorVersion()) {
+ void* rawInterface;
+ if (createHalService(std::max(*ifaceVersionIt, *siblingVersionIt), isDevice,
+ &rawInterface)) {
+ return rawInterface;
+ } else {
+ ALOGE("Failed to create HAL services with major %s, sibling %s!",
+ ifaceVersionIt->toString().c_str(), siblingVersionIt->toString().c_str());
+ }
+ } else {
+ ALOGE("Found no HAL version, main(%s) %s %s!", isDevice ? "Device" : "Effect",
+ (ifaceVersionIt == sAudioHALVersions.end()) ? "null"
+ : ifaceVersionIt->toString().c_str(),
+ (siblingVersionIt == sAudioHALVersions.end()) ? "null"
+ : siblingVersionIt->toString().c_str());
+ }
+ return nullptr;
+}
+
+} // namespace android::detail
diff --git a/media/libaudiohal/FactoryHalHidl.cpp b/media/libaudiohal/FactoryHalHidl.cpp
deleted file mode 100644
index 590fec5..0000000
--- a/media/libaudiohal/FactoryHalHidl.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "FactoryHalHidl"
-
-#include <algorithm>
-#include <array>
-#include <utility>
-
-#include <media/audiohal/FactoryHalHidl.h>
-
-#include <dlfcn.h>
-
-#include <android/hidl/manager/1.0/IServiceManager.h>
-#include <hidl/ServiceManagement.h>
-#include <hidl/Status.h>
-#include <utils/Log.h>
-
-namespace android::detail {
-
-namespace {
-/** Supported HAL versions, from most recent to least recent.
- */
-#define CONC_VERSION(maj, min) #maj "." #min
-#define DECLARE_VERSION(maj, min) std::make_pair(std::make_pair(maj, min), CONC_VERSION(maj, min))
-static constexpr std::array<std::pair<std::pair<int, int>, const char*>, 5> sAudioHALVersions = {
- DECLARE_VERSION(7, 1),
- DECLARE_VERSION(7, 0),
- DECLARE_VERSION(6, 0),
- DECLARE_VERSION(5, 0),
- DECLARE_VERSION(4, 0)
-};
-
-bool createHalService(const std::string& version, const std::string& interface,
- void** rawInterface) {
- const std::string libName = "libaudiohal@" + version + ".so";
- const std::string factoryFunctionName = "create" + interface;
- constexpr int dlMode = RTLD_LAZY;
- void* handle = nullptr;
- dlerror(); // clear
- handle = dlopen(libName.c_str(), dlMode);
- if (handle == nullptr) {
- const char* error = dlerror();
- ALOGE("Failed to dlopen %s: %s", libName.c_str(),
- error != nullptr ? error : "unknown error");
- return false;
- }
- void* (*factoryFunction)();
- *(void **)(&factoryFunction) = dlsym(handle, factoryFunctionName.c_str());
- if (!factoryFunction) {
- const char* error = dlerror();
- ALOGE("Factory function %s not found in library %s: %s",
- factoryFunctionName.c_str(), libName.c_str(),
- error != nullptr ? error : "unknown error");
- dlclose(handle);
- return false;
- }
- *rawInterface = (*factoryFunction)();
- ALOGW_IF(!*rawInterface, "Factory function %s from %s returned nullptr",
- factoryFunctionName.c_str(), libName.c_str());
- return true;
-}
-
-bool hasHalService(const std::string& package, const std::string& version,
- const std::string& interface) {
- using ::android::hidl::manager::V1_0::IServiceManager;
- sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
- if (!sm) {
- ALOGE("Failed to obtain HIDL ServiceManager");
- return false;
- }
- // Since audio HAL doesn't support multiple clients, avoid instantiating
- // the interface right away. Instead, query the transport type for it.
- using ::android::hardware::Return;
- using Transport = IServiceManager::Transport;
- const std::string fqName = package + "@" + version + "::" + interface;
- const std::string instance = "default";
- Return<Transport> transport = sm->getTransport(fqName, instance);
- if (!transport.isOk()) {
- ALOGE("Failed to obtain transport type for %s/%s: %s",
- fqName.c_str(), instance.c_str(), transport.description().c_str());
- return false;
- }
- return transport != Transport::EMPTY;
-}
-
-} // namespace
-
-void* createPreferredImpl(const InterfaceName& iface, const InterfaceName& siblingIface) {
- auto findMostRecentVersion = [](const InterfaceName& iface) {
- return std::find_if(detail::sAudioHALVersions.begin(), detail::sAudioHALVersions.end(),
- [&](const auto& v) { return hasHalService(iface.first, v.second, iface.second); });
- };
- auto ifaceVersionIt = findMostRecentVersion(iface);
- auto siblingVersionIt = findMostRecentVersion(siblingIface);
- if (ifaceVersionIt != detail::sAudioHALVersions.end() &&
- siblingVersionIt != detail::sAudioHALVersions.end() &&
- // same major version
- ifaceVersionIt->first.first == siblingVersionIt->first.first) {
- std::string libraryVersion =
- ifaceVersionIt->first >= siblingVersionIt->first ?
- ifaceVersionIt->second : siblingVersionIt->second;
- void* rawInterface;
- if (createHalService(libraryVersion, iface.second, &rawInterface)) {
- return rawInterface;
- }
- }
- return nullptr;
-}
-
-} // namespace android::detail
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index d30883a..d5f6598 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -12,13 +12,14 @@
srcs: [
"CoreConversionHelperHidl.cpp",
"DeviceHalHidl.cpp",
+ "DevicesFactoryHalEntry.cpp",
"DevicesFactoryHalHidl.cpp",
"StreamHalHidl.cpp",
],
}
filegroup {
- name: "audio_effect_hal_client_sources",
+ name: "audio_effect_hidl_hal_client_sources",
srcs: [
"EffectBufferHalHidl.cpp",
"EffectConversionHelperHidl.cpp",
@@ -28,6 +29,21 @@
}
cc_defaults {
+ name: "libaudiohal_hidl_default",
+ shared_libs: [
+ "android.hardware.audio.common-util",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory@1.0",
+ "libaudiohal_deathhandler",
+ "libhidlbase",
+ "libhidlmemory",
+ ],
+ header_libs: [
+ "android.hardware.audio.common.util@all-versions",
+ ]
+}
+
+cc_defaults {
name: "libaudiohal_default",
cflags: [
@@ -37,31 +53,28 @@
"-fvisibility=hidden",
],
shared_libs: [
- "android.hardware.audio.common-util",
- "android.hidl.allocator@1.0",
- "android.hidl.memory@1.0",
+ "audioclient-types-aidl-cpp",
"av-types-aidl-cpp",
+ "libaudioclient_aidl_conversion",
"libaudiofoundation",
- "libaudiohal_deathhandler",
"libaudioutils",
"libbase",
"libbinder",
"libcutils",
"libfmq",
"libhardware",
- "libhidlbase",
- "libhidlmemory",
"liblog",
"libmedia_helper",
"libmediautils",
"libutils",
- "audioclient-types-aidl-cpp",
],
header_libs: [
- "android.hardware.audio.common.util@all-versions",
"libaudioclient_headers",
"libaudiohal_headers"
],
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_export_shared",
+ ],
export_shared_lib_headers: [
"libfmq",
@@ -70,11 +83,14 @@
cc_library_shared {
name: "libaudiohal@4.0",
- defaults: ["libaudiohal_default"],
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_hidl_default"
+ ],
srcs: [
":audio_core_hal_client_sources",
- ":audio_effect_hal_client_sources",
- "EffectsFactoryHalHidlEntry.cpp",
+ ":audio_effect_hidl_hal_client_sources",
+ "EffectsFactoryHalEntry.cpp",
],
shared_libs: [
"android.hardware.audio.common@4.0",
@@ -93,11 +109,14 @@
cc_library_shared {
name: "libaudiohal@5.0",
- defaults: ["libaudiohal_default"],
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_hidl_default"
+ ],
srcs: [
":audio_core_hal_client_sources",
- ":audio_effect_hal_client_sources",
- "EffectsFactoryHalHidlEntry.cpp",
+ ":audio_effect_hidl_hal_client_sources",
+ "EffectsFactoryHalEntry.cpp",
],
shared_libs: [
"android.hardware.audio.common@5.0",
@@ -116,11 +135,14 @@
cc_library_shared {
name: "libaudiohal@6.0",
- defaults: ["libaudiohal_default"],
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_hidl_default"
+ ],
srcs: [
":audio_core_hal_client_sources",
- ":audio_effect_hal_client_sources",
- "EffectsFactoryHalHidlEntry.cpp",
+ ":audio_effect_hidl_hal_client_sources",
+ "EffectsFactoryHalEntry.cpp",
],
shared_libs: [
"android.hardware.audio.common@6.0",
@@ -139,9 +161,12 @@
cc_library_static {
name: "libaudiohal.effect@7.0",
- defaults: ["libaudiohal_default"],
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_hidl_default"
+ ],
srcs: [
- ":audio_effect_hal_client_sources",
+ ":audio_effect_hidl_hal_client_sources",
],
static_libs: [
"android.hardware.audio.common@7.0",
@@ -158,10 +183,13 @@
cc_library_shared {
name: "libaudiohal@7.0",
- defaults: ["libaudiohal_default"],
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_hidl_default"
+ ],
srcs: [
":audio_core_hal_client_sources",
- "EffectsFactoryHalHidlEntry.cpp",
+ "EffectsFactoryHalEntry.cpp",
],
static_libs: [
"android.hardware.audio.common@7.0",
@@ -182,10 +210,13 @@
cc_library_shared {
name: "libaudiohal@7.1",
- defaults: ["libaudiohal_default"],
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_hidl_default"
+ ],
srcs: [
":audio_core_hal_client_sources",
- "EffectsFactoryHalHidlEntry.cpp",
+ "EffectsFactoryHalEntry.cpp",
],
static_libs: [
"android.hardware.audio.common@7.0",
@@ -207,3 +238,62 @@
"-include common/all-versions/VersionMacro.h",
]
}
+
+cc_library_shared {
+ name: "libaudiohal@aidl",
+ defaults: [
+ "libaudiohal_default",
+ "latest_android_hardware_audio_common_ndk_shared",
+ "latest_android_hardware_audio_core_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ srcs: [
+ "DeviceHalAidl.cpp",
+ "DevicesFactoryHalEntry.cpp",
+ "DevicesFactoryHalAidl.cpp",
+ "EffectConversionHelperAidl.cpp",
+ "EffectBufferHalAidl.cpp",
+ "EffectHalAidl.cpp",
+ "effectsAidlConversion/AidlConversionAec.cpp",
+ "effectsAidlConversion/AidlConversionAgc1.cpp",
+ "effectsAidlConversion/AidlConversionAgc2.cpp",
+ "effectsAidlConversion/AidlConversionBassBoost.cpp",
+ "effectsAidlConversion/AidlConversionDownmix.cpp",
+ "effectsAidlConversion/AidlConversionDynamicsProcessing.cpp",
+ "effectsAidlConversion/AidlConversionEnvReverb.cpp",
+ "effectsAidlConversion/AidlConversionEq.cpp",
+ "effectsAidlConversion/AidlConversionHapticGenerator.cpp",
+ "effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp",
+ "effectsAidlConversion/AidlConversionNoiseSuppression.cpp",
+ "effectsAidlConversion/AidlConversionPresetReverb.cpp",
+ "effectsAidlConversion/AidlConversionSpatializer.cpp",
+ "effectsAidlConversion/AidlConversionVendorExtension.cpp",
+ "effectsAidlConversion/AidlConversionVirtualizer.cpp",
+ "effectsAidlConversion/AidlConversionVisualizer.cpp",
+ "EffectsFactoryHalAidl.cpp",
+ "EffectsFactoryHalEntry.cpp",
+ "StreamHalAidl.cpp",
+ ],
+ static_libs: [
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libaudio_aidl_conversion_common_cpp",
+ "libaudio_aidl_conversion_common_ndk",
+ "libaudio_aidl_conversion_effect_ndk",
+ "libaudioaidlcommon",
+ ],
+ header_libs: [
+ "libaudio_system_headers",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ "-DBACKEND_CPP_NDK",
+ ],
+}
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.h b/media/libaudiohal/impl/ConversionHelperAidl.h
new file mode 100644
index 0000000..db6b6cf
--- /dev/null
+++ b/media/libaudiohal/impl/ConversionHelperAidl.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 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 <string>
+#include <string_view>
+#include <vector>
+
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+class Args {
+ public:
+ explicit Args(const Vector<String16>& args)
+ : mValues(args.size()), mPtrs(args.size()) {
+ for (size_t i = 0; i < args.size(); ++i) {
+ mValues[i] = std::string(String8(args[i]));
+ mPtrs[i] = mValues[i].c_str();
+ }
+ }
+ const char** args() { return mPtrs.data(); }
+ private:
+ std::vector<std::string> mValues;
+ std::vector<const char*> mPtrs;
+};
+
+class ConversionHelperAidl {
+ protected:
+ ConversionHelperAidl(std::string_view className) : mClassName(className) {}
+
+ const std::string& getClassName() const {
+ return mClassName;
+ }
+
+ const std::string mClassName;
+};
+
+} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
new file mode 100644
index 0000000..8b88f24
--- /dev/null
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -0,0 +1,1115 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DeviceHalAidl"
+// #define LOG_NDEBUG 0
+
+#include <algorithm>
+#include <forward_list>
+
+#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
+#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
+#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionUtil.h>
+#include <mediautils/TimeCheck.h>
+#include <Utils.h>
+#include <utils/Log.h>
+
+#include "DeviceHalAidl.h"
+#include "StreamHalAidl.h"
+
+using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::media::audio::common::AudioConfig;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioInputFlags;
+using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioLatencyMode;
+using aidl::android::media::audio::common::AudioMode;
+using aidl::android::media::audio::common::AudioOutputFlags;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::AudioPortDeviceExt;
+using aidl::android::media::audio::common::AudioPortMixExt;
+using aidl::android::media::audio::common::AudioPortMixExtUseCase;
+using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioSource;
+using aidl::android::media::audio::common::Int;
+using aidl::android::media::audio::common::Float;
+using aidl::android::hardware::audio::common::getFrameSizeInBytes;
+using aidl::android::hardware::audio::common::isBitPositionFlagSet;
+using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
+using aidl::android::media::audio::common::MicrophoneDynamicInfo;
+using aidl::android::media::audio::common::MicrophoneInfo;
+using aidl::android::hardware::audio::common::RecordTrackMetadata;
+using aidl::android::hardware::audio::core::AudioPatch;
+using aidl::android::hardware::audio::core::IModule;
+using aidl::android::hardware::audio::core::ITelephony;
+using aidl::android::hardware::audio::core::StreamDescriptor;
+
+namespace android {
+
+namespace {
+
+bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
+ return portConfig.sampleRate.value().value == config.base.sampleRate &&
+ portConfig.channelMask.value() == config.base.channelMask &&
+ portConfig.format.value() == config.base.format;
+}
+
+void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
+ config->base.sampleRate = portConfig.sampleRate.value().value;
+ config->base.channelMask = portConfig.channelMask.value();
+ config->base.format = portConfig.format.value();
+}
+
+void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
+ portConfig->sampleRate = Int{ .value = config.base.sampleRate };
+ portConfig->channelMask = config.base.channelMask;
+ portConfig->format = config.base.format;
+}
+
+} // namespace
+
+status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
+ // Obsolete.
+ return INVALID_OPERATION;
+}
+
+status_t DeviceHalAidl::initCheck() {
+ TIME_CHECK();
+ if (mModule == nullptr) return NO_INIT;
+ std::vector<AudioPort> ports;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
+ ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
+ __func__, mInstance.c_str());
+ std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
+ [](const auto& p) { return std::make_pair(p.id, p); });
+ mDefaultInputPortId = mDefaultOutputPortId = -1;
+ const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
+ for (const auto& pair : mPorts) {
+ const auto& p = pair.second;
+ if (p.ext.getTag() == AudioPortExt::Tag::device &&
+ (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
+ if (p.flags.getTag() == AudioIoFlags::Tag::input) {
+ mDefaultInputPortId = p.id;
+ } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
+ mDefaultOutputPortId = p.id;
+ }
+ }
+ }
+ ALOGI("%s: module %s default port ids: input %d, output %d",
+ __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
+ std::vector<AudioPortConfig> portConfigs;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
+ std::transform(portConfigs.begin(), portConfigs.end(),
+ std::inserter(mPortConfigs, mPortConfigs.end()),
+ [](const auto& p) { return std::make_pair(p.id, p); });
+ std::vector<AudioPatch> patches;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
+ std::transform(patches.begin(), patches.end(),
+ std::inserter(mPatches, mPatches.end()),
+ [](const auto& p) { return std::make_pair(p.id, p); });
+ return OK;
+}
+
+status_t DeviceHalAidl::setVoiceVolume(float volume) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ std::shared_ptr<ITelephony> telephony;
+ if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
+ status.isOk() && telephony != nullptr) {
+ ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
+ ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
+ "%s: the resulting voice volume %f is not the same as requested %f",
+ __func__, outConfig.voiceVolume.value().value, volume);
+ }
+ return INVALID_OPERATION;
+}
+
+status_t DeviceHalAidl::setMasterVolume(float volume) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ return statusTFromBinderStatus(mModule->setMasterVolume(volume));
+}
+
+status_t DeviceHalAidl::getMasterVolume(float *volume) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ return statusTFromBinderStatus(mModule->getMasterVolume(volume));
+}
+
+status_t DeviceHalAidl::setMode(audio_mode_t mode) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
+ std::shared_ptr<ITelephony> telephony;
+ if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
+ status.isOk() && telephony != nullptr) {
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
+ }
+ return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
+}
+
+status_t DeviceHalAidl::setMicMute(bool state) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ return statusTFromBinderStatus(mModule->setMicMute(state));
+}
+
+status_t DeviceHalAidl::getMicMute(bool *state) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ return statusTFromBinderStatus(mModule->getMicMute(state));
+}
+
+status_t DeviceHalAidl::setMasterMute(bool state) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ return statusTFromBinderStatus(mModule->setMasterMute(state));
+}
+
+status_t DeviceHalAidl::getMasterMute(bool *state) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ return statusTFromBinderStatus(mModule->getMasterMute(state));
+}
+
+status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
+ TIME_CHECK();
+ values->clear();
+ if (!mModule) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+namespace {
+
+class Cleanup {
+ public:
+ typedef void (DeviceHalAidl::*Cleaner)(int32_t);
+
+ Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
+ mDevice(device), mCleaner(cleaner), mId(id) {}
+ ~Cleanup() { clean(); }
+ void clean() {
+ if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
+ disarm();
+ }
+ void disarm() { mDevice = nullptr; }
+
+ private:
+ DeviceHalAidl* mDevice;
+ const Cleaner mCleaner;
+ const int32_t mId;
+};
+
+} // namespace
+
+// Since the order of container elements destruction is unspecified,
+// ensure that cleanups are performed from the most recent one and upwards.
+// This is the same as if there were individual Cleanup instances on the stack,
+// however the bonus is that we can disarm all of them with just one statement.
+class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
+ public:
+ ~Cleanups() { for (auto& c : *this) c.clean(); }
+ void disarmAll() { for (auto& c : *this) c.disarm(); }
+};
+
+status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (size == nullptr) return BAD_VALUE;
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
+ AudioDevice aidlDevice;
+ aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
+ AudioSource aidlSource = AudioSource::DEFAULT;
+ AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
+ AudioPortConfig mixPortConfig;
+ Cleanups cleanups;
+ audio_config writableConfig = *config;
+ int32_t nominalLatency;
+ RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
+ &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+ *size = aidlConfig.frameCount *
+ getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
+ // Do not disarm cleanups to release temporary port configs.
+ return OK;
+}
+
+status_t DeviceHalAidl::prepareToOpenStream(
+ int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
+ AudioSource aidlSource, struct audio_config* config,
+ Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
+ int32_t* nominalLatency) {
+ const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
+ // Find / create AudioPortConfigs for the device port and the mix port,
+ // then find / create a patch between them, and open a stream on the mix port.
+ AudioPortConfig devicePortConfig;
+ bool created = false;
+ RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
+ if (created) {
+ cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
+ }
+ RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
+ mixPortConfig, &created));
+ if (created) {
+ cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
+ }
+ setConfigFromPortConfig(aidlConfig, *mixPortConfig);
+ AudioPatch patch;
+ if (isInput) {
+ RETURN_STATUS_IF_ERROR(findOrCreatePatch(
+ {devicePortConfig.id}, {mixPortConfig->id}, &patch, &created));
+ } else {
+ RETURN_STATUS_IF_ERROR(findOrCreatePatch(
+ {mixPortConfig->id}, {devicePortConfig.id}, &patch, &created));
+ }
+ if (created) {
+ cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
+ }
+ *nominalLatency = patch.latenciesMs[0];
+ if (aidlConfig->frameCount <= 0) {
+ aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
+ }
+ *config = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
+ return OK;
+}
+
+namespace {
+
+class StreamCallbackBase {
+ protected:
+ explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
+ public:
+ void* getCookie() const { return mCookie; }
+ void setCookie(void* cookie) { mCookie = cookie; }
+ sp<CallbackBroker> getBroker() const {
+ if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
+ return nullptr;
+ }
+ private:
+ const wp<CallbackBroker> mBroker;
+ std::atomic<void*> mCookie;
+};
+
+template<class C>
+class StreamCallbackBaseHelper {
+ protected:
+ explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
+ sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
+ using CbRef = const sp<C>&;
+ ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
+ if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
+ return ndk::ScopedAStatus::ok();
+ }
+ private:
+ const StreamCallbackBase& mBase;
+};
+
+template<>
+sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
+ const sp<CallbackBroker>& broker, void* cookie) {
+ if (broker != nullptr) return broker->getStreamOutCallback(cookie);
+ return nullptr;
+}
+
+template<>
+sp<StreamOutHalInterfaceEventCallback>
+StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
+ const sp<CallbackBroker>& broker, void* cookie) {
+ if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
+ return nullptr;
+}
+
+template<>
+sp<StreamOutHalInterfaceLatencyModeCallback>
+StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
+ const sp<CallbackBroker>& broker, void* cookie) {
+ if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
+ return nullptr;
+}
+
+/*
+Note on the callback ownership.
+
+In the Binder ownership model, the server implementation is kept alive
+as long as there is any client (proxy object) alive. This is done by
+incrementing the refcount of the server-side object by the Binder framework.
+When it detects that the last client is gone, it decrements the refcount back.
+
+Thus, it is not needed to keep any references to StreamCallback on our
+side (after we have sent an instance to the client), because we are
+the server-side. The callback object will be kept alive as long as the HAL server
+holds a strong ref to IStreamCallback proxy.
+*/
+
+class OutputStreamCallbackAidl : public StreamCallbackBase,
+ public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
+ public ::aidl::android::hardware::audio::core::BnStreamCallback {
+ public:
+ explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
+ : StreamCallbackBase(broker),
+ StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
+ *static_cast<StreamCallbackBase*>(this)) {}
+ ndk::ScopedAStatus onTransferReady() override {
+ return runCb([](CbRef cb) { cb->onWriteReady(); });
+ }
+ ndk::ScopedAStatus onError() override {
+ return runCb([](CbRef cb) { cb->onError(); });
+ }
+ ndk::ScopedAStatus onDrainReady() override {
+ return runCb([](CbRef cb) { cb->onDrainReady(); });
+ }
+};
+
+class OutputStreamEventCallbackAidl :
+ public StreamCallbackBase,
+ public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
+ public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
+ public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
+ public:
+ explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
+ : StreamCallbackBase(broker),
+ StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
+ *static_cast<StreamCallbackBase*>(this)),
+ StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
+ *static_cast<StreamCallbackBase*>(this)) {}
+ ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
+ std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
+ return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
+ [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
+ }
+ ndk::ScopedAStatus onRecommendedLatencyModeChanged(
+ const std::vector<AudioLatencyMode>& in_modes) override {
+ auto halModes = VALUE_OR_FATAL(
+ ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
+ in_modes,
+ ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
+ return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
+ [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
+ }
+};
+
+} // namespace
+
+status_t DeviceHalAidl::openOutputStream(
+ audio_io_handle_t handle, audio_devices_t devices,
+ audio_output_flags_t flags, struct audio_config* config,
+ const char* address,
+ sp<StreamOutHalInterface>* outStream) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (!outStream || !config) {
+ return BAD_VALUE;
+ }
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
+ AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
+ AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
+ int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
+ AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
+ AudioPortConfig mixPortConfig;
+ Cleanups cleanups;
+ int32_t nominalLatency;
+ RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
+ AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
+ config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+ ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
+ args.portConfigId = mixPortConfig.id;
+ const bool isOffload = isBitPositionFlagSet(
+ aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
+ std::shared_ptr<OutputStreamCallbackAidl> streamCb;
+ if (isOffload) {
+ streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
+ }
+ auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
+ if (isOffload) {
+ args.offloadInfo = aidlConfig.offloadInfo;
+ args.callback = streamCb;
+ }
+ args.bufferSizeFrames = aidlConfig.frameCount;
+ args.eventCallback = eventCb;
+ ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
+ StreamContextAidl context(ret.desc, isOffload);
+ if (!context.isValid()) {
+ ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
+ __func__, ret.desc.toString().c_str());
+ return NO_INIT;
+ }
+ *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
+ std::move(ret.stream), this /*callbackBroker*/);
+ void* cbCookie = (*outStream).get();
+ {
+ std::lock_guard l(mLock);
+ mCallbacks.emplace(cbCookie, Callbacks{});
+ }
+ if (streamCb) streamCb->setCookie(cbCookie);
+ eventCb->setCookie(cbCookie);
+ cleanups.disarmAll();
+ return OK;
+}
+
+status_t DeviceHalAidl::openInputStream(
+ audio_io_handle_t handle, audio_devices_t devices,
+ struct audio_config* config, audio_input_flags_t flags,
+ const char* address, audio_source_t source,
+ audio_devices_t outputDevice, const char* outputDeviceAddress,
+ sp<StreamInHalInterface>* inStream) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (!inStream || !config) {
+ return BAD_VALUE;
+ }
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
+ AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
+ AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
+ int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
+ AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
+ AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
+ AudioPortConfig mixPortConfig;
+ Cleanups cleanups;
+ int32_t nominalLatency;
+ RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
+ config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+ ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
+ args.portConfigId = mixPortConfig.id;
+ RecordTrackMetadata aidlTrackMetadata{
+ .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
+ if (outputDevice != AUDIO_DEVICE_NONE) {
+ aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_device_AudioDevice(
+ outputDevice, outputDeviceAddress));
+ }
+ args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
+ args.bufferSizeFrames = aidlConfig.frameCount;
+ ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
+ StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
+ if (!context.isValid()) {
+ ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
+ __func__, ret.desc.toString().c_str());
+ return NO_INIT;
+ }
+ *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), nominalLatency,
+ std::move(ret.stream), this /*micInfoProvider*/);
+ cleanups.disarmAll();
+ return OK;
+}
+
+status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
+ *supportsPatches = true;
+ return OK;
+}
+
+status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
+ const struct audio_port_config* sources,
+ unsigned int num_sinks,
+ const struct audio_port_config* sinks,
+ audio_patch_handle_t* patch) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
+ sources == nullptr || sinks == nullptr || patch == nullptr) {
+ return BAD_VALUE;
+ }
+ // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
+ // the framework wants to create a new patch. The handle has to be generated
+ // by the HAL. Since handles generated this way can only be unique within
+ // a HAL module, the framework generates a globally unique handle, and maps
+ // it on the <HAL module, patch handle> pair.
+ // When the patch handle is set, it meant the framework intends to update
+ // an existing patch.
+ //
+ // This behavior corresponds to HAL module behavior, with the only difference
+ // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
+ // that both the framework and the HAL use the same value for "no ID":
+ static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
+ int32_t halPatchId = static_cast<int32_t>(*patch);
+
+ // Upon conversion, mix port configs contain audio configuration, while
+ // device port configs contain device address. This data is used to find
+ // or create HAL configs.
+ std::vector<AudioPortConfig> aidlSources, aidlSinks;
+ for (unsigned int i = 0; i < num_sources; ++i) {
+ bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
+ sources[i].role, sources[i].type)) ==
+ ::aidl::android::AudioPortDirection::INPUT;
+ aidlSources.push_back(VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
+ sources[i], isInput, 0)));
+ }
+ for (unsigned int i = 0; i < num_sinks; ++i) {
+ bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
+ sinks[i].role, sinks[i].type)) ==
+ ::aidl::android::AudioPortDirection::INPUT;
+ aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
+ sinks[i], isInput, 0)));
+ }
+ Cleanups cleanups;
+ auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
+ AudioPatch aidlPatch;
+ if (existingPatchIt != mPatches.end()) {
+ aidlPatch = existingPatchIt->second;
+ aidlPatch.sourcePortConfigIds.clear();
+ aidlPatch.sinkPortConfigIds.clear();
+ }
+ ALOGD("%s: sources: %s, sinks: %s",
+ __func__, ::android::internal::ToString(aidlSources).c_str(),
+ ::android::internal::ToString(aidlSinks).c_str());
+ auto fillPortConfigs = [&](
+ const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
+ for (const auto& s : configs) {
+ AudioPortConfig portConfig;
+ bool created = false;
+ RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
+ if (created) {
+ cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
+ }
+ ids->push_back(portConfig.id);
+ }
+ return OK;
+ };
+ RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
+ RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
+ if (existingPatchIt != mPatches.end()) {
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mModule->setAudioPatch(aidlPatch, &aidlPatch)));
+ existingPatchIt->second = aidlPatch;
+ } else {
+ bool created = false;
+ RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
+ // Since no cleanup of the patch is needed, 'created' is ignored.
+ halPatchId = aidlPatch.id;
+ *patch = static_cast<audio_patch_handle_t>(halPatchId);
+ }
+ cleanups.disarmAll();
+ return OK;
+}
+
+status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
+ if (patch == AUDIO_PATCH_HANDLE_NONE) {
+ return BAD_VALUE;
+ }
+ int32_t halPatchId = static_cast<int32_t>(patch);
+ auto patchIt = mPatches.find(halPatchId);
+ if (patchIt == mPatches.end()) {
+ ALOGE("%s: patch with id %d not found", __func__, halPatchId);
+ return BAD_VALUE;
+ }
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
+ mPatches.erase(patchIt);
+ return OK;
+}
+
+status_t DeviceHalAidl::getAudioPort(struct audio_port* port __unused) {
+ TIME_CHECK();
+ ALOGE("%s not implemented yet", __func__);
+ return INVALID_OPERATION;
+}
+
+status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port __unused) {
+ TIME_CHECK();
+ ALOGE("%s not implemented yet", __func__);
+ return INVALID_OPERATION;
+}
+
+status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config __unused) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
+ if (mMicrophones.status == Microphones::Status::UNKNOWN) {
+ TIME_CHECK();
+ std::vector<MicrophoneInfo> aidlInfo;
+ status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
+ if (status == OK) {
+ mMicrophones.status = Microphones::Status::QUERIED;
+ mMicrophones.info = std::move(aidlInfo);
+ } else if (status == INVALID_OPERATION) {
+ mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
+ } else {
+ ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
+ return {};
+ }
+ }
+ if (mMicrophones.status == Microphones::Status::QUERIED) {
+ return &mMicrophones.info;
+ }
+ return {}; // NOT_SUPPORTED
+}
+
+status_t DeviceHalAidl::getMicrophones(
+ std::vector<audio_microphone_characteristic_t>* microphones) {
+ if (!microphones) {
+ return BAD_VALUE;
+ }
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ auto staticInfo = getMicrophoneInfo();
+ if (!staticInfo) return INVALID_OPERATION;
+ std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
+ emptyDynamicInfo.reserve(staticInfo->size());
+ std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
+ [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
+ *microphones = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
+ *staticInfo, emptyDynamicInfo,
+ ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
+ );
+ return OK;
+}
+
+status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
+ sp<EffectHalInterface> effect) {
+ if (!effect) {
+ return BAD_VALUE;
+ }
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
+ sp<EffectHalInterface> effect) {
+ if (!effect) {
+ return BAD_VALUE;
+ }
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t DeviceHalAidl::getMmapPolicyInfos(
+ media::audio::common::AudioMMapPolicyType policyType __unused,
+ std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos __unused) {
+ TIME_CHECK();
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
+ TIME_CHECK();
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
+ TIME_CHECK();
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ int32_t aidlHwAvSync;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
+ return VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
+}
+
+status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ return mModule->dump(fd, Args(args).args(), args.size());
+};
+
+int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
+ TIME_CHECK();
+ ALOGE("%s not implemented yet", __func__);
+ return INVALID_OPERATION;
+}
+
+bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
+ if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
+ return p.ext.get<AudioPortExt::Tag::device>().device == device;
+}
+
+bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
+ if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
+ if (device.type.type == AudioDeviceType::IN_DEFAULT) {
+ return p.portId == mDefaultInputPortId;
+ } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
+ return p.portId == mDefaultOutputPortId;
+ }
+ return p.ext.get<AudioPortExt::Tag::device>().device == device;
+}
+
+status_t DeviceHalAidl::createPortConfig(
+ const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result) {
+ TIME_CHECK();
+ AudioPortConfig appliedPortConfig;
+ bool applied = false;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
+ requestedPortConfig, &appliedPortConfig, &applied)));
+ if (!applied) {
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
+ appliedPortConfig, &appliedPortConfig, &applied)));
+ if (!applied) {
+ ALOGE("%s: module %s did not apply suggested config %s",
+ __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
+ return NO_INIT;
+ }
+ }
+ auto id = appliedPortConfig.id;
+ auto [it, inserted] = mPortConfigs.emplace(std::move(id), std::move(appliedPortConfig));
+ LOG_ALWAYS_FATAL_IF(!inserted, "%s: port config with id %d already exists",
+ __func__, it->first);
+ *result = it;
+ return OK;
+}
+
+status_t DeviceHalAidl::findOrCreatePatch(
+ const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
+ std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
+ requestedPatch.sourcePortConfigIds.end());
+ std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
+ requestedPatch.sinkPortConfigIds.end());
+ return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
+}
+
+status_t DeviceHalAidl::findOrCreatePatch(
+ const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
+ AudioPatch* patch, bool* created) {
+ auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
+ if (patchIt == mPatches.end()) {
+ TIME_CHECK();
+ AudioPatch requestedPatch, appliedPatch;
+ requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
+ sourcePortConfigIds.begin(), sourcePortConfigIds.end());
+ requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
+ sinkPortConfigIds.begin(), sinkPortConfigIds.end());
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
+ requestedPatch, &appliedPatch)));
+ patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
+ *created = true;
+ } else {
+ *created = false;
+ }
+ *patch = patchIt->second;
+ return OK;
+}
+
+status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
+ AudioPortConfig* portConfig, bool* created) {
+ auto portConfigIt = findPortConfig(device);
+ if (portConfigIt == mPortConfigs.end()) {
+ auto portsIt = findPort(device);
+ if (portsIt == mPorts.end()) {
+ ALOGE("%s: device port for device %s is not found in the module %s",
+ __func__, device.toString().c_str(), mInstance.c_str());
+ return BAD_VALUE;
+ }
+ AudioPortConfig requestedPortConfig;
+ requestedPortConfig.portId = portsIt->first;
+ RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
+ *created = true;
+ } else {
+ *created = false;
+ }
+ *portConfig = portConfigIt->second;
+ return OK;
+}
+
+status_t DeviceHalAidl::findOrCreatePortConfig(
+ const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
+ AudioSource source, AudioPortConfig* portConfig, bool* created) {
+ // These flags get removed one by one in this order when retrying port finding.
+ static const std::vector<AudioInputFlags> kOptionalInputFlags{
+ AudioInputFlags::FAST, AudioInputFlags::RAW };
+ auto portConfigIt = findPortConfig(config, flags, ioHandle);
+ if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
+ auto optionalInputFlagsIt = kOptionalInputFlags.begin();
+ AudioIoFlags matchFlags = flags.value();
+ auto portsIt = findPort(config, matchFlags);
+ while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
+ && optionalInputFlagsIt != kOptionalInputFlags.end()) {
+ if (!isBitPositionFlagSet(
+ matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
+ ++optionalInputFlagsIt;
+ continue;
+ }
+ matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
+ ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
+ portsIt = findPort(config, matchFlags);
+ ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
+ "retried with flags %s", __func__, config.toString().c_str(),
+ flags.value().toString().c_str(), mInstance.c_str(),
+ matchFlags.toString().c_str());
+ }
+ if (portsIt == mPorts.end()) {
+ ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
+ __func__, config.toString().c_str(), matchFlags.toString().c_str(),
+ mInstance.c_str());
+ return BAD_VALUE;
+ }
+ AudioPortConfig requestedPortConfig;
+ requestedPortConfig.portId = portsIt->first;
+ setPortConfigFromConfig(&requestedPortConfig, config);
+ requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
+ if (matchFlags.getTag() == AudioIoFlags::Tag::input
+ && source != AudioSource::SYS_RESERVED_INVALID) {
+ requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
+ AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
+ }
+ RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
+ *created = true;
+ } else if (!flags.has_value()) {
+ ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
+ "and was not created as flags are not specified",
+ __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
+ return BAD_VALUE;
+ } else {
+ *created = false;
+ }
+ *portConfig = portConfigIt->second;
+ return OK;
+}
+
+status_t DeviceHalAidl::findOrCreatePortConfig(
+ const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
+ using Tag = AudioPortExt::Tag;
+ if (requestedPortConfig.ext.getTag() == Tag::mix) {
+ if (const auto& p = requestedPortConfig;
+ !p.sampleRate.has_value() || !p.channelMask.has_value() ||
+ !p.format.has_value()) {
+ ALOGW("%s: provided mix port config is not fully specified: %s",
+ __func__, p.toString().c_str());
+ return BAD_VALUE;
+ }
+ AudioConfig config;
+ setConfigFromPortConfig(&config, requestedPortConfig);
+ AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
+ AudioPortMixExtUseCase::Tag::source ?
+ requestedPortConfig.ext.get<Tag::mix>().usecase.
+ get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
+ return findOrCreatePortConfig(config, requestedPortConfig.flags,
+ requestedPortConfig.ext.get<Tag::mix>().handle, source, portConfig, created);
+ } else if (requestedPortConfig.ext.getTag() == Tag::device) {
+ return findOrCreatePortConfig(
+ requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
+ }
+ ALOGW("%s: unsupported audio port config: %s",
+ __func__, requestedPortConfig.toString().c_str());
+ return BAD_VALUE;
+}
+
+DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
+ const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
+ return std::find_if(mPatches.begin(), mPatches.end(),
+ [&](const auto& pair) {
+ const auto& p = pair.second;
+ std::set<int32_t> patchSrcs(
+ p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
+ std::set<int32_t> patchSinks(
+ p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
+ return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
+}
+
+DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
+ if (device.type.type == AudioDeviceType::IN_DEFAULT) {
+ return mPorts.find(mDefaultInputPortId);
+ } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
+ return mPorts.find(mDefaultOutputPortId);
+ }
+ return std::find_if(mPorts.begin(), mPorts.end(),
+ [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
+}
+
+DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
+ const AudioConfig& config, const AudioIoFlags& flags) {
+ auto matcher = [&](const auto& pair) {
+ const auto& p = pair.second;
+ return p.ext.getTag() == AudioPortExt::Tag::mix &&
+ p.flags == flags &&
+ std::find_if(p.profiles.begin(), p.profiles.end(),
+ [&](const auto& prof) {
+ return prof.format == config.base.format &&
+ std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
+ config.base.channelMask) != prof.channelMasks.end() &&
+ std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
+ config.base.sampleRate) != prof.sampleRates.end();
+ }) != p.profiles.end(); };
+ return std::find_if(mPorts.begin(), mPorts.end(), matcher);
+}
+
+DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
+ return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
+ [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
+}
+
+DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
+ const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
+ using Tag = AudioPortExt::Tag;
+ return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
+ [&](const auto& pair) {
+ const auto& p = pair.second;
+ LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
+ !p.sampleRate.has_value() || !p.channelMask.has_value() ||
+ !p.format.has_value() || !p.flags.has_value(),
+ "%s: stored mix port config is not fully specified: %s",
+ __func__, p.toString().c_str());
+ return p.ext.getTag() == Tag::mix &&
+ isConfigEqualToPortConfig(config, p) &&
+ (!flags.has_value() || p.flags.value() == flags.value()) &&
+ p.ext.template get<Tag::mix>().handle == ioHandle; });
+}
+/*
+DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
+ const AudioPortConfig& portConfig) {
+ using Tag = AudioPortExt::Tag;
+ if (portConfig.ext.getTag() == Tag::mix) {
+ return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
+ [&](const auto& pair) {
+ const auto& p = pair.second;
+ LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
+ !p.sampleRate.has_value() || !p.channelMask.has_value() ||
+ !p.format.has_value() || !p.flags.has_value(),
+ "%s: stored mix port config is not fully specified: %s",
+ __func__, p.toString().c_str());
+ return p.ext.getTag() == Tag::mix &&
+ (!portConfig.sampleRate.has_value() ||
+ p.sampleRate == portConfig.sampleRate) &&
+ (!portConfig.channelMask.has_value() ||
+ p.channelMask == portConfig.channelMask) &&
+ (!portConfig.format.has_value() || p.format == portConfig.format) &&
+ (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
+ p.ext.template get<Tag::mix>().handle ==
+ portConfig.ext.template get<Tag::mix>().handle; });
+ } else if (portConfig.ext.getTag() == Tag::device) {
+ return findPortConfig(portConfig.ext.get<Tag::device>().device);
+ }
+ return mPortConfigs.end();
+}
+*/
+void DeviceHalAidl::resetPatch(int32_t patchId) {
+ if (auto it = mPatches.find(patchId); it != mPatches.end()) {
+ mPatches.erase(it);
+ TIME_CHECK();
+ if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
+ ALOGE("%s: error while resetting patch %d: %s",
+ __func__, patchId, status.getDescription().c_str());
+ }
+ return;
+ }
+ ALOGE("%s: patch id %d not found", __func__, patchId);
+}
+
+void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
+ if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
+ mPortConfigs.erase(it);
+ TIME_CHECK();
+ if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
+ !status.isOk()) {
+ ALOGE("%s: error while resetting port config %d: %s",
+ __func__, portConfigId, status.getDescription().c_str());
+ }
+ return;
+ }
+ ALOGE("%s: port config id %d not found", __func__, portConfigId);
+}
+
+void DeviceHalAidl::clearCallbacks(void* cookie) {
+ std::lock_guard l(mLock);
+ mCallbacks.erase(cookie);
+}
+
+sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
+ return getCallbackImpl(cookie, &Callbacks::out);
+}
+
+void DeviceHalAidl::setStreamOutCallback(
+ void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
+ setCallbackImpl(cookie, &Callbacks::out, cb);
+}
+
+sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
+ void* cookie) {
+ return getCallbackImpl(cookie, &Callbacks::event);
+}
+
+void DeviceHalAidl::setStreamOutEventCallback(
+ void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
+ setCallbackImpl(cookie, &Callbacks::event, cb);
+}
+
+sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
+ void* cookie) {
+ return getCallbackImpl(cookie, &Callbacks::latency);
+}
+
+void DeviceHalAidl::setStreamOutLatencyModeCallback(
+ void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
+ setCallbackImpl(cookie, &Callbacks::latency, cb);
+}
+
+template<class C>
+sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
+ std::lock_guard l(mLock);
+ if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
+ return ((it->second).*field).promote();
+ }
+ return nullptr;
+}
+template<class C>
+void DeviceHalAidl::setCallbackImpl(
+ void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
+ std::lock_guard l(mLock);
+ if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
+ (it->second).*field = cb;
+ }
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
new file mode 100644
index 0000000..0a86ddc
--- /dev/null
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2022 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 <map>
+#include <set>
+#include <vector>
+
+#include <aidl/android/hardware/audio/core/BpModule.h>
+#include <android-base/thread_annotations.h>
+#include <media/audiohal/DeviceHalInterface.h>
+#include <media/audiohal/EffectHalInterface.h>
+
+#include "ConversionHelperAidl.h"
+
+namespace android {
+
+class StreamOutHalInterfaceCallback;
+class StreamOutHalInterfaceEventCallback;
+class StreamOutHalInterfaceLatencyModeCallback;
+
+// The role of the broker is to connect AIDL callback interface implementations
+// with StreamOut callback implementations. Since AIDL requires all callbacks
+// to be provided upfront, while libaudiohal interfaces allow late registration,
+// there is a need to coordinate the matching process.
+class CallbackBroker : public virtual RefBase {
+ public:
+ virtual ~CallbackBroker() = default;
+ // The cookie is always the stream instance pointer. We don't use weak pointers to avoid extra
+ // costs on reference counting. The stream cleans up related entries on destruction. Since
+ // access to the callbacks map is synchronized, the possibility for pointer aliasing due to
+ // allocation of a new stream at the address of previously deleted stream is avoided.
+ virtual void clearCallbacks(void* cookie) = 0;
+ virtual sp<StreamOutHalInterfaceCallback> getStreamOutCallback(void* cookie) = 0;
+ virtual void setStreamOutCallback(void* cookie, const sp<StreamOutHalInterfaceCallback>&) = 0;
+ virtual sp<StreamOutHalInterfaceEventCallback> getStreamOutEventCallback(void* cookie) = 0;
+ virtual void setStreamOutEventCallback(void* cookie,
+ const sp<StreamOutHalInterfaceEventCallback>&) = 0;
+ virtual sp<StreamOutHalInterfaceLatencyModeCallback> getStreamOutLatencyModeCallback(
+ void* cookie) = 0;
+ virtual void setStreamOutLatencyModeCallback(
+ void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>&) = 0;
+};
+
+class MicrophoneInfoProvider : public virtual RefBase {
+ public:
+ using Info = std::vector<::aidl::android::media::audio::common::MicrophoneInfo>;
+ virtual ~MicrophoneInfoProvider() = default;
+ // Returns a nullptr if the HAL does not support microphone info retrieval.
+ virtual Info const* getMicrophoneInfo() = 0;
+};
+
+class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl,
+ public CallbackBroker, public MicrophoneInfoProvider {
+ public:
+ // Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
+ status_t getSupportedDevices(uint32_t *devices) override;
+
+ // Check to see if the audio hardware interface has been initialized.
+ status_t initCheck() override;
+
+ // Set the audio volume of a voice call. Range is between 0.0 and 1.0.
+ status_t setVoiceVolume(float volume) override;
+
+ // Set the audio volume for all audio activities other than voice call.
+ status_t setMasterVolume(float volume) override;
+
+ // Get the current master volume value for the HAL.
+ status_t getMasterVolume(float *volume) override;
+
+ // Called when the audio mode changes.
+ status_t setMode(audio_mode_t mode) override;
+
+ // Muting control.
+ status_t setMicMute(bool state) override;
+
+ status_t getMicMute(bool* state) override;
+
+ status_t setMasterMute(bool state) override;
+
+ status_t getMasterMute(bool *state) override;
+
+ // Set global audio parameters.
+ status_t setParameters(const String8& kvPairs) override;
+
+ // Get global audio parameters.
+ status_t getParameters(const String8& keys, String8 *values) override;
+
+ // Returns audio input buffer size according to parameters passed.
+ status_t getInputBufferSize(const struct audio_config* config, size_t* size) override;
+
+ // Creates and opens the audio hardware output stream. The stream is closed
+ // by releasing all references to the returned object.
+ status_t openOutputStream(audio_io_handle_t handle, audio_devices_t devices,
+ audio_output_flags_t flags, struct audio_config* config,
+ const char* address, sp<StreamOutHalInterface>* outStream) override;
+
+ // Creates and opens the audio hardware input stream. The stream is closed
+ // by releasing all references to the returned object.
+ status_t openInputStream(audio_io_handle_t handle, audio_devices_t devices,
+ struct audio_config* config, audio_input_flags_t flags,
+ const char* address, audio_source_t source,
+ audio_devices_t outputDevice, const char* outputDeviceAddress,
+ sp<StreamInHalInterface>* inStream) override;
+
+ // Returns whether createAudioPatch and releaseAudioPatch operations are supported.
+ status_t supportsAudioPatches(bool* supportsPatches) override;
+
+ // Creates an audio patch between several source and sink ports.
+ status_t createAudioPatch(unsigned int num_sources, const struct audio_port_config* sources,
+ unsigned int num_sinks, const struct audio_port_config* sinks,
+ audio_patch_handle_t* patch) override;
+
+ // Releases an audio patch.
+ status_t releaseAudioPatch(audio_patch_handle_t patch) override;
+
+ // Fills the list of supported attributes for a given audio port.
+ status_t getAudioPort(struct audio_port* port) override;
+
+ // Fills the list of supported attributes for a given audio port.
+ status_t getAudioPort(struct audio_port_v7 *port) override;
+
+ // Set audio port configuration.
+ status_t setAudioPortConfig(const struct audio_port_config* config) override;
+
+ // List microphones
+ status_t getMicrophones(std::vector<audio_microphone_characteristic_t>* microphones);
+
+ status_t addDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
+
+ status_t removeDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
+
+ status_t getMmapPolicyInfos(media::audio::common::AudioMMapPolicyType policyType __unused,
+ std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos
+ __unused) override;
+
+ int32_t getAAudioMixerBurstCount() override;
+
+ int32_t getAAudioHardwareBurstMinUsec() override;
+
+ error::Result<audio_hw_sync_t> getHwAvSync() override;
+
+ status_t dump(int __unused, const Vector<String16>& __unused) override;
+
+ int32_t supportsBluetoothVariableLatency(bool* supports __unused) override;
+
+ private:
+ friend class sp<DeviceHalAidl>;
+
+ struct Callbacks { // No need to use `atomic_wp` because access is serialized.
+ wp<StreamOutHalInterfaceCallback> out;
+ wp<StreamOutHalInterfaceEventCallback> event;
+ wp<StreamOutHalInterfaceLatencyModeCallback> latency;
+ };
+ struct Microphones {
+ enum Status { UNKNOWN, NOT_SUPPORTED, QUERIED };
+ Status status = Status::UNKNOWN;
+ MicrophoneInfoProvider::Info info;
+ };
+ using Patches = std::map<int32_t /*patch ID*/,
+ ::aidl::android::hardware::audio::core::AudioPatch>;
+ using PortConfigs = std::map<int32_t /*port config ID*/,
+ ::aidl::android::media::audio::common::AudioPortConfig>;
+ using Ports = std::map<int32_t /*port ID*/, ::aidl::android::media::audio::common::AudioPort>;
+ class Cleanups;
+
+ // Must not be constructed directly by clients.
+ DeviceHalAidl(
+ const std::string& instance,
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module)
+ : ConversionHelperAidl("DeviceHalAidl"), mInstance(instance), mModule(module) {}
+
+ ~DeviceHalAidl() override = default;
+
+ bool audioDeviceMatches(const ::aidl::android::media::audio::common::AudioDevice& device,
+ const ::aidl::android::media::audio::common::AudioPort& p);
+ bool audioDeviceMatches(const ::aidl::android::media::audio::common::AudioDevice& device,
+ const ::aidl::android::media::audio::common::AudioPortConfig& p);
+ status_t createPortConfig(
+ const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
+ PortConfigs::iterator* result);
+ status_t findOrCreatePatch(
+ const std::set<int32_t>& sourcePortConfigIds,
+ const std::set<int32_t>& sinkPortConfigIds,
+ ::aidl::android::hardware::audio::core::AudioPatch* patch, bool* created);
+ status_t findOrCreatePatch(
+ const ::aidl::android::hardware::audio::core::AudioPatch& requestedPatch,
+ ::aidl::android::hardware::audio::core::AudioPatch* patch, bool* created);
+ status_t findOrCreatePortConfig(
+ const ::aidl::android::media::audio::common::AudioDevice& device,
+ ::aidl::android::media::audio::common::AudioPortConfig* portConfig,
+ bool* created);
+ status_t findOrCreatePortConfig(
+ const ::aidl::android::media::audio::common::AudioConfig& config,
+ const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
+ int32_t ioHandle,
+ ::aidl::android::media::audio::common::AudioSource aidlSource,
+ ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
+ status_t findOrCreatePortConfig(
+ const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
+ ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
+ Patches::iterator findPatch(const std::set<int32_t>& sourcePortConfigIds,
+ const std::set<int32_t>& sinkPortConfigIds);
+ Ports::iterator findPort(const ::aidl::android::media::audio::common::AudioDevice& device);
+ Ports::iterator findPort(
+ const ::aidl::android::media::audio::common::AudioConfig& config,
+ const ::aidl::android::media::audio::common::AudioIoFlags& flags);
+ PortConfigs::iterator findPortConfig(
+ const ::aidl::android::media::audio::common::AudioDevice& device);
+ PortConfigs::iterator findPortConfig(
+ const ::aidl::android::media::audio::common::AudioConfig& config,
+ const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
+ int32_t ioHandle);
+ // Currently unused but may be useful for implementing setAudioPortConfig
+ // PortConfigs::iterator findPortConfig(
+ // const ::aidl::android::media::audio::common::AudioPortConfig& portConfig);
+ status_t prepareToOpenStream(
+ int32_t aidlHandle,
+ const ::aidl::android::media::audio::common::AudioDevice& aidlDevice,
+ const ::aidl::android::media::audio::common::AudioIoFlags& aidlFlags,
+ ::aidl::android::media::audio::common::AudioSource aidlSource,
+ struct audio_config* config,
+ Cleanups* cleanups,
+ ::aidl::android::media::audio::common::AudioConfig* aidlConfig,
+ ::aidl::android::media::audio::common::AudioPortConfig* mixPortConfig,
+ int32_t* nominalLatency);
+ void resetPatch(int32_t patchId);
+ void resetPortConfig(int32_t portConfigId);
+
+ // CallbackBroker implementation
+ void clearCallbacks(void* cookie) override;
+ sp<StreamOutHalInterfaceCallback> getStreamOutCallback(void* cookie) override;
+ void setStreamOutCallback(void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) override;
+ sp<StreamOutHalInterfaceEventCallback> getStreamOutEventCallback(void* cookie) override;
+ void setStreamOutEventCallback(void* cookie,
+ const sp<StreamOutHalInterfaceEventCallback>& cb) override;
+ sp<StreamOutHalInterfaceLatencyModeCallback> getStreamOutLatencyModeCallback(
+ void* cookie) override;
+ void setStreamOutLatencyModeCallback(
+ void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) override;
+ // Implementation helpers.
+ template<class C> sp<C> getCallbackImpl(void* cookie, wp<C> Callbacks::* field);
+ template<class C> void setCallbackImpl(void* cookie, wp<C> Callbacks::* field, const sp<C>& cb);
+
+ // MicrophoneInfoProvider implementation
+ MicrophoneInfoProvider::Info const* getMicrophoneInfo() override;
+
+ const std::string mInstance;
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule;
+ Ports mPorts;
+ int32_t mDefaultInputPortId = -1;
+ int32_t mDefaultOutputPortId = -1;
+ PortConfigs mPortConfigs;
+ Patches mPatches;
+ Microphones mMicrophones;
+ std::mutex mLock;
+ std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
+};
+
+} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index 0cdf621..12acebd 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -46,9 +46,6 @@
using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
-#define TIME_CHECK() auto timeCheck = \
- mediautils::makeTimeCheckStatsForClassMethod(getClassName(), __func__)
-
DeviceHalHidl::DeviceHalHidl(const sp<::android::hardware::audio::CPP_VERSION::IDevice>& device)
: CoreConversionHelperHidl("DeviceHalHidl"), mDevice(device) {
}
@@ -459,12 +456,13 @@
#if MAJOR_VERSION == 2
status_t DeviceHalHidl::getMicrophones(
- std::vector<media::MicrophoneInfo> *microphonesInfo __unused) {
+ std::vector<audio_microphone_characteristic_t> *microphonesInfo __unused) {
if (mDevice == 0) return NO_INIT;
return INVALID_OPERATION;
}
#elif MAJOR_VERSION >= 4
-status_t DeviceHalHidl::getMicrophones(std::vector<media::MicrophoneInfo> *microphonesInfo) {
+status_t DeviceHalHidl::getMicrophones(
+ std::vector<audio_microphone_characteristic_t> *microphonesInfo) {
TIME_CHECK();
if (mDevice == 0) return NO_INIT;
Result retval;
@@ -475,8 +473,7 @@
audio_microphone_characteristic_t dst;
//convert
(void)CoreUtils::microphoneInfoToHal(micArrayHal[k], &dst);
- media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
- microphonesInfo->push_back(microphone);
+ microphonesInfo->push_back(dst);
}
});
return processReturn("getMicrophones", ret, retval);
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index f6519b6..052eb65 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -30,87 +30,74 @@
{
public:
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
- virtual status_t getSupportedDevices(uint32_t *devices);
+ status_t getSupportedDevices(uint32_t *devices) override;
// Check to see if the audio hardware interface has been initialized.
- virtual status_t initCheck();
+ status_t initCheck() override;
// Set the audio volume of a voice call. Range is between 0.0 and 1.0.
- virtual status_t setVoiceVolume(float volume);
+ status_t setVoiceVolume(float volume) override;
// Set the audio volume for all audio activities other than voice call.
- virtual status_t setMasterVolume(float volume);
+ status_t setMasterVolume(float volume) override;
// Get the current master volume value for the HAL.
- virtual status_t getMasterVolume(float *volume);
+ status_t getMasterVolume(float *volume) override;
// Called when the audio mode changes.
- virtual status_t setMode(audio_mode_t mode);
+ status_t setMode(audio_mode_t mode) override;
// Muting control.
- virtual status_t setMicMute(bool state);
- virtual status_t getMicMute(bool *state);
- virtual status_t setMasterMute(bool state);
- virtual status_t getMasterMute(bool *state);
+ status_t setMicMute(bool state) override;
+ status_t getMicMute(bool *state) override;
+ status_t setMasterMute(bool state) override;
+ status_t getMasterMute(bool *state) override;
// Set global audio parameters.
- virtual status_t setParameters(const String8& kvPairs);
+ status_t setParameters(const String8& kvPairs) override;
// Get global audio parameters.
- virtual status_t getParameters(const String8& keys, String8 *values);
+ status_t getParameters(const String8& keys, String8 *values) override;
// Returns audio input buffer size according to parameters passed.
- virtual status_t getInputBufferSize(const struct audio_config *config,
- size_t *size);
+ status_t getInputBufferSize(const struct audio_config* config, size_t* size) override;
// Creates and opens the audio hardware output stream. The stream is closed
// by releasing all references to the returned object.
- virtual status_t openOutputStream(
- audio_io_handle_t handle,
- audio_devices_t devices,
- audio_output_flags_t flags,
- struct audio_config *config,
- const char *address,
- sp<StreamOutHalInterface> *outStream);
+ status_t openOutputStream(audio_io_handle_t handle, audio_devices_t devices,
+ audio_output_flags_t flags, struct audio_config* config,
+ const char* address, sp<StreamOutHalInterface>* outStream) override;
// Creates and opens the audio hardware input stream. The stream is closed
// by releasing all references to the returned object.
- virtual status_t openInputStream(
- audio_io_handle_t handle,
- audio_devices_t devices,
- struct audio_config *config,
- audio_input_flags_t flags,
- const char *address,
- audio_source_t source,
- audio_devices_t outputDevice,
- const char *outputDeviceAddress,
- sp<StreamInHalInterface> *inStream);
+ status_t openInputStream(audio_io_handle_t handle, audio_devices_t devices,
+ struct audio_config* config, audio_input_flags_t flags,
+ const char* address, audio_source_t source,
+ audio_devices_t outputDevice, const char* outputDeviceAddress,
+ sp<StreamInHalInterface>* inStream) override;
// Returns whether createAudioPatch and releaseAudioPatch operations are supported.
- virtual status_t supportsAudioPatches(bool *supportsPatches);
+ status_t supportsAudioPatches(bool* supportsPatches) override;
// Creates an audio patch between several source and sink ports.
- virtual status_t createAudioPatch(
- unsigned int num_sources,
- const struct audio_port_config *sources,
- unsigned int num_sinks,
- const struct audio_port_config *sinks,
- audio_patch_handle_t *patch);
+ status_t createAudioPatch(unsigned int num_sources, const struct audio_port_config* sources,
+ unsigned int num_sinks, const struct audio_port_config* sinks,
+ audio_patch_handle_t* patch) override;
// Releases an audio patch.
- virtual status_t releaseAudioPatch(audio_patch_handle_t patch);
+ status_t releaseAudioPatch(audio_patch_handle_t patch) override;
// Fills the list of supported attributes for a given audio port.
- virtual status_t getAudioPort(struct audio_port *port);
+ status_t getAudioPort(struct audio_port *port) override;
// Fills the list of supported attributes for a given audio port.
- virtual status_t getAudioPort(struct audio_port_v7 *port);
+ status_t getAudioPort(struct audio_port_v7 *port) override;
// Set audio port configuration.
- virtual status_t setAudioPortConfig(const struct audio_port_config *config);
+ status_t setAudioPortConfig(const struct audio_port_config *config) override;
// List microphones
- virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+ status_t getMicrophones(std::vector<audio_microphone_characteristic_t>* microphones) override;
status_t addDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
status_t removeDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
@@ -132,6 +119,11 @@
return INVALID_OPERATION;
}
+ int32_t supportsBluetoothVariableLatency(bool* supports __unused) override {
+ // TODO: Implement the HAL query when moving to AIDL HAL.
+ return INVALID_OPERATION;
+ }
+
status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override;
error::Result<audio_hw_sync_t> getHwAvSync() override;
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
new file mode 100644
index 0000000..2eaaf5d
--- /dev/null
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DevicesFactoryHalAidl"
+//#define LOG_NDEBUG 0
+
+#include <aidl/android/hardware/audio/core/IModule.h>
+#include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
+#include <memory>
+#include <utils/Log.h>
+
+#include "DeviceHalAidl.h"
+#include "DevicesFactoryHalAidl.h"
+
+using namespace ::aidl::android::hardware::audio::core;
+using ::android::detail::AudioHalVersionInfo;
+
+namespace android {
+
+DevicesFactoryHalAidl::DevicesFactoryHalAidl(std::shared_ptr<IConfig> iconfig)
+ : mIConfig(std::move(iconfig)) {
+ ALOG_ASSERT(iconfig != nullptr, "Provided default IConfig service is NULL");
+}
+
+// Opens a device with the specified name. To close the device, it is
+// necessary to release references to the returned object.
+status_t DevicesFactoryHalAidl::openDevice(const char *name, sp<DeviceHalInterface> *device) {
+ if (name == nullptr || device == nullptr) {
+ return BAD_VALUE;
+ }
+
+ std::shared_ptr<IModule> service;
+ // FIXME: Normally we will list available HAL modules and connect to them,
+ // however currently we still get the list of module names from the config.
+ // Since the example service does not have all modules, the SM will wait
+ // for the missing ones forever.
+ if (strcmp(name, "primary") == 0 || strcmp(name, "r_submix") == 0 || strcmp(name, "usb") == 0) {
+ if (strcmp(name, "primary") == 0) name = "default";
+ auto serviceName = std::string(IModule::descriptor) + "/" + name;
+ service = IModule::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
+ ALOGE_IF(service == nullptr, "%s fromBinder %s failed", __func__, serviceName.c_str());
+ }
+ // If the service is a nullptr, the device will not be really functional,
+ // but will not crash either.
+ *device = sp<DeviceHalAidl>::make(name, service);
+ return OK;
+}
+
+status_t DevicesFactoryHalAidl::getHalPids(std::vector<pid_t> *pids) {
+ if (pids == nullptr) {
+ return BAD_VALUE;
+ }
+ // The functionality for retrieving debug infos of services is not exposed via the NDK.
+ sp<IServiceManager> sm = defaultServiceManager();
+ if (sm == nullptr) {
+ return NO_INIT;
+ }
+ std::set<pid_t> pidsSet;
+ const auto moduleServiceName = std::string(IModule::descriptor) + "/";
+ auto debugInfos = sm->getServiceDebugInfo();
+ for (const auto& info : debugInfos) {
+ if (info.pid > 0 &&
+ info.name.size() > moduleServiceName.size() && // '>' as there must be instance name
+ info.name.substr(0, moduleServiceName.size()) == moduleServiceName) {
+ pidsSet.insert(info.pid);
+ }
+ }
+ *pids = {pidsSet.begin(), pidsSet.end()};
+ return NO_ERROR;
+}
+
+status_t DevicesFactoryHalAidl::setCallbackOnce(sp<DevicesFactoryHalCallback> callback) {
+ // Dynamic registration of module instances is not supported. The functionality
+ // in the audio server which is related to this callback can be removed together
+ // with HIDL support.
+ ALOG_ASSERT(callback != nullptr);
+ if (callback != nullptr) {
+ callback->onNewDevicesAvailable();
+ }
+ return NO_ERROR;
+}
+
+AudioHalVersionInfo DevicesFactoryHalAidl::getHalVersion() const {
+ int32_t versionNumber = 0;
+ if (mIConfig != 0) {
+ if (ndk::ScopedAStatus status = mIConfig->getInterfaceVersion(&versionNumber);
+ !status.isOk()) {
+ ALOGE("%s getInterfaceVersion failed: %s", __func__, status.getDescription().c_str());
+ }
+ } else {
+ ALOGW("%s no IConfig instance", __func__);
+ }
+ // AIDL does not have minor version, fill 0 for all versions
+ return AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, versionNumber);
+}
+
+// Main entry-point to the shared library.
+extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
+ auto serviceName = std::string(IConfig::descriptor) + "/default";
+ auto service = IConfig::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
+ if (!service) {
+ ALOGE("%s binder service %s not exist", __func__, serviceName.c_str());
+ return nullptr;
+ }
+ return new DevicesFactoryHalAidl(service);
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.h b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
new file mode 100644
index 0000000..cb627bc
--- /dev/null
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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 <aidl/android/hardware/audio/core/IConfig.h>
+#include <media/audiohal/DevicesFactoryHalInterface.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class DevicesFactoryHalAidl : public DevicesFactoryHalInterface
+{
+ public:
+ explicit DevicesFactoryHalAidl(
+ std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> iConfig);
+
+ // Opens a device with the specified name. To close the device, it is
+ // necessary to release references to the returned object.
+ status_t openDevice(const char *name, sp<DeviceHalInterface> *device) override;
+
+ status_t getHalPids(std::vector<pid_t> *pids) override;
+
+ status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
+
+ android::detail::AudioHalVersionInfo getHalVersion() const override;
+
+ private:
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> mIConfig;
+ ~DevicesFactoryHalAidl() = default;
+};
+
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp b/media/libaudiohal/impl/DevicesFactoryHalEntry.cpp
similarity index 74%
copy from media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp
copy to media/libaudiohal/impl/DevicesFactoryHalEntry.cpp
index 2c6f2c6..5bf6d89 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalEntry.cpp
@@ -14,8 +14,10 @@
* limitations under the License.
*/
-extern "C" void* createIEffectsFactoryImpl();
+#include "android/media/AudioHalVersion.h"
-extern "C" __attribute__((visibility("default"))) void* createIEffectsFactory() {
- return createIEffectsFactoryImpl();
+extern "C" void* createIDevicesFactoryImpl();
+
+extern "C" __attribute__((visibility("default"))) void* createIDevicesFactory() {
+ return createIDevicesFactoryImpl();
}
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
index 4069a6b..9f06f83 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
@@ -29,6 +29,7 @@
#include "DeviceHalHidl.h"
#include "DevicesFactoryHalHidl.h"
+using ::android::detail::AudioHalVersionInfo;
using ::android::hardware::audio::CPP_VERSION::IDevice;
using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::Result;
using ::android::hardware::Return;
@@ -226,8 +227,13 @@
return mDeviceFactories;
}
+
+AudioHalVersionInfo DevicesFactoryHalHidl::getHalVersion() const {
+ return AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, MAJOR_VERSION, MINOR_VERSION);
+}
+
// Main entry-point to the shared library.
-extern "C" __attribute__((visibility("default"))) void* createIDevicesFactory() {
+extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
auto service = hardware::audio::CPP_VERSION::IDevicesFactory::getService();
return service ? new DevicesFactoryHalHidl(service) : nullptr;
}
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.h b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
index ffd229d..5294728 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
@@ -45,7 +45,7 @@
status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
- float getHalVersion() const override { return MAJOR_VERSION + (float)MINOR_VERSION / 10; }
+ android::detail::AudioHalVersionInfo getHalVersion() const override;
private:
friend class ServiceNotificationListener;
diff --git a/media/libaudiohal/impl/EffectBufferHalAidl.cpp b/media/libaudiohal/impl/EffectBufferHalAidl.cpp
new file mode 100644
index 0000000..a701852
--- /dev/null
+++ b/media/libaudiohal/impl/EffectBufferHalAidl.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2022 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 <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <sys/mman.h>
+#define LOG_TAG "EffectBufferHalAidl"
+//#define LOG_NDEBUG 0
+
+#include <cutils/ashmem.h>
+#include <utils/Log.h>
+
+#include "EffectBufferHalAidl.h"
+
+using ndk::ScopedFileDescriptor;
+
+namespace android {
+namespace effect {
+
+// static
+status_t EffectBufferHalAidl::allocate(size_t size, sp<EffectBufferHalInterface>* buffer) {
+ return mirror(nullptr, size, buffer);
+}
+
+status_t EffectBufferHalAidl::mirror(void* external, size_t size,
+ sp<EffectBufferHalInterface>* buffer) {
+ sp<EffectBufferHalAidl> tempBuffer = new EffectBufferHalAidl(size);
+ status_t status = tempBuffer.get()->init();
+ if (status != OK) {
+ ALOGE("%s init failed %d", __func__, status);
+ return status;
+ }
+
+ tempBuffer->setExternalData(external);
+ *buffer = tempBuffer;
+ return OK;
+}
+
+EffectBufferHalAidl::EffectBufferHalAidl(size_t size)
+ : mBufferSize(size),
+ mFrameCountChanged(false),
+ mExternalData(nullptr),
+ mAudioBuffer{0, {nullptr}} {
+}
+
+EffectBufferHalAidl::~EffectBufferHalAidl() {
+}
+
+status_t EffectBufferHalAidl::init() {
+ int fd = ashmem_create_region("audioEffectAidl", mBufferSize);
+ if (fd < 0) {
+ ALOGE("%s create ashmem failed %d", __func__, fd);
+ return fd;
+ }
+
+ ScopedFileDescriptor tempFd(fd);
+ mAudioBuffer.raw = mmap(nullptr /* address */, mBufferSize /* length */, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0 /* offset */);
+ if (mAudioBuffer.raw == MAP_FAILED) {
+ ALOGE("mmap failed for fd %d", fd);
+ mAudioBuffer.raw = nullptr;
+ return INVALID_OPERATION;
+ }
+
+ mMemory = {std::move(tempFd), static_cast<int64_t>(mBufferSize)};
+ return OK;
+}
+
+audio_buffer_t* EffectBufferHalAidl::audioBuffer() {
+ return &mAudioBuffer;
+}
+
+void* EffectBufferHalAidl::externalData() const {
+ return mExternalData;
+}
+
+void EffectBufferHalAidl::setFrameCount(size_t frameCount) {
+ mAudioBuffer.frameCount = frameCount;
+ mFrameCountChanged = true;
+}
+
+bool EffectBufferHalAidl::checkFrameCountChange() {
+ bool result = mFrameCountChanged;
+ mFrameCountChanged = false;
+ return result;
+}
+
+void EffectBufferHalAidl::setExternalData(void* external) {
+ mExternalData = external;
+}
+
+void EffectBufferHalAidl::update() {
+ update(mBufferSize);
+}
+
+void EffectBufferHalAidl::commit() {
+ commit(mBufferSize);
+}
+
+void EffectBufferHalAidl::copy(void* dst, const void* src, size_t n) const {
+ if (!dst || !src) {
+ return;
+ }
+ std::memcpy(dst, src, std::min(n, mBufferSize));
+}
+
+void EffectBufferHalAidl::update(size_t n) {
+ copy(mAudioBuffer.raw, mExternalData, n);
+}
+
+void EffectBufferHalAidl::commit(size_t n) {
+ copy(mExternalData, mAudioBuffer.raw, n);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectBufferHalAidl.h b/media/libaudiohal/impl/EffectBufferHalAidl.h
new file mode 100644
index 0000000..035314b
--- /dev/null
+++ b/media/libaudiohal/impl/EffectBufferHalAidl.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 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 <aidl/android/hardware/common/Ashmem.h>
+
+#include <media/audiohal/EffectBufferHalInterface.h>
+#include <system/audio_effect.h>
+
+namespace android {
+namespace effect {
+
+class EffectBufferHalAidl : public EffectBufferHalInterface {
+ public:
+ static status_t allocate(size_t size, sp<EffectBufferHalInterface>* buffer);
+ static status_t mirror(void* external, size_t size, sp<EffectBufferHalInterface>* buffer);
+
+ audio_buffer_t* audioBuffer() override;
+ void* externalData() const override;
+
+ size_t getSize() const override { return mBufferSize; }
+
+ void setExternalData(void* external) override;
+ void setFrameCount(size_t frameCount) override;
+ bool checkFrameCountChange() override;
+
+ void update() override;
+ void commit() override;
+ void update(size_t size) override;
+ void commit(size_t size) override;
+
+ private:
+ friend class EffectBufferHalInterface;
+
+ // buffer size in bytes
+ const size_t mBufferSize;
+ bool mFrameCountChanged;
+ void* mExternalData;
+ aidl::android::hardware::common::Ashmem mMemory;
+ audio_buffer_t mAudioBuffer;
+
+ // Can not be constructed directly by clients.
+ explicit EffectBufferHalAidl(size_t size);
+
+ ~EffectBufferHalAidl();
+ void copy(void* dst, const void* src, size_t n) const;
+ status_t init();
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
new file mode 100644
index 0000000..519b871
--- /dev/null
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "EffectConversionHelperAidl"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_visualizer.h>
+
+#include <utils/Log.h>
+
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::CommandId;
+using ::aidl::android::hardware::audio::effect::Descriptor;
+using ::aidl::android::hardware::audio::effect::Flags;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+using ::aidl::android::media::audio::common::AudioMode;
+using ::aidl::android::media::audio::common::AudioSource;
+using android::effect::utils::EffectParamReader;
+using android::effect::utils::EffectParamWriter;
+
+using ::android::status_t;
+
+const std::map<uint32_t /* effect_command_e */, EffectConversionHelperAidl::CommandHandler>
+ EffectConversionHelperAidl::mCommandHandlerMap = {
+ {EFFECT_CMD_INIT, &EffectConversionHelperAidl::handleInit},
+ {EFFECT_CMD_SET_PARAM, &EffectConversionHelperAidl::handleSetParameter},
+ {EFFECT_CMD_GET_PARAM, &EffectConversionHelperAidl::handleGetParameter},
+ {EFFECT_CMD_SET_CONFIG, &EffectConversionHelperAidl::handleSetConfig},
+ {EFFECT_CMD_GET_CONFIG, &EffectConversionHelperAidl::handleGetConfig},
+ {EFFECT_CMD_RESET, &EffectConversionHelperAidl::handleReset},
+ {EFFECT_CMD_ENABLE, &EffectConversionHelperAidl::handleEnable},
+ {EFFECT_CMD_DISABLE, &EffectConversionHelperAidl::handleDisable},
+ {EFFECT_CMD_SET_AUDIO_SOURCE, &EffectConversionHelperAidl::handleSetAudioSource},
+ {EFFECT_CMD_SET_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
+ {EFFECT_CMD_SET_INPUT_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
+ {EFFECT_CMD_SET_VOLUME, &EffectConversionHelperAidl::handleSetVolume},
+ {EFFECT_CMD_OFFLOAD, &EffectConversionHelperAidl::handleSetOffload},
+ // Only visualizer support these commands, reuse of EFFECT_CMD_FIRST_PROPRIETARY
+ {VISUALIZER_CMD_CAPTURE, &EffectConversionHelperAidl::handleVisualizerCapture},
+ {VISUALIZER_CMD_MEASURE, &EffectConversionHelperAidl::handleVisualizerMeasure}};
+
+EffectConversionHelperAidl::EffectConversionHelperAidl(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId, const Descriptor& desc)
+ : mSessionId(sessionId),
+ mIoId(ioId),
+ mDesc(desc),
+ mEffect(std::move(effect)),
+ mIsInputStream(mDesc.common.flags.type == Flags::Type::PRE_PROC) {
+ mCommon.session = sessionId;
+ mCommon.ioHandle = ioId;
+ mCommon.input = mCommon.output = kDefaultAudioConfig;
+}
+
+status_t EffectConversionHelperAidl::handleCommand(uint32_t cmdCode, uint32_t cmdSize,
+ void* pCmdData, uint32_t* replySize,
+ void* pReplyData) {
+ const auto& handler = mCommandHandlerMap.find(cmdCode);
+ if (handler == mCommandHandlerMap.end() || !handler->second) {
+ ALOGE("%s handler for command %u doesn't exist", __func__, cmdCode);
+ return BAD_VALUE;
+ }
+ return (this->*handler->second)(cmdSize, pCmdData, replySize, pReplyData);
+}
+
+status_t EffectConversionHelperAidl::handleInit(uint32_t cmdSize __unused,
+ const void* pCmdData __unused, uint32_t* replySize,
+ void* pReplyData) {
+ if (!replySize || *replySize < sizeof(int) || !pReplyData) {
+ return BAD_VALUE;
+ }
+
+ return *(status_t*)pReplyData =
+ statusTFromBinderStatus(mEffect->open(mCommon, std::nullopt, &mOpenReturn));
+}
+
+status_t EffectConversionHelperAidl::handleSetParameter(uint32_t cmdSize, const void* pCmdData,
+ uint32_t* replySize, void* pReplyData) {
+ if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize ||
+ *replySize < sizeof(int) || !pReplyData) {
+ return BAD_VALUE;
+ }
+
+ auto reader = EffectParamReader(*(effect_param_t*)pCmdData);
+ if (!reader.validateCmdSize(cmdSize)) {
+ ALOGE("%s illegal param %s size %u", __func__, reader.toString().c_str(), cmdSize);
+ return BAD_VALUE;
+ }
+
+ status_t ret = setParameter(reader);
+ EffectParamWriter writer(*(effect_param_t*)pReplyData);
+ writer.setStatus(ret);
+ return *(status_t*)pReplyData = ret;
+}
+
+status_t EffectConversionHelperAidl::handleGetParameter(uint32_t cmdSize, const void* pCmdData,
+ uint32_t* replySize, void* pReplyData) {
+ if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize || !pReplyData) {
+ return BAD_VALUE;
+ }
+
+ const auto reader = EffectParamReader(*(effect_param_t*)pCmdData);
+ if (*replySize < sizeof(effect_param_t) + reader.getParameterSize()) {
+ ALOGE("%s illegal param %s, replySize %u", __func__, reader.toString().c_str(), *replySize);
+ return BAD_VALUE;
+ }
+
+ // copy effect_param_t and parameters
+ memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + reader.getParameterSize());
+ auto writer = EffectParamWriter(*(effect_param_t*)pReplyData);
+ status_t ret = getParameter(writer);
+ writer.finishValueWrite();
+ writer.setStatus(ret);
+ *replySize = writer.getTotalSize();
+ if (ret != OK) {
+ ALOGE("%s error ret %d, %s", __func__, ret, writer.toString().c_str());
+ }
+ return ret;
+}
+
+status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize, const void* pCmdData,
+ uint32_t* replySize, void* pReplyData) {
+ if (!replySize || *replySize != sizeof(int) || !pReplyData ||
+ cmdSize != sizeof(effect_config_t)) {
+ ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
+ pReplyData);
+ return BAD_VALUE;
+ }
+
+ effect_config_t* config = (effect_config_t*)pCmdData;
+ Parameter::Common aidlCommon = {
+ .session = mSessionId,
+ .ioHandle = mIoId,
+ .input = {.base = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
+ config->inputCfg, mIsInputStream))},
+ .output = {.base = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
+ config->outputCfg, mIsInputStream))}};
+
+ Parameter aidlParam = UNION_MAKE(Parameter, common, aidlCommon);
+
+ status_t ret = statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+ EffectParamWriter writer(*(effect_param_t*)pReplyData);
+ writer.setStatus(ret);
+ return ret;
+}
+
+status_t EffectConversionHelperAidl::handleGetConfig(uint32_t cmdSize __unused,
+ const void* pCmdData __unused,
+ uint32_t* replySize, void* pReplyData) {
+ if (!replySize || *replySize != sizeof(effect_config_t) || !pReplyData) {
+ ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ Parameter param;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(
+ Parameter::Id::make<Parameter::Id::commonTag>(Parameter::common), ¶m)));
+
+ const auto& common = param.get<Parameter::common>();
+ effect_config_t* pConfig = (effect_config_t*)pReplyData;
+ pConfig->inputCfg = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioConfigBase_buffer_config_t(common.input.base, true));
+ pConfig->outputCfg =
+ VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioConfigBase_buffer_config_t(
+ common.output.base, false));
+ mCommon = common;
+ return OK;
+}
+
+status_t EffectConversionHelperAidl::handleReset(uint32_t cmdSize __unused,
+ const void* pCmdData __unused, uint32_t* replySize,
+ void* pReplyData) {
+ if (!replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ return statusTFromBinderStatus(mEffect->command(CommandId::RESET));
+}
+
+status_t EffectConversionHelperAidl::handleEnable(uint32_t cmdSize __unused,
+ const void* pCmdData __unused,
+ uint32_t* replySize, void* pReplyData) {
+ if (!replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ return statusTFromBinderStatus(mEffect->command(CommandId::START));
+}
+
+status_t EffectConversionHelperAidl::handleDisable(uint32_t cmdSize __unused,
+ const void* pCmdData __unused,
+ uint32_t* replySize, void* pReplyData) {
+ if (!replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ return statusTFromBinderStatus(mEffect->command(CommandId::STOP));
+}
+
+status_t EffectConversionHelperAidl::handleSetAudioSource(uint32_t cmdSize, const void* pCmdData,
+ uint32_t* replySize, void* pReplyData) {
+ if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
+ pReplyData);
+ return BAD_VALUE;
+ }
+
+ audio_source_t source = *(audio_source_t*)pCmdData;
+ AudioSource aidlSource =
+ VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mEffect->setParameter(Parameter::make<Parameter::source>(aidlSource))));
+ return *static_cast<int32_t*>(pReplyData) = OK;
+}
+
+status_t EffectConversionHelperAidl::handleSetAudioMode(uint32_t cmdSize, const void* pCmdData,
+ uint32_t* replySize, void* pReplyData) {
+ if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
+ pReplyData);
+ return BAD_VALUE;
+ }
+ audio_mode_t mode = *(audio_mode_t *)pCmdData;
+ AudioMode aidlMode =
+ VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mEffect->setParameter(Parameter::make<Parameter::mode>(aidlMode))));
+ return *static_cast<int32_t*>(pReplyData) = OK;
+}
+
+status_t EffectConversionHelperAidl::handleSetDevice(uint32_t cmdSize, const void* pCmdData,
+ uint32_t* replySize, void* pReplyData) {
+ if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
+ pReplyData);
+ return BAD_VALUE;
+ }
+ // TODO: convert from audio_devices_t to std::vector<AudioDeviceDescription>
+ // const auto& legacyDevice = *(uint32_t*)(pCmdData);
+ std::vector<AudioDeviceDescription> aidlDevices;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mEffect->setParameter(Parameter::make<Parameter::deviceDescription>(aidlDevices))));
+ return *static_cast<int32_t*>(pReplyData) = OK;
+}
+status_t EffectConversionHelperAidl::handleSetVolume(uint32_t cmdSize, const void* pCmdData,
+ uint32_t* replySize __unused,
+ void* pReplyData __unused) {
+ if (cmdSize != 2 * sizeof(uint32_t) || !pCmdData) {
+ ALOGE("%s parameter invalid %u %p", __func__, cmdSize, pCmdData);
+ return BAD_VALUE;
+ }
+ Parameter::VolumeStereo volume = {.left = (float)(*(uint32_t*)pCmdData) / (1 << 24),
+ .right = (float)(*(uint32_t*)pCmdData + 1) / (1 << 24)};
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mEffect->setParameter(Parameter::make<Parameter::volumeStereo>(volume))));
+ return OK;
+}
+
+status_t EffectConversionHelperAidl::handleSetOffload(uint32_t cmdSize, const void* pCmdData,
+ uint32_t* replySize, void* pReplyData) {
+ if (cmdSize < sizeof(effect_offload_param_t) || !pCmdData || !replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
+ pReplyData);
+ return BAD_VALUE;
+ }
+ // TODO: handle this after effectproxy implemented in libaudiohal
+ return *static_cast<int32_t*>(pReplyData) = OK;
+}
+
+status_t EffectConversionHelperAidl::handleVisualizerCapture(uint32_t cmdSize __unused,
+ const void* pCmdData __unused,
+ uint32_t* replySize,
+ void* pReplyData) {
+ if (!replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ const auto& uuid = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(mDesc.common.id.type));
+ if (0 != memcmp(&uuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t))) {
+ ALOGE("%s visualizer command not supported by %s", __func__,
+ mDesc.common.id.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ return visualizerCapture(replySize, pReplyData);
+}
+
+status_t EffectConversionHelperAidl::handleVisualizerMeasure(uint32_t cmdSize __unused,
+ const void* pCmdData __unused,
+ uint32_t* replySize,
+ void* pReplyData) {
+ if (!replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ const auto& uuid = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(mDesc.common.id.type));
+ if (0 != memcmp(&uuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t))) {
+ ALOGE("%s visualizer command not supported by %s", __func__,
+ mDesc.common.id.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ return visualizerMeasure(replySize, pReplyData);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
new file mode 100644
index 0000000..54df1b8
--- /dev/null
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2023 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 <utils/Errors.h>
+
+#include <aidl/android/hardware/audio/effect/BpEffect.h>
+#include <system/audio_effect.h>
+#include <system/audio_effects/audio_effects_utils.h>
+
+namespace android {
+namespace effect {
+
+class EffectConversionHelperAidl {
+ public:
+ status_t handleCommand(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ virtual ~EffectConversionHelperAidl() {}
+ const ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn&
+ getEffectReturnParam() const {
+ return mOpenReturn;
+ }
+
+ protected:
+ const int32_t mSessionId;
+ const int32_t mIoId;
+ const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> mEffect;
+ // whether the effect is instantiated on an input stream
+ const bool mIsInputStream;
+ ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn mOpenReturn;
+ ::aidl::android::hardware::audio::effect::Parameter::Common mCommon;
+
+ EffectConversionHelperAidl(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc);
+
+ status_t handleSetParameter(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleGetParameter(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+
+ private:
+ const aidl::android::media::audio::common::AudioFormatDescription kDefaultFormatDescription = {
+ .type = aidl::android::media::audio::common::AudioFormatType::PCM,
+ .pcm = aidl::android::media::audio::common::PcmType::FLOAT_32_BIT};
+
+ static constexpr int kDefaultframeCount = 0x100;
+
+ using AudioChannelLayout = aidl::android::media::audio::common::AudioChannelLayout;
+ const aidl::android::media::audio::common::AudioConfig kDefaultAudioConfig = {
+ .base = {.sampleRate = 44100,
+ .channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ AudioChannelLayout::LAYOUT_STEREO),
+ .format = kDefaultFormatDescription},
+ .frameCount = kDefaultframeCount};
+ // command handler map
+ typedef status_t (EffectConversionHelperAidl::*CommandHandler)(uint32_t /* cmdSize */,
+ const void* /* pCmdData */,
+ uint32_t* /* replySize */,
+ void* /* pReplyData */);
+ static const std::map<uint32_t /* effect_command_e */, CommandHandler> mCommandHandlerMap;
+
+ status_t handleInit(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleSetConfig(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleGetConfig(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleEnable(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleDisable(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleReset(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleSetAudioSource(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleSetAudioMode(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleSetDevice(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleSetVolume(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleSetOffload(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleVisualizerCapture(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleVisualizerMeasure(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+
+ // implemented by conversion of each effect
+ virtual status_t setParameter(utils::EffectParamReader& param) = 0;
+ virtual status_t getParameter(utils::EffectParamWriter& param) = 0;
+ virtual status_t visualizerCapture(uint32_t* replySize __unused, void* pReplyData __unused) {
+ return BAD_VALUE;
+ }
+ virtual status_t visualizerMeasure(uint32_t* replySize __unused, void* pReplyData __unused) {
+ return BAD_VALUE;
+ }
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
new file mode 100644
index 0000000..0c19ac8
--- /dev/null
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2022 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 <cstddef>
+#define LOG_TAG "EffectHalAidl"
+//#define LOG_NDEBUG 0
+
+#include <memory>
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/AidlConversionUtil.h>
+#include <media/EffectsFactoryApi.h>
+#include <mediautils/TimeCheck.h>
+#include <system/audio.h>
+#include <system/audio_effects/effect_uuid.h>
+#include <utils/Log.h>
+
+#include "EffectHalAidl.h"
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+
+#include "effectsAidlConversion/AidlConversionAec.h"
+#include "effectsAidlConversion/AidlConversionAgc1.h"
+#include "effectsAidlConversion/AidlConversionAgc2.h"
+#include "effectsAidlConversion/AidlConversionBassBoost.h"
+#include "effectsAidlConversion/AidlConversionDownmix.h"
+#include "effectsAidlConversion/AidlConversionDynamicsProcessing.h"
+#include "effectsAidlConversion/AidlConversionEnvReverb.h"
+#include "effectsAidlConversion/AidlConversionEq.h"
+#include "effectsAidlConversion/AidlConversionHapticGenerator.h"
+#include "effectsAidlConversion/AidlConversionLoudnessEnhancer.h"
+#include "effectsAidlConversion/AidlConversionNoiseSuppression.h"
+#include "effectsAidlConversion/AidlConversionPresetReverb.h"
+#include "effectsAidlConversion/AidlConversionSpatializer.h"
+#include "effectsAidlConversion/AidlConversionVendorExtension.h"
+#include "effectsAidlConversion/AidlConversionVirtualizer.h"
+#include "effectsAidlConversion/AidlConversionVisualizer.h"
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Descriptor;
+using ::aidl::android::hardware::audio::effect::IEffect;
+using ::aidl::android::hardware::audio::effect::IFactory;
+
+namespace android {
+namespace effect {
+
+EffectHalAidl::EffectHalAidl(const std::shared_ptr<IFactory>& factory,
+ const std::shared_ptr<IEffect>& effect, uint64_t effectId,
+ int32_t sessionId, int32_t ioId, const Descriptor& desc)
+ : mFactory(factory),
+ mEffect(effect),
+ mEffectId(effectId),
+ mSessionId(sessionId),
+ mIoId(ioId),
+ mDesc(desc) {
+ createAidlConversion(effect, sessionId, ioId, desc);
+}
+
+EffectHalAidl::~EffectHalAidl() {
+ if (mFactory) {
+ mFactory->destroyEffect(mEffect);
+ }
+}
+
+status_t EffectHalAidl::createAidlConversion(
+ std::shared_ptr<IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const Descriptor& desc) {
+ const auto& typeUuid = desc.common.id.type;
+ ALOGI("%s create UUID %s", __func__, typeUuid.toString().c_str());
+ if (typeUuid ==
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidAcousticEchoCanceler()) {
+ mConversion =
+ std::make_unique<android::effect::AidlConversionAec>(effect, sessionId, ioId, desc);
+ } else if (typeUuid == ::aidl::android::hardware::audio::effect::
+ getEffectTypeUuidAutomaticGainControlV1()) {
+ mConversion = std::make_unique<android::effect::AidlConversionAgc1>(effect, sessionId, ioId,
+ desc);
+ } else if (typeUuid == ::aidl::android::hardware::audio::effect::
+ getEffectTypeUuidAutomaticGainControlV2()) {
+ mConversion = std::make_unique<android::effect::AidlConversionAgc2>(effect, sessionId, ioId,
+ desc);
+ } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost()) {
+ mConversion = std::make_unique<android::effect::AidlConversionBassBoost>(effect, sessionId,
+ ioId, desc);
+ } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix()) {
+ mConversion = std::make_unique<android::effect::AidlConversionDownmix>(effect, sessionId,
+ ioId, desc);
+ } else if (typeUuid ==
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing()) {
+ mConversion =
+ std::make_unique<android::effect::AidlConversionDp>(effect, sessionId, ioId, desc);
+ } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb()) {
+ mConversion = std::make_unique<android::effect::AidlConversionEnvReverb>(effect, sessionId,
+ ioId, desc);
+ } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer()) {
+ mConversion =
+ std::make_unique<android::effect::AidlConversionEq>(effect, sessionId, ioId, desc);
+ } else if (typeUuid ==
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator()) {
+ mConversion = std::make_unique<android::effect::AidlConversionHapticGenerator>(
+ effect, sessionId, ioId, desc);
+ } else if (typeUuid ==
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer()) {
+ mConversion = std::make_unique<android::effect::AidlConversionLoudnessEnhancer>(
+ effect, sessionId, ioId, desc);
+ } else if (typeUuid ==
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidNoiseSuppression()) {
+ mConversion = std::make_unique<android::effect::AidlConversionNoiseSuppression>(
+ effect, sessionId, ioId, desc);
+ } else if (typeUuid ==
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb()) {
+ mConversion = std::make_unique<android::effect::AidlConversionPresetReverb>(
+ effect, sessionId, ioId, desc);
+ } else if (typeUuid ==
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer()) {
+ mConversion = std::make_unique<android::effect::AidlConversionSpatializer>(
+ effect, sessionId, ioId, desc);
+ } else if (typeUuid ==
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer()) {
+ mConversion = std::make_unique<android::effect::AidlConversionVirtualizer>(
+ effect, sessionId, ioId, desc);
+ } else if (typeUuid ==
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer()) {
+ mConversion = std::make_unique<android::effect::AidlConversionVisualizer>(effect, sessionId,
+ ioId, desc);
+ } else {
+ // For unknown UUID, use vendor extension implementation
+ mConversion = std::make_unique<android::effect::AidlConversionVendorExtension>(
+ effect, sessionId, ioId, desc);
+ }
+ return OK;
+}
+
+status_t EffectHalAidl::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
+ mInBuffer = buffer;
+ return OK;
+}
+
+status_t EffectHalAidl::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
+ mOutBuffer = buffer;
+ return OK;
+}
+
+
+// write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ
+status_t EffectHalAidl::process() {
+ size_t available = mInputQ->availableToWrite();
+ size_t floatsToWrite = std::min(available, mInBuffer->getSize() / sizeof(float));
+ if (floatsToWrite == 0) {
+ ALOGW("%s not able to write, floats in buffer %zu, space in FMQ %zu", __func__,
+ mInBuffer->getSize() / sizeof(float), available);
+ return INVALID_OPERATION;
+ }
+ if (!mInputQ->write((float*)mInBuffer->ptr(), floatsToWrite)) {
+ ALOGW("%s failed to write %zu into inputQ", __func__, floatsToWrite);
+ return INVALID_OPERATION;
+ }
+
+ IEffect::Status retStatus{};
+ if (!mStatusQ->readBlocking(&retStatus, 1) || retStatus.status != OK ||
+ (size_t)retStatus.fmqConsumed != floatsToWrite || retStatus.fmqProduced == 0) {
+ ALOGW("%s read status failed: %s", __func__, retStatus.toString().c_str());
+ return INVALID_OPERATION;
+ }
+
+ available = mOutputQ->availableToRead();
+ size_t floatsToRead = std::min(available, mOutBuffer->getSize() / sizeof(float));
+ if (floatsToRead == 0) {
+ ALOGW("%s not able to read, buffer space %zu, floats in FMQ %zu", __func__,
+ mOutBuffer->getSize() / sizeof(float), available);
+ return INVALID_OPERATION;
+ }
+ if (!mOutputQ->read((float*)mOutBuffer->ptr(), floatsToRead)) {
+ ALOGW("%s failed to read %zu from outputQ", __func__, floatsToRead);
+ return INVALID_OPERATION;
+ }
+
+ ALOGD("%s %s consumed %zu produced %zu", __func__, mDesc.common.name.c_str(), floatsToWrite,
+ floatsToRead);
+ return OK;
+}
+
+// TODO: no one using, maybe deprecate this interface
+status_t EffectHalAidl::processReverse() {
+ ALOGW("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t EffectHalAidl::command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData,
+ uint32_t* replySize, void* pReplyData) {
+ TIME_CHECK();
+ if (!mConversion) {
+ ALOGE("%s can not handle command %d when conversion not exist", __func__, cmdCode);
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+ // update FMQs when effect open successfully
+ if (ret == OK && cmdCode == EFFECT_CMD_INIT) {
+ const auto& retParam = mConversion->getEffectReturnParam();
+ mStatusQ = std::make_unique<StatusMQ>(retParam.statusMQ);
+ mInputQ = std::make_unique<DataMQ>(retParam.inputDataMQ);
+ mOutputQ = std::make_unique<DataMQ>(retParam.outputDataMQ);
+ if (!mStatusQ->isValid() || !mInputQ->isValid() || !mOutputQ->isValid()) {
+ ALOGE("%s return with invalid FMQ", __func__);
+ return NO_INIT;
+ }
+ }
+
+ return ret;
+}
+
+status_t EffectHalAidl::getDescriptor(effect_descriptor_t* pDescriptor) {
+ TIME_CHECK();
+ if (pDescriptor == nullptr) {
+ ALOGE("%s null descriptor pointer", __func__);
+ return BAD_VALUE;
+ }
+ Descriptor aidlDesc;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getDescriptor(&aidlDesc)));
+
+ *pDescriptor = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(aidlDesc));
+ return OK;
+}
+
+status_t EffectHalAidl::close() {
+ TIME_CHECK();
+ return statusTFromBinderStatus(mEffect->close());
+}
+
+status_t EffectHalAidl::dump(int fd) {
+ TIME_CHECK();
+ return mEffect->dump(fd, nullptr, 0);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
new file mode 100644
index 0000000..194150d
--- /dev/null
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2023 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 <memory>
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <fmq/AidlMessageQueue.h>
+#include <media/audiohal/EffectHalInterface.h>
+#include <system/audio_effect.h>
+
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class EffectHalAidl : public EffectHalInterface {
+ public:
+ using StatusMQ = ::android::AidlMessageQueue<
+ ::aidl::android::hardware::audio::effect::IEffect::Status,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+ using DataMQ = ::android::AidlMessageQueue<
+ float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+
+ // Set the input buffer.
+ status_t setInBuffer(const sp<EffectBufferHalInterface>& buffer) override;
+
+ // Set the output buffer.
+ status_t setOutBuffer(const sp<EffectBufferHalInterface>& buffer) override;
+
+ // Effect process function.
+ status_t process() override;
+
+ // Process reverse stream function. This function is used to pass
+ // a reference stream to the effect engine.
+ status_t processReverse() override;
+
+ // Send a command and receive a response to/from effect engine.
+ status_t command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData, uint32_t* replySize,
+ void* pReplyData) override;
+
+ // Returns the effect descriptor.
+ status_t getDescriptor(effect_descriptor_t *pDescriptor) override;
+
+ // Free resources on the remote side.
+ status_t close() override;
+
+ // Whether it's a local implementation.
+ bool isLocal() const override { return false; }
+
+ status_t dump(int fd) override;
+
+ uint64_t effectId() const override { return mEffectId; }
+
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> getIEffect() const {
+ return mEffect;
+ }
+
+ // for TIME_CHECK
+ const std::string getClassName() const { return "EffectHalAidl"; }
+
+ private:
+ friend class sp<EffectHalAidl>;
+
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory> mFactory;
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> mEffect;
+ const uint64_t mEffectId;
+ const int32_t mSessionId;
+ const int32_t mIoId;
+ const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
+ std::unique_ptr<EffectConversionHelperAidl> mConversion;
+ std::unique_ptr<StatusMQ> mStatusQ;
+ std::unique_ptr<DataMQ> mInputQ, mOutputQ;
+
+ sp<EffectBufferHalInterface> mInBuffer, mOutBuffer;
+ effect_config_t mConfig;
+
+ status_t createAidlConversion(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc);
+ // Can not be constructed directly by clients.
+ EffectHalAidl(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory>& factory,
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& effect,
+ uint64_t effectId, int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc);
+ bool setEffectReverse(bool reverse);
+
+ // The destructor automatically releases the effect.
+ virtual ~EffectHalAidl();
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectHalHidl.cpp b/media/libaudiohal/impl/EffectHalHidl.cpp
index 3956a6c..7ecdbd2 100644
--- a/media/libaudiohal/impl/EffectHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectHalHidl.cpp
@@ -46,9 +46,6 @@
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::effect::CPP_VERSION;
-#define TIME_CHECK() auto timeCheck = \
- mediautils::makeTimeCheckStatsForClassMethod(getClassName(), __func__)
-
EffectHalHidl::EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId)
: EffectConversionHelperHidl("EffectHalHidl"),
mEffect(effect), mEffectId(effectId), mBuffersChanged(true), mEfGroup(nullptr) {
@@ -110,13 +107,13 @@
}
status_t EffectHalHidl::process() {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS));
}
status_t EffectHalHidl::processReverse() {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE));
}
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
new file mode 100644
index 0000000..f289f24
--- /dev/null
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2022 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 <algorithm>
+#include <cstdint>
+#include <memory>
+#define LOG_TAG "EffectsFactoryHalAidl"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <android/binder_manager.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio.h>
+#include <utils/Log.h>
+
+#include "EffectBufferHalAidl.h"
+#include "EffectHalAidl.h"
+#include "EffectsFactoryHalAidl.h"
+
+using ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid;
+using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::media::audio::common::AudioUuid;
+using android::detail::AudioHalVersionInfo;
+
+namespace android {
+namespace effect {
+
+EffectsFactoryHalAidl::EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFactory)
+ : mFactory(effectsFactory),
+ mHalVersion(AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, [this]() {
+ int32_t majorVersion = 0;
+ return (mFactory && mFactory->getInterfaceVersion(&majorVersion).isOk()) ? majorVersion
+ : 0;
+ }())) {
+ ALOG_ASSERT(effectsFactory != nullptr, "Provided IEffectsFactory service is NULL");
+}
+
+status_t EffectsFactoryHalAidl::queryNumberEffects(uint32_t *pNumEffects) {
+ if (pNumEffects == nullptr) {
+ return BAD_VALUE;
+ }
+
+ {
+ std::lock_guard lg(mLock);
+ RETURN_STATUS_IF_ERROR(queryEffectList_l());
+ *pNumEffects = mDescList->size();
+ }
+ ALOGI("%s %d", __func__, *pNumEffects);
+ return OK;
+}
+
+status_t EffectsFactoryHalAidl::getDescriptor(uint32_t index, effect_descriptor_t* pDescriptor) {
+ if (pDescriptor == nullptr) {
+ return BAD_VALUE;
+ }
+
+ std::lock_guard lg(mLock);
+ RETURN_STATUS_IF_ERROR(queryEffectList_l());
+
+ auto listSize = mDescList->size();
+ if (index >= listSize) {
+ ALOGE("%s index %d exceed size DescList %zd", __func__, index, listSize);
+ return INVALID_OPERATION;
+ }
+
+ *pDescriptor = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(mDescList->at(index)));
+ return OK;
+}
+
+status_t EffectsFactoryHalAidl::getDescriptor(const effect_uuid_t* halUuid,
+ effect_descriptor_t* pDescriptor) {
+ if (halUuid == nullptr || pDescriptor == nullptr) {
+ return BAD_VALUE;
+ }
+
+ AudioUuid uuid = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halUuid));
+ std::lock_guard lg(mLock);
+ return getHalDescriptorWithImplUuid_l(uuid, pDescriptor);
+}
+
+status_t EffectsFactoryHalAidl::getDescriptors(const effect_uuid_t* halType,
+ std::vector<effect_descriptor_t>* descriptors) {
+ if (halType == nullptr || descriptors == nullptr) {
+ return BAD_VALUE;
+ }
+
+ AudioUuid type = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halType));
+ std::lock_guard lg(mLock);
+ return getHalDescriptorWithTypeUuid_l(type, descriptors);
+}
+
+status_t EffectsFactoryHalAidl::createEffect(const effect_uuid_t* uuid, int32_t sessionId,
+ int32_t ioId, int32_t deviceId __unused,
+ sp<EffectHalInterface>* effect) {
+ if (uuid == nullptr || effect == nullptr) {
+ return BAD_VALUE;
+ }
+ if (sessionId == AUDIO_SESSION_DEVICE && ioId == AUDIO_IO_HANDLE_NONE) {
+ return INVALID_OPERATION;
+ }
+
+ ALOGI("%s session %d ioId %d", __func__, sessionId, ioId);
+
+ AudioUuid aidlUuid = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*uuid));
+ std::shared_ptr<IEffect> aidlEffect;
+ Descriptor desc;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mFactory->createEffect(aidlUuid, &aidlEffect)));
+ if (aidlEffect == nullptr) {
+ ALOGE("%s IFactory::createFactory failed UUID %s", __func__, aidlUuid.toString().c_str());
+ return NAME_NOT_FOUND;
+ }
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(aidlEffect->getDescriptor(&desc)));
+
+ uint64_t effectId;
+ {
+ std::lock_guard lg(mLock);
+ effectId = ++mEffectIdCounter;
+ }
+
+ *effect = sp<EffectHalAidl>::make(mFactory, aidlEffect, effectId, sessionId, ioId, desc);
+ return OK;
+}
+
+status_t EffectsFactoryHalAidl::dumpEffects(int fd) {
+ // TODO: add proxy dump here because AIDL service EffectFactory doesn't have proxy handle
+ return mFactory->dump(fd, nullptr, 0);
+}
+
+status_t EffectsFactoryHalAidl::allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) {
+ ALOGI("%s size %zu buffer %p", __func__, size, buffer);
+ return EffectBufferHalAidl::allocate(size, buffer);
+}
+
+status_t EffectsFactoryHalAidl::mirrorBuffer(void* external, size_t size,
+ sp<EffectBufferHalInterface>* buffer) {
+ ALOGI("%s extern %p size %zu buffer %p", __func__, external, size, buffer);
+ return EffectBufferHalAidl::mirror(external, size, buffer);
+}
+
+AudioHalVersionInfo EffectsFactoryHalAidl::getHalVersion() const {
+ return mHalVersion;
+}
+
+status_t EffectsFactoryHalAidl::queryEffectList_l() {
+ if (!mDescList) {
+ std::vector<Descriptor> list;
+ auto status = mFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &list);
+ if (!status.isOk()) {
+ ALOGE("%s IFactory::queryEffects failed %s", __func__, status.getDescription().c_str());
+ return status.getStatus();
+ }
+
+ mDescList = std::make_unique<std::vector<Descriptor>>(list);
+ }
+ return OK;
+}
+
+status_t EffectsFactoryHalAidl::getHalDescriptorWithImplUuid_l(const AudioUuid& uuid,
+ effect_descriptor_t* pDescriptor) {
+ if (pDescriptor == nullptr) {
+ return BAD_VALUE;
+ }
+ if (!mDescList) {
+ RETURN_STATUS_IF_ERROR(queryEffectList_l());
+ }
+
+ auto matchIt = std::find_if(mDescList->begin(), mDescList->end(),
+ [&](const auto& desc) { return desc.common.id.uuid == uuid; });
+ if (matchIt == mDescList->end()) {
+ ALOGE("%s UUID %s not found", __func__, uuid.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ *pDescriptor = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(*matchIt));
+ return OK;
+}
+
+status_t EffectsFactoryHalAidl::getHalDescriptorWithTypeUuid_l(
+ const AudioUuid& type, std::vector<effect_descriptor_t>* descriptors) {
+ if (descriptors == nullptr) {
+ return BAD_VALUE;
+ }
+ if (!mDescList) {
+ RETURN_STATUS_IF_ERROR(queryEffectList_l());
+ }
+ std::vector<Descriptor> result;
+ std::copy_if(mDescList->begin(), mDescList->end(), std::back_inserter(result),
+ [&](auto& desc) { return desc.common.id.type == type; });
+ if (result.size() == 0) {
+ ALOGE("%s type UUID %s not found", __func__, type.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ *descriptors = VALUE_OR_RETURN_STATUS(
+ aidl::android::convertContainer<std::vector<effect_descriptor_t>>(
+ result, ::aidl::android::aidl2legacy_Descriptor_effect_descriptor));
+ return OK;
+}
+
+} // namespace effect
+
+// When a shared library is built from a static library, even explicit
+// exports from a static library are optimized out unless actually used by
+// the shared library. See EffectsFactoryHalEntry.cpp.
+extern "C" void* createIEffectsFactoryImpl() {
+ auto serviceName = std::string(IFactory::descriptor) + "/default";
+ auto service = IFactory::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
+ if (!service) {
+ ALOGE("%s binder service %s not exist", __func__, serviceName.c_str());
+ return nullptr;
+ }
+ return new effect::EffectsFactoryHalAidl(service);
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
new file mode 100644
index 0000000..9c3643b
--- /dev/null
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 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 <cstddef>
+#include <memory>
+#include <mutex>
+
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <android-base/thread_annotations.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <system/thread_defs.h>
+
+namespace android {
+namespace effect {
+
+using namespace aidl::android::hardware::audio::effect;
+
+class EffectsFactoryHalAidl final : public EffectsFactoryHalInterface {
+ public:
+ explicit EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFactory);
+
+ // Returns the number of different effects in all loaded libraries.
+ status_t queryNumberEffects(uint32_t *pNumEffects) override;
+
+ // Returns a descriptor of the next available effect.
+ status_t getDescriptor(uint32_t index, effect_descriptor_t* pDescriptor) override;
+
+ status_t getDescriptor(const effect_uuid_t* pEffectUuid,
+ effect_descriptor_t* pDescriptor) override;
+
+ status_t getDescriptors(const effect_uuid_t* pEffectType,
+ std::vector<effect_descriptor_t>* descriptors) override;
+
+ // Creates an effect engine of the specified type.
+ // To release the effect engine, it is necessary to release references to the returned effect
+ // object.
+ status_t createEffect(const effect_uuid_t* pEffectUuid, int32_t sessionId, int32_t ioId,
+ int32_t deviceId, sp<EffectHalInterface>* effect) override;
+
+ status_t dumpEffects(int fd) override;
+
+ status_t allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override;
+ status_t mirrorBuffer(void* external, size_t size,
+ sp<EffectBufferHalInterface>* buffer) override;
+
+ detail::AudioHalVersionInfo getHalVersion() const override;
+
+ // for TIME_CHECK
+ const std::string getClassName() const { return "EffectHalAidl"; }
+
+ private:
+ std::mutex mLock;
+ const std::shared_ptr<IFactory> mFactory;
+ uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0; // Align with HIDL (0 is INVALID_ID)
+ std::unique_ptr<std::vector<Descriptor>> mDescList GUARDED_BY(mLock) = nullptr;
+ const detail::AudioHalVersionInfo mHalVersion;
+
+ virtual ~EffectsFactoryHalAidl() = default;
+ status_t queryEffectList_l() REQUIRES(mLock);
+ status_t getHalDescriptorWithImplUuid_l(
+ const aidl::android::media::audio::common::AudioUuid& uuid,
+ effect_descriptor_t* pDescriptor) REQUIRES(mLock);
+ status_t getHalDescriptorWithTypeUuid_l(
+ const aidl::android::media::audio::common::AudioUuid& type,
+ std::vector<effect_descriptor_t>* descriptors) REQUIRES(mLock);
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp b/media/libaudiohal/impl/EffectsFactoryHalEntry.cpp
similarity index 94%
rename from media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp
rename to media/libaudiohal/impl/EffectsFactoryHalEntry.cpp
index 2c6f2c6..f6ad99a 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalEntry.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "android/media/AudioHalVersion.h"
+
extern "C" void* createIEffectsFactoryImpl();
extern "C" __attribute__((visibility("default"))) void* createIEffectsFactory() {
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
index 3470380..172ebdf 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
@@ -31,6 +31,9 @@
#include "EffectHalHidl.h"
#include "EffectsFactoryHalHidl.h"
+#include "android/media/AudioHalVersion.h"
+
+using ::android::detail::AudioHalVersionInfo;
using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
using ::android::hardware::audio::effect::CPP_VERSION::implementation::EffectUtils;
using ::android::hardware::Return;
@@ -77,7 +80,7 @@
EffectsFactoryHalHidl::EffectsFactoryHalHidl(sp<IEffectsFactory> effectsFactory)
: EffectConversionHelperHidl("EffectsFactory"), mCache(new EffectDescriptorCache) {
ALOG_ASSERT(effectsFactory != nullptr, "Provided IEffectsFactory service is NULL");
- mEffectsFactory = effectsFactory;
+ mEffectsFactory = std::move(effectsFactory);
}
status_t EffectsFactoryHalHidl::queryNumberEffects(uint32_t *pNumEffects) {
@@ -221,11 +224,15 @@
return EffectBufferHalHidl::mirror(external, size, buffer);
}
+AudioHalVersionInfo EffectsFactoryHalHidl::getHalVersion() const {
+ return AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, MAJOR_VERSION, MINOR_VERSION);
+}
+
} // namespace effect
// When a shared library is built from a static library, even explicit
// exports from a static library are optimized out unless actually used by
-// the shared library. See EffectsFactoryHalHidlEntry.cpp.
+// the shared library. See EffectsFactoryHalEntry.cpp.
extern "C" void* createIEffectsFactoryImpl() {
auto service = hardware::audio::effect::CPP_VERSION::IEffectsFactory::getService();
return service ? new effect::EffectsFactoryHalHidl(service) : nullptr;
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.h b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
index 7ccddc6..9875154 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_HIDL_H
-#define ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_HIDL_H
+#pragma once
#include <memory>
@@ -32,39 +31,37 @@
class EffectDescriptorCache;
-class EffectsFactoryHalHidl : public EffectsFactoryHalInterface, public EffectConversionHelperHidl
-{
+class EffectsFactoryHalHidl final : public EffectsFactoryHalInterface,
+ public EffectConversionHelperHidl {
public:
EffectsFactoryHalHidl(sp<IEffectsFactory> effectsFactory);
// Returns the number of different effects in all loaded libraries.
- virtual status_t queryNumberEffects(uint32_t *pNumEffects);
+ status_t queryNumberEffects(uint32_t *pNumEffects) override;
// Returns a descriptor of the next available effect.
- virtual status_t getDescriptor(uint32_t index,
- effect_descriptor_t *pDescriptor);
+ status_t getDescriptor(uint32_t index, effect_descriptor_t* pDescriptor) override;
- virtual status_t getDescriptor(const effect_uuid_t *pEffectUuid,
- effect_descriptor_t *pDescriptor);
+ status_t getDescriptor(const effect_uuid_t* pEffectUuid,
+ effect_descriptor_t* pDescriptor) override;
- virtual status_t getDescriptors(const effect_uuid_t *pEffectType,
- std::vector<effect_descriptor_t> *descriptors);
+ status_t getDescriptors(const effect_uuid_t* pEffectType,
+ std::vector<effect_descriptor_t>* descriptors) override;
// Creates an effect engine of the specified type.
// To release the effect engine, it is necessary to release references
// to the returned effect object.
- virtual status_t createEffect(const effect_uuid_t *pEffectUuid,
- int32_t sessionId, int32_t ioId, int32_t deviceId,
- sp<EffectHalInterface> *effect);
+ status_t createEffect(const effect_uuid_t* pEffectUuid, int32_t sessionId, int32_t ioId,
+ int32_t deviceId, sp<EffectHalInterface>* effect) override;
- virtual status_t dumpEffects(int fd);
-
- virtual float getHalVersion() { return MAJOR_VERSION + (float)MINOR_VERSION / 10; }
+ status_t dumpEffects(int fd) override;
status_t allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override;
status_t mirrorBuffer(void* external, size_t size,
sp<EffectBufferHalInterface>* buffer) override;
+ android::detail::AudioHalVersionInfo getHalVersion() const override;
+
private:
sp<IEffectsFactory> mEffectsFactory;
std::unique_ptr<EffectDescriptorCache> mCache;
@@ -72,5 +69,3 @@
} // namespace effect
} // namespace android
-
-#endif // ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_HIDL_H
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
new file mode 100644
index 0000000..cbc1578
--- /dev/null
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -0,0 +1,940 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "StreamHalAidl"
+//#define LOG_NDEBUG 0
+
+#include <algorithm>
+#include <cstdint>
+
+#include <audio_utils/clock.h>
+#include <media/AidlConversion.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionUtil.h>
+#include <media/AudioParameter.h>
+#include <mediautils/TimeCheck.h>
+#include <system/audio.h>
+#include <utils/Log.h>
+
+#include "DeviceHalAidl.h"
+#include "StreamHalAidl.h"
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::common::PlaybackTrackMetadata;
+using ::aidl::android::hardware::audio::common::RecordTrackMetadata;
+using ::aidl::android::hardware::audio::core::IStreamCommon;
+using ::aidl::android::hardware::audio::core::IStreamIn;
+using ::aidl::android::hardware::audio::core::IStreamOut;
+using ::aidl::android::hardware::audio::core::StreamDescriptor;
+using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;
+
+namespace android {
+
+using HalCommand = StreamDescriptor::Command;
+namespace {
+template<HalCommand::Tag cmd> HalCommand makeHalCommand() {
+ return HalCommand::make<cmd>(::aidl::android::media::audio::common::Void{});
+}
+template<HalCommand::Tag cmd, typename T> HalCommand makeHalCommand(T data) {
+ return HalCommand::make<cmd>(data);
+}
+} // namespace
+
+// static
+template<class T>
+std::shared_ptr<IStreamCommon> StreamHalAidl::getStreamCommon(const std::shared_ptr<T>& stream) {
+ std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> streamCommon;
+ if (stream != nullptr) {
+ if (ndk::ScopedAStatus status = stream->getStreamCommon(&streamCommon);
+ !status.isOk()) {
+ ALOGE("%s: failed to retrieve IStreamCommon instance: %s", __func__,
+ status.getDescription().c_str());
+ }
+ }
+ return streamCommon;
+}
+
+StreamHalAidl::StreamHalAidl(
+ std::string_view className, bool isInput, const audio_config& config,
+ int32_t nominalLatency, StreamContextAidl&& context,
+ const std::shared_ptr<IStreamCommon>& stream)
+ : ConversionHelperAidl(className),
+ mIsInput(isInput),
+ mConfig(configToBase(config)),
+ mContext(std::move(context)),
+ mStream(stream) {
+ {
+ std::lock_guard l(mLock);
+ mLastReply.latencyMs = nominalLatency;
+ }
+ // Instrument audio signal power logging.
+ // Note: This assumes channel mask, format, and sample rate do not change after creation.
+ if (audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
+ /* mStreamPowerLog.isUserDebugOrEngBuild() && */
+ StreamHalAidl::getAudioProperties(&config) == NO_ERROR) {
+ mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format);
+ }
+}
+
+StreamHalAidl::~StreamHalAidl() {
+ if (mStream != nullptr) {
+ ndk::ScopedAStatus status = mStream->close();
+ ALOGE_IF(!status.isOk(), "%s: status %s", __func__, status.getDescription().c_str());
+ }
+}
+
+status_t StreamHalAidl::getBufferSize(size_t *size) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (size == nullptr) {
+ return BAD_VALUE;
+ }
+ if (mContext.getFrameSizeBytes() == 0 || mContext.getBufferSizeFrames() == 0 ||
+ !mStream) {
+ return NO_INIT;
+ }
+ *size = mContext.getBufferSizeBytes();
+ return OK;
+}
+
+status_t StreamHalAidl::getAudioProperties(audio_config_base_t *configBase) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (configBase == nullptr) {
+ return BAD_VALUE;
+ }
+ if (!mStream) return NO_INIT;
+ *configBase = mConfig;
+ return OK;
+}
+
+namespace {
+
+// 'action' must accept a value of type 'T' and return 'status_t'.
+// The function returns 'true' if the parameter was found, and the action has succeeded.
+// The function returns 'false' if the parameter was not found.
+// Any errors get propagated, if there are errors it means the parameter was found.
+template<typename T, typename F>
+error::Result<bool> filterOutAndProcessParameter(
+ AudioParameter& parameters, const String8& key, const F& action) {
+ if (parameters.containsKey(key)) {
+ T value;
+ status_t status = parameters.get(key, value);
+ if (status == OK) {
+ parameters.remove(key);
+ status = action(value);
+ if (status == OK) return true;
+ }
+ return base::unexpected(status);
+ }
+ return false;
+}
+
+} // namespace
+
+status_t StreamHalAidl::setParameters(const String8& kvPairs) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+
+ AudioParameter parameters(kvPairs);
+ ALOGD("%s: parameters: %s", __func__, parameters.toString().c_str());
+
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+ parameters, String8(AudioParameter::keyStreamHwAvSync),
+ [&](int hwAvSyncId) {
+ return statusTFromBinderStatus(mStream->updateHwAvSyncId(hwAvSyncId));
+ }));
+
+ ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: %s",
+ __func__, parameters.toString().c_str());
+ return OK;
+}
+
+status_t StreamHalAidl::getParameters(const String8& keys __unused, String8 *values) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ values->clear();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamHalAidl::getFrameSize(size_t *size) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (size == nullptr) {
+ return BAD_VALUE;
+ }
+ if (mContext.getFrameSizeBytes() == 0 || !mStream) {
+ return NO_INIT;
+ }
+ *size = mContext.getFrameSizeBytes();
+ return OK;
+}
+
+status_t StreamHalAidl::addEffect(sp<EffectHalInterface> effect __unused) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamHalAidl::removeEffect(sp<EffectHalInterface> effect __unused) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamHalAidl::standby() {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ const auto state = getState();
+ StreamDescriptor::Reply reply;
+ switch (state) {
+ case StreamDescriptor::State::ACTIVE:
+ if (status_t status = pause(&reply); status != OK) return status;
+ if (reply.state != StreamDescriptor::State::PAUSED) {
+ ALOGE("%s: unexpected stream state: %s (expected PAUSED)",
+ __func__, toString(reply.state).c_str());
+ return INVALID_OPERATION;
+ }
+ FALLTHROUGH_INTENDED;
+ case StreamDescriptor::State::PAUSED:
+ case StreamDescriptor::State::DRAIN_PAUSED:
+ if (mIsInput) return flush();
+ if (status_t status = flush(&reply); status != OK) return status;
+ if (reply.state != StreamDescriptor::State::IDLE) {
+ ALOGE("%s: unexpected stream state: %s (expected IDLE)",
+ __func__, toString(reply.state).c_str());
+ return INVALID_OPERATION;
+ }
+ FALLTHROUGH_INTENDED;
+ case StreamDescriptor::State::IDLE:
+ if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::standby>(),
+ &reply, true /*safeFromNonWorkerThread*/); status != OK) {
+ return status;
+ }
+ if (reply.state != StreamDescriptor::State::STANDBY) {
+ ALOGE("%s: unexpected stream state: %s (expected STANDBY)",
+ __func__, toString(reply.state).c_str());
+ return INVALID_OPERATION;
+ }
+ FALLTHROUGH_INTENDED;
+ case StreamDescriptor::State::STANDBY:
+ return OK;
+ default:
+ ALOGE("%s: not supported from %s stream state %s",
+ __func__, mIsInput ? "input" : "output", toString(state).c_str());
+ return INVALID_OPERATION;
+ }
+}
+
+status_t StreamHalAidl::dump(int fd, const Vector<String16>& args) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ return mStream->dump(fd, Args(args).args(), args.size());
+}
+
+status_t StreamHalAidl::start() {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamHalAidl::stop() {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamHalAidl::getLatency(uint32_t *latency) {
+ ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (!mStream) return NO_INIT;
+ StreamDescriptor::Reply reply;
+ if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
+ return status;
+ }
+ *latency = std::max<int32_t>(0, reply.latencyMs);
+ return OK;
+}
+
+status_t StreamHalAidl::getObservablePosition(int64_t *frames, int64_t *timestamp) {
+ ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (!mStream) return NO_INIT;
+ StreamDescriptor::Reply reply;
+ if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
+ return status;
+ }
+ *frames = reply.observable.frames;
+ *timestamp = reply.observable.timeNs;
+ return OK;
+}
+
+status_t StreamHalAidl::getXruns(int32_t *frames) {
+ ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (!mStream) return NO_INIT;
+ StreamDescriptor::Reply reply;
+ if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
+ return status;
+ }
+ *frames = reply.xrunFrames;
+ return OK;
+}
+
+status_t StreamHalAidl::transfer(void *buffer, size_t bytes, size_t *transferred) {
+ ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
+ if (!mStream || mContext.getDataMQ() == nullptr) return NO_INIT;
+ mWorkerTid.store(gettid(), std::memory_order_release);
+ // Switch the stream into an active state if needed.
+ // Note: in future we may add support for priming the audio pipeline
+ // with data prior to enabling output (thus we can issue a "burst" command in the "standby"
+ // stream state), however this scenario wasn't supported by the HIDL HAL.
+ if (getState() == StreamDescriptor::State::STANDBY) {
+ StreamDescriptor::Reply reply;
+ if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply);
+ status != OK) {
+ return status;
+ }
+ if (reply.state != StreamDescriptor::State::IDLE) {
+ ALOGE("%s: failed to get the stream out of standby, actual state: %s",
+ __func__, toString(reply.state).c_str());
+ return INVALID_OPERATION;
+ }
+ }
+ if (!mIsInput) {
+ bytes = std::min(bytes, mContext.getDataMQ()->availableToWrite());
+ }
+ StreamDescriptor::Command burst =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(bytes);
+ if (!mIsInput) {
+ if (!mContext.getDataMQ()->write(static_cast<const int8_t*>(buffer), bytes)) {
+ ALOGE("%s: failed to write %zu bytes to data MQ", __func__, bytes);
+ return NOT_ENOUGH_DATA;
+ }
+ }
+ StreamDescriptor::Reply reply;
+ if (status_t status = sendCommand(burst, &reply); status != OK) {
+ return status;
+ }
+ *transferred = reply.fmqByteCount;
+ if (mIsInput) {
+ LOG_ALWAYS_FATAL_IF(*transferred > bytes,
+ "%s: HAL module read %zu bytes, which exceeds requested count %zu",
+ __func__, *transferred, bytes);
+ if (auto toRead = mContext.getDataMQ()->availableToRead();
+ toRead != 0 && !mContext.getDataMQ()->read(static_cast<int8_t*>(buffer), toRead)) {
+ ALOGE("%s: failed to read %zu bytes to data MQ", __func__, toRead);
+ return NOT_ENOUGH_DATA;
+ }
+ }
+ mStreamPowerLog.log(buffer, *transferred);
+ return OK;
+}
+
+status_t StreamHalAidl::pause(StreamDescriptor::Reply* reply) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ return sendCommand(makeHalCommand<HalCommand::Tag::pause>(), reply,
+ true /*safeFromNonWorkerThread*/); // The workers stops its I/O activity first.
+}
+
+status_t StreamHalAidl::resume(StreamDescriptor::Reply* reply) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ if (mIsInput) {
+ return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), reply);
+ } else {
+ if (mContext.isAsynchronous()) {
+ // Handle pause-flush-resume sequence. 'flush' from PAUSED goes to
+ // IDLE. We move here from IDLE to ACTIVE (same as 'start' from PAUSED).
+ const auto state = getState();
+ if (state == StreamDescriptor::State::IDLE) {
+ StreamDescriptor::Reply localReply{};
+ StreamDescriptor::Reply* innerReply = reply ?: &localReply;
+ if (status_t status =
+ sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), innerReply);
+ status != OK) {
+ return status;
+ }
+ if (innerReply->state != StreamDescriptor::State::ACTIVE) {
+ ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
+ __func__, toString(innerReply->state).c_str());
+ return INVALID_OPERATION;
+ }
+ return OK;
+ }
+ }
+ return sendCommand(makeHalCommand<HalCommand::Tag::start>(), reply);
+ }
+}
+
+status_t StreamHalAidl::drain(bool earlyNotify, StreamDescriptor::Reply* reply) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ return sendCommand(makeHalCommand<HalCommand::Tag::drain>(
+ mIsInput ? StreamDescriptor::DrainMode::DRAIN_UNSPECIFIED :
+ earlyNotify ? StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY :
+ StreamDescriptor::DrainMode::DRAIN_ALL), reply,
+ true /*safeFromNonWorkerThread*/);
+}
+
+status_t StreamHalAidl::flush(StreamDescriptor::Reply* reply) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ return sendCommand(makeHalCommand<HalCommand::Tag::flush>(), reply,
+ true /*safeFromNonWorkerThread*/); // The workers stops its I/O activity first.
+}
+
+status_t StreamHalAidl::exit() {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
+ struct audio_mmap_buffer_info *info __unused) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position __unused) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamHalAidl::setHalThreadPriority(int priority __unused) {
+ // Obsolete, must be done by the HAL module.
+ return OK;
+}
+
+status_t StreamHalAidl::getHalPid(pid_t *pid __unused) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+bool StreamHalAidl::requestHalThreadPriority(pid_t threadPid __unused, pid_t threadId __unused) {
+ // Obsolete, must be done by the HAL module.
+ return true;
+}
+
+status_t StreamHalAidl::legacyCreateAudioPatch(const struct audio_port_config& port __unused,
+ std::optional<audio_source_t> source __unused,
+ audio_devices_t type __unused) {
+ // Obsolete since 'DeviceHalAidl.supportsAudioPatches' always returns 'true'.
+ return INVALID_OPERATION;
+}
+
+status_t StreamHalAidl::legacyReleaseAudioPatch() {
+ // Obsolete since 'DeviceHalAidl.supportsAudioPatches' always returns 'true'.
+ return INVALID_OPERATION;
+}
+
+status_t StreamHalAidl::sendCommand(
+ const ::aidl::android::hardware::audio::core::StreamDescriptor::Command &command,
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply,
+ bool safeFromNonWorkerThread) {
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
+ if (!safeFromNonWorkerThread) {
+ const pid_t workerTid = mWorkerTid.load(std::memory_order_acquire);
+ LOG_ALWAYS_FATAL_IF(workerTid != gettid(),
+ "%s %s: must be invoked from the worker thread (%d)",
+ __func__, command.toString().c_str(), workerTid);
+ }
+ if (!mContext.getCommandMQ()->writeBlocking(&command, 1)) {
+ ALOGE("%s: failed to write command %s to MQ", __func__, command.toString().c_str());
+ return NOT_ENOUGH_DATA;
+ }
+ StreamDescriptor::Reply localReply{};
+ if (reply == nullptr) {
+ reply = &localReply;
+ }
+ if (!mContext.getReplyMQ()->readBlocking(reply, 1)) {
+ ALOGE("%s: failed to read from reply MQ, command %s", __func__, command.toString().c_str());
+ return NOT_ENOUGH_DATA;
+ }
+ {
+ std::lock_guard l(mLock);
+ mLastReply = *reply;
+ }
+ switch (reply->status) {
+ case STATUS_OK: return OK;
+ case STATUS_BAD_VALUE: return BAD_VALUE;
+ case STATUS_INVALID_OPERATION: return INVALID_OPERATION;
+ case STATUS_NOT_ENOUGH_DATA: return NOT_ENOUGH_DATA;
+ default:
+ ALOGE("%s: unexpected status %d returned for command %s",
+ __func__, reply->status, command.toString().c_str());
+ return INVALID_OPERATION;
+ }
+}
+
+status_t StreamHalAidl::updateCountersIfNeeded(
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply) {
+ if (mWorkerTid.load(std::memory_order_acquire) == gettid()) {
+ if (const auto state = getState(); state != StreamDescriptor::State::ACTIVE &&
+ state != StreamDescriptor::State::DRAINING &&
+ state != StreamDescriptor::State::TRANSFERRING) {
+ return sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), reply);
+ }
+ }
+ if (reply != nullptr) {
+ std::lock_guard l(mLock);
+ *reply = mLastReply;
+ }
+ return OK;
+}
+
+// static
+ConversionResult<::aidl::android::hardware::audio::common::SourceMetadata>
+StreamOutHalAidl::legacy2aidl_SourceMetadata(const StreamOutHalInterface::SourceMetadata& legacy) {
+ ::aidl::android::hardware::audio::common::SourceMetadata aidl;
+ aidl.tracks = VALUE_OR_RETURN(
+ ::aidl::android::convertContainer<std::vector<PlaybackTrackMetadata>>(
+ legacy.tracks,
+ ::aidl::android::legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata));
+ return aidl;
+}
+
+StreamOutHalAidl::StreamOutHalAidl(
+ const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
+ const std::shared_ptr<IStreamOut>& stream, const sp<CallbackBroker>& callbackBroker)
+ : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config, nominalLatency,
+ std::move(context), getStreamCommon(stream)),
+ mStream(stream), mCallbackBroker(callbackBroker) {
+ // Initialize the offload metadata
+ mOffloadMetadata.sampleRate = static_cast<int32_t>(config.sample_rate);
+ mOffloadMetadata.channelMask = VALUE_OR_FATAL(
+ ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+ config.channel_mask, false));
+ mOffloadMetadata.averageBitRatePerSecond = static_cast<int32_t>(config.offload_info.bit_rate);
+}
+
+StreamOutHalAidl::~StreamOutHalAidl() {
+ if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+ broker->clearCallbacks(this);
+ }
+}
+
+status_t StreamOutHalAidl::setParameters(const String8& kvPairs) {
+ if (!mStream) return NO_INIT;
+
+ AudioParameter parameters(kvPairs);
+ ALOGD("%s parameters: %s", __func__, parameters.toString().c_str());
+
+ if (status_t status = filterAndUpdateOffloadMetadata(parameters); status != OK) {
+ ALOGW("%s filtering or updating offload metadata failed: %d", __func__, status);
+ }
+
+ return StreamHalAidl::setParameters(parameters.toString());
+}
+
+status_t StreamOutHalAidl::getLatency(uint32_t *latency) {
+ return StreamHalAidl::getLatency(latency);
+}
+
+status_t StreamOutHalAidl::setVolume(float left, float right) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ return statusTFromBinderStatus(mStream->setHwVolume({left, right}));
+}
+
+status_t StreamOutHalAidl::selectPresentation(int presentationId __unused, int programId __unused) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamOutHalAidl::write(const void *buffer, size_t bytes, size_t *written) {
+ if (buffer == nullptr || written == nullptr) {
+ return BAD_VALUE;
+ }
+ // For the output scenario, 'transfer' does not modify the buffer.
+ return transfer(const_cast<void*>(buffer), bytes, written);
+}
+
+status_t StreamOutHalAidl::getRenderPosition(uint32_t *dspFrames) {
+ if (dspFrames == nullptr) {
+ return BAD_VALUE;
+ }
+ int64_t aidlFrames = 0, aidlTimestamp = 0;
+ if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
+ return OK;
+ }
+ *dspFrames = std::clamp<int64_t>(aidlFrames, 0, UINT32_MAX);
+ return OK;
+}
+
+status_t StreamOutHalAidl::getNextWriteTimestamp(int64_t *timestamp __unused) {
+ // Obsolete, use getPresentationPosition.
+ return INVALID_OPERATION;
+}
+
+status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ if (!mContext.isAsynchronous()) {
+ ALOGE("%s: the callback is intended for asynchronous streams only", __func__);
+ return INVALID_OPERATION;
+ }
+ if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+ if (auto cb = callback.promote(); cb != nullptr) {
+ broker->setStreamOutCallback(this, cb);
+ } else {
+ // It is expected that the framework never passes a null pointer.
+ // In the AIDL model callbacks can't be "unregistered".
+ LOG_ALWAYS_FATAL("%s: received an expired or null callback pointer", __func__);
+ }
+ }
+ return OK;
+}
+
+status_t StreamOutHalAidl::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
+ if (supportsPause == nullptr || supportsResume == nullptr) {
+ return BAD_VALUE;
+ }
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ *supportsPause = *supportsResume = true;
+ return OK;
+}
+
+status_t StreamOutHalAidl::pause() {
+ return StreamHalAidl::pause();
+}
+
+status_t StreamOutHalAidl::resume() {
+ return StreamHalAidl::resume();
+}
+
+status_t StreamOutHalAidl::supportsDrain(bool *supportsDrain) {
+ if (supportsDrain == nullptr) {
+ return BAD_VALUE;
+ }
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ *supportsDrain = true;
+ return OK;
+}
+
+status_t StreamOutHalAidl::drain(bool earlyNotify) {
+ return StreamHalAidl::drain(earlyNotify);
+}
+
+status_t StreamOutHalAidl::flush() {
+ return StreamHalAidl::flush();
+}
+
+status_t StreamOutHalAidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
+ if (frames == nullptr || timestamp == nullptr) {
+ return BAD_VALUE;
+ }
+ int64_t aidlFrames = 0, aidlTimestamp = 0;
+ if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
+ return status;
+ }
+ *frames = std::max<int64_t>(0, aidlFrames);
+ timestamp->tv_sec = aidlTimestamp / NANOS_PER_SECOND;
+ timestamp->tv_nsec = aidlTimestamp - timestamp->tv_sec * NANOS_PER_SECOND;
+ return OK;
+}
+
+status_t StreamOutHalAidl::updateSourceMetadata(
+ const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ::aidl::android::hardware::audio::common::SourceMetadata aidlMetadata =
+ VALUE_OR_RETURN_STATUS(legacy2aidl_SourceMetadata(sourceMetadata));
+ return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
+}
+
+status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB __unused) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamOutHalAidl::getPlaybackRateParameters(
+ audio_playback_rate_t* playbackRate __unused) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return BAD_VALUE;
+}
+
+status_t StreamOutHalAidl::setPlaybackRateParameters(
+ const audio_playback_rate_t& playbackRate __unused) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return BAD_VALUE;
+}
+
+status_t StreamOutHalAidl::setEventCallback(
+ const sp<StreamOutHalInterfaceEventCallback>& callback) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+ broker->setStreamOutEventCallback(this, callback);
+ }
+ return OK;
+}
+
+status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode __unused) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+};
+
+status_t StreamOutHalAidl::getRecommendedLatencyModes(
+ std::vector<audio_latency_mode_t> *modes __unused) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+};
+
+status_t StreamOutHalAidl::setLatencyModeCallback(
+ const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+ broker->setStreamOutLatencyModeCallback(this, callback);
+ }
+ return OK;
+};
+
+status_t StreamOutHalAidl::exit() {
+ return StreamHalAidl::exit();
+}
+
+status_t StreamOutHalAidl::filterAndUpdateOffloadMetadata(AudioParameter ¶meters) {
+ TIME_CHECK();
+ bool updateMetadata = false;
+ if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+ parameters, String8(AudioParameter::keyOffloadCodecAverageBitRate),
+ [&](int value) {
+ return value > 0 ?
+ mOffloadMetadata.averageBitRatePerSecond = value, OK : BAD_VALUE;
+ }))) {
+ updateMetadata = true;
+ }
+ if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+ parameters, String8(AudioParameter::keyOffloadCodecSampleRate),
+ [&](int value) {
+ return value > 0 ? mOffloadMetadata.sampleRate = value, OK : BAD_VALUE;
+ }))) {
+ updateMetadata = true;
+ }
+ if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+ parameters, String8(AudioParameter::keyOffloadCodecChannels),
+ [&](int value) -> status_t {
+ if (value > 0) {
+ audio_channel_mask_t channel_mask = audio_channel_out_mask_from_count(
+ static_cast<uint32_t>(value));
+ if (channel_mask == AUDIO_CHANNEL_INVALID) return BAD_VALUE;
+ mOffloadMetadata.channelMask = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+ channel_mask, false /*isInput*/));
+ }
+ return BAD_VALUE;
+ }))) {
+ updateMetadata = true;
+ }
+ if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+ parameters, String8(AudioParameter::keyOffloadCodecDelaySamples),
+ [&](int value) {
+ // The legacy keys are misnamed, the value is in frames.
+ return value > 0 ? mOffloadMetadata.delayFrames = value, OK : BAD_VALUE;
+ }))) {
+ updateMetadata = true;
+ }
+ if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+ parameters, String8(AudioParameter::keyOffloadCodecPaddingSamples),
+ [&](int value) {
+ // The legacy keys are misnamed, the value is in frames.
+ return value > 0 ? mOffloadMetadata.paddingFrames = value, OK : BAD_VALUE;
+ }))) {
+ updateMetadata = true;
+ }
+ if (updateMetadata) {
+ ALOGD("%s set offload metadata %s", __func__, mOffloadMetadata.toString().c_str());
+ if (status_t status = statusTFromBinderStatus(
+ mStream->updateOffloadMetadata(mOffloadMetadata)); status != OK) {
+ ALOGE("%s: updateOffloadMetadata failed %d", __func__, status);
+ return status;
+ }
+ }
+ return OK;
+}
+
+// static
+ConversionResult<::aidl::android::hardware::audio::common::SinkMetadata>
+StreamInHalAidl::legacy2aidl_SinkMetadata(const StreamInHalInterface::SinkMetadata& legacy) {
+ ::aidl::android::hardware::audio::common::SinkMetadata aidl;
+ aidl.tracks = VALUE_OR_RETURN(
+ ::aidl::android::convertContainer<std::vector<RecordTrackMetadata>>(
+ legacy.tracks,
+ ::aidl::android::legacy2aidl_record_track_metadata_v7_RecordTrackMetadata));
+ return aidl;
+}
+
+StreamInHalAidl::StreamInHalAidl(
+ const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
+ const std::shared_ptr<IStreamIn>& stream, const sp<MicrophoneInfoProvider>& micInfoProvider)
+ : StreamHalAidl("StreamInHalAidl", true /*isInput*/, config, nominalLatency,
+ std::move(context), getStreamCommon(stream)),
+ mStream(stream), mMicInfoProvider(micInfoProvider) {}
+
+status_t StreamInHalAidl::setGain(float gain __unused) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamInHalAidl::read(void *buffer, size_t bytes, size_t *read) {
+ if (buffer == nullptr || read == nullptr) {
+ return BAD_VALUE;
+ }
+ return transfer(buffer, bytes, read);
+}
+
+status_t StreamInHalAidl::getInputFramesLost(uint32_t *framesLost) {
+ if (framesLost == nullptr) {
+ return BAD_VALUE;
+ }
+ int32_t aidlXruns = 0;
+ if (status_t status = getXruns(&aidlXruns); status != OK) {
+ return status;
+ }
+ *framesLost = std::max<int32_t>(0, aidlXruns);
+ return OK;
+}
+
+status_t StreamInHalAidl::getCapturePosition(int64_t *frames, int64_t *time) {
+ if (frames == nullptr || time == nullptr) {
+ return BAD_VALUE;
+ }
+ return getObservablePosition(frames, time);
+}
+
+status_t StreamInHalAidl::getActiveMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) {
+ if (!microphones) {
+ return BAD_VALUE;
+ }
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ sp<MicrophoneInfoProvider> micInfoProvider = mMicInfoProvider.promote();
+ if (!micInfoProvider) return NO_INIT;
+ auto staticInfo = micInfoProvider->getMicrophoneInfo();
+ if (!staticInfo) return INVALID_OPERATION;
+ std::vector<MicrophoneDynamicInfo> dynamicInfo;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getActiveMicrophones(&dynamicInfo)));
+ std::vector<media::MicrophoneInfoFw> result;
+ result.reserve(dynamicInfo.size());
+ for (const auto& d : dynamicInfo) {
+ const auto staticInfoIt = std::find_if(staticInfo->begin(), staticInfo->end(),
+ [&](const auto& s) { return s.id == d.id; });
+ if (staticInfoIt != staticInfo->end()) {
+ // Convert into the c++ backend type from the ndk backend type via the legacy structure.
+ audio_microphone_characteristic_t legacy = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t(
+ *staticInfoIt, d));
+ media::MicrophoneInfoFw info = VALUE_OR_RETURN_STATUS(
+ ::android::legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(
+ legacy));
+ // Note: info.portId is not filled because it's a bit of framework info.
+ result.push_back(std::move(info));
+ } else {
+ ALOGE("%s: no static info for active microphone with id '%s'", __func__, d.id.c_str());
+ }
+ }
+ *microphones = std::move(result);
+ return OK;
+}
+
+status_t StreamInHalAidl::updateSinkMetadata(
+ const StreamInHalInterface::SinkMetadata& sinkMetadata) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ::aidl::android::hardware::audio::common::SinkMetadata aidlMetadata =
+ VALUE_OR_RETURN_STATUS(legacy2aidl_SinkMetadata(sinkMetadata));
+ return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
+}
+
+status_t StreamInHalAidl::setPreferredMicrophoneDirection(
+ audio_microphone_direction_t direction __unused) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
new file mode 100644
index 0000000..157e8bb
--- /dev/null
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2023 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 <atomic>
+#include <memory>
+#include <mutex>
+#include <string_view>
+
+#include <aidl/android/hardware/audio/common/AudioOffloadMetadata.h>
+#include <aidl/android/hardware/audio/core/BpStreamCommon.h>
+#include <aidl/android/hardware/audio/core/BpStreamIn.h>
+#include <aidl/android/hardware/audio/core/BpStreamOut.h>
+#include <fmq/AidlMessageQueue.h>
+#include <media/audiohal/EffectHalInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
+#include <media/AudioParameter.h>
+
+#include "ConversionHelperAidl.h"
+#include "StreamPowerLog.h"
+
+using ::aidl::android::hardware::audio::common::AudioOffloadMetadata;
+
+namespace android {
+
+class StreamContextAidl {
+ public:
+ typedef AidlMessageQueue<::aidl::android::hardware::audio::core::StreamDescriptor::Command,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> CommandMQ;
+ typedef AidlMessageQueue<::aidl::android::hardware::audio::core::StreamDescriptor::Reply,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> ReplyMQ;
+ typedef AidlMessageQueue<int8_t,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;
+
+ explicit StreamContextAidl(
+ const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
+ bool isAsynchronous)
+ : mFrameSizeBytes(descriptor.frameSizeBytes),
+ mCommandMQ(new CommandMQ(descriptor.command)),
+ mReplyMQ(new ReplyMQ(descriptor.reply)),
+ mBufferSizeFrames(descriptor.bufferSizeFrames),
+ mDataMQ(maybeCreateDataMQ(descriptor)),
+ mIsAsynchronous(isAsynchronous) {}
+ StreamContextAidl(StreamContextAidl&& other) :
+ mFrameSizeBytes(other.mFrameSizeBytes),
+ mCommandMQ(std::move(other.mCommandMQ)),
+ mReplyMQ(std::move(other.mReplyMQ)),
+ mBufferSizeFrames(other.mBufferSizeFrames),
+ mDataMQ(std::move(other.mDataMQ)),
+ mIsAsynchronous(other.mIsAsynchronous) {}
+ StreamContextAidl& operator=(StreamContextAidl&& other) {
+ mFrameSizeBytes = other.mFrameSizeBytes;
+ mCommandMQ = std::move(other.mCommandMQ);
+ mReplyMQ = std::move(other.mReplyMQ);
+ mBufferSizeFrames = other.mBufferSizeFrames;
+ mDataMQ = std::move(other.mDataMQ);
+ mIsAsynchronous = other.mIsAsynchronous;
+ return *this;
+ }
+ bool isValid() const {
+ return mFrameSizeBytes != 0 &&
+ mCommandMQ != nullptr && mCommandMQ->isValid() &&
+ mReplyMQ != nullptr && mReplyMQ->isValid() &&
+ (mDataMQ != nullptr || (
+ mDataMQ->isValid() &&
+ mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() >=
+ mFrameSizeBytes * mBufferSizeFrames));
+ }
+ size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; }
+ size_t getBufferSizeFrames() const { return mBufferSizeFrames; }
+ CommandMQ* getCommandMQ() const { return mCommandMQ.get(); }
+ DataMQ* getDataMQ() const { return mDataMQ.get(); }
+ size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
+ ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
+ bool isAsynchronous() const { return mIsAsynchronous; }
+
+ private:
+ static std::unique_ptr<DataMQ> maybeCreateDataMQ(
+ const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
+ using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag;
+ if (descriptor.audio.getTag() == Tag::fmq) {
+ return std::make_unique<DataMQ>(descriptor.audio.get<Tag::fmq>());
+ }
+ return nullptr;
+ }
+
+ size_t mFrameSizeBytes;
+ std::unique_ptr<CommandMQ> mCommandMQ;
+ std::unique_ptr<ReplyMQ> mReplyMQ;
+ size_t mBufferSizeFrames;
+ std::unique_ptr<DataMQ> mDataMQ;
+ bool mIsAsynchronous;
+};
+
+class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelperAidl {
+ public:
+ // Return size of input/output buffer in bytes for this stream - eg. 4800.
+ status_t getBufferSize(size_t *size) override;
+
+ // Return the base configuration of the stream:
+ // - channel mask;
+ // - format - e.g. AUDIO_FORMAT_PCM_16_BIT;
+ // - sampling rate in Hz - eg. 44100.
+ status_t getAudioProperties(audio_config_base_t *configBase) override;
+
+ // Set audio stream parameters.
+ status_t setParameters(const String8& kvPairs) override;
+
+ // Get audio stream parameters.
+ status_t getParameters(const String8& keys, String8 *values) override;
+
+ // Return the frame size (number of bytes per sample) of a stream.
+ status_t getFrameSize(size_t *size) override;
+
+ // Add or remove the effect on the stream.
+ status_t addEffect(sp<EffectHalInterface> effect) override;
+ status_t removeEffect(sp<EffectHalInterface> effect) override;
+
+ // Put the audio hardware input/output into standby mode.
+ status_t standby() override;
+
+ status_t dump(int fd, const Vector<String16>& args) override;
+
+ // Start a stream operating in mmap mode.
+ status_t start() override;
+
+ // Stop a stream operating in mmap mode.
+ status_t stop() override;
+
+ // Retrieve information on the data buffer in mmap mode.
+ status_t createMmapBuffer(int32_t minSizeFrames,
+ struct audio_mmap_buffer_info *info) override;
+
+ // Get current read/write position in the mmap buffer
+ status_t getMmapPosition(struct audio_mmap_position *position) override;
+
+ // Set the priority of the thread that interacts with the HAL
+ // (must match the priority of the audioflinger's thread that calls 'read' / 'write')
+ status_t setHalThreadPriority(int priority) override;
+
+ status_t legacyCreateAudioPatch(const struct audio_port_config& port,
+ std::optional<audio_source_t> source,
+ audio_devices_t type) override;
+
+ status_t legacyReleaseAudioPatch() override;
+
+ protected:
+ template<class T>
+ static std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> getStreamCommon(
+ const std::shared_ptr<T>& stream);
+
+ // Subclasses can not be constructed directly by clients.
+ StreamHalAidl(std::string_view className,
+ bool isInput,
+ const audio_config& config,
+ int32_t nominalLatency,
+ StreamContextAidl&& context,
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>& stream);
+
+ ~StreamHalAidl() override;
+
+ status_t getHalPid(pid_t *pid);
+
+ bool requestHalThreadPriority(pid_t threadPid, pid_t threadId);
+
+ status_t getLatency(uint32_t *latency);
+
+ status_t getObservablePosition(int64_t *frames, int64_t *timestamp);
+
+ status_t getXruns(int32_t *frames);
+
+ status_t transfer(void *buffer, size_t bytes, size_t *transferred);
+
+ status_t pause(
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+ status_t resume(
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+ status_t drain(bool earlyNotify,
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+ status_t flush(
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+ status_t exit();
+
+ const bool mIsInput;
+ const audio_config_base_t mConfig;
+ const StreamContextAidl mContext;
+
+ private:
+ static audio_config_base_t configToBase(const audio_config& config) {
+ audio_config_base_t result = AUDIO_CONFIG_BASE_INITIALIZER;
+ result.sample_rate = config.sample_rate;
+ result.channel_mask = config.channel_mask;
+ result.format = config.format;
+ return result;
+ }
+ ::aidl::android::hardware::audio::core::StreamDescriptor::State getState() {
+ std::lock_guard l(mLock);
+ return mLastReply.state;
+ }
+ status_t sendCommand(
+ const ::aidl::android::hardware::audio::core::StreamDescriptor::Command &command,
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr,
+ bool safeFromNonWorkerThread = false);
+ status_t updateCountersIfNeeded(
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> mStream;
+ std::mutex mLock;
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply mLastReply GUARDED_BY(mLock);
+ // mStreamPowerLog is used for audio signal power logging.
+ StreamPowerLog mStreamPowerLog;
+ std::atomic<pid_t> mWorkerTid = -1;
+};
+
+class CallbackBroker;
+
+class StreamOutHalAidl : public StreamOutHalInterface, public StreamHalAidl {
+ public:
+ // Extract the output stream parameters and set by AIDL APIs.
+ status_t setParameters(const String8& kvPairs) override;
+
+ // Return the audio hardware driver estimated latency in milliseconds.
+ status_t getLatency(uint32_t *latency) override;
+
+ // Use this method in situations where audio mixing is done in the hardware.
+ status_t setVolume(float left, float right) override;
+
+ // Selects the audio presentation (if available).
+ status_t selectPresentation(int presentationId, int programId) override;
+
+ // Write audio buffer to driver.
+ status_t write(const void *buffer, size_t bytes, size_t *written) override;
+
+ // Return the number of audio frames written by the audio dsp to DAC since
+ // the output has exited standby.
+ status_t getRenderPosition(uint32_t *dspFrames) override;
+
+ // Get the local time at which the next write to the audio driver will be presented.
+ status_t getNextWriteTimestamp(int64_t *timestamp) override;
+
+ // Set the callback for notifying completion of non-blocking write and drain.
+ status_t setCallback(wp<StreamOutHalInterfaceCallback> callback) override;
+
+ // Returns whether pause and resume operations are supported.
+ status_t supportsPauseAndResume(bool *supportsPause, bool *supportsResume) override;
+
+ // Notifies to the audio driver to resume playback following a pause.
+ status_t pause() override;
+
+ // Notifies to the audio driver to resume playback following a pause.
+ status_t resume() override;
+
+ // Returns whether drain operation is supported.
+ status_t supportsDrain(bool *supportsDrain) override;
+
+ // Requests notification when data buffered by the driver/hardware has been played.
+ status_t drain(bool earlyNotify) override;
+
+ // Notifies to the audio driver to flush the queued data.
+ status_t flush() override;
+
+ // Return a recent count of the number of audio frames presented to an external observer.
+ status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) override;
+
+ // Called when the metadata of the stream's source has been changed.
+ status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) override;
+
+ // Returns the Dual Mono mode presentation setting.
+ status_t getDualMonoMode(audio_dual_mono_mode_t* mode) override;
+
+ // Sets the Dual Mono mode presentation on the output device.
+ status_t setDualMonoMode(audio_dual_mono_mode_t mode) override;
+
+ // Returns the Audio Description Mix level in dB.
+ status_t getAudioDescriptionMixLevel(float* leveldB) override;
+
+ // Sets the Audio Description Mix level in dB.
+ status_t setAudioDescriptionMixLevel(float leveldB) override;
+
+ // Retrieves current playback rate parameters.
+ status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) override;
+
+ // Sets the playback rate parameters that control playback behavior.
+ status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) override;
+
+ status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) override;
+
+ status_t setLatencyMode(audio_latency_mode_t mode) override;
+ status_t getRecommendedLatencyModes(std::vector<audio_latency_mode_t> *modes) override;
+ status_t setLatencyModeCallback(
+ const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) override;
+
+ status_t exit() override;
+
+ private:
+ friend class sp<StreamOutHalAidl>;
+
+ static ConversionResult<::aidl::android::hardware::audio::common::SourceMetadata>
+ legacy2aidl_SourceMetadata(const StreamOutHalInterface::SourceMetadata& legacy);
+
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut> mStream;
+ const wp<CallbackBroker> mCallbackBroker;
+
+ AudioOffloadMetadata mOffloadMetadata;
+
+ // Can not be constructed directly by clients.
+ StreamOutHalAidl(
+ const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut>& stream,
+ const sp<CallbackBroker>& callbackBroker);
+
+ ~StreamOutHalAidl() override;
+
+ // Filter and update the offload metadata. The parameters which are related to the offload
+ // metadata will be removed after filtering.
+ status_t filterAndUpdateOffloadMetadata(AudioParameter ¶meters);
+};
+
+class MicrophoneInfoProvider;
+
+class StreamInHalAidl : public StreamInHalInterface, public StreamHalAidl {
+ public:
+ // Set the input gain for the audio driver.
+ status_t setGain(float gain) override;
+
+ // Read audio buffer in from driver.
+ status_t read(void *buffer, size_t bytes, size_t *read) override;
+
+ // Return the amount of input frames lost in the audio driver.
+ status_t getInputFramesLost(uint32_t *framesLost) override;
+
+ // Return a recent count of the number of audio frames received and
+ // the clock time associated with that frame count.
+ status_t getCapturePosition(int64_t *frames, int64_t *time) override;
+
+ // Get active microphones
+ status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) override;
+
+ // Set microphone direction (for processing)
+ status_t setPreferredMicrophoneDirection(
+ audio_microphone_direction_t direction) override;
+
+ // Set microphone zoom (for processing)
+ status_t setPreferredMicrophoneFieldDimension(float zoom) override;
+
+ // Called when the metadata of the stream's sink has been changed.
+ status_t updateSinkMetadata(const SinkMetadata& sinkMetadata) override;
+
+ private:
+ friend class sp<StreamInHalAidl>;
+
+ static ConversionResult<::aidl::android::hardware::audio::common::SinkMetadata>
+ legacy2aidl_SinkMetadata(const StreamInHalInterface::SinkMetadata& legacy);
+
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamIn> mStream;
+ const wp<MicrophoneInfoProvider> mMicInfoProvider;
+
+ // Can not be constructed directly by clients.
+ StreamInHalAidl(
+ const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamIn>& stream,
+ const sp<MicrophoneInfoProvider>& micInfoProvider);
+
+ ~StreamInHalAidl() override = default;
+};
+
+} // namespace android
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 76f9a60..192790c 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -24,6 +24,9 @@
#include <mediautils/SchedulingPolicyService.h>
#include <mediautils/TimeCheck.h>
#include <utils/Log.h>
+#if MAJOR_VERSION >= 4
+#include <media/AidlConversion.h>
+#endif
#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamOutCallback.h)
#include <HidlUtils.h>
@@ -46,9 +49,6 @@
using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
-#define TIME_CHECK() auto TimeCheck = \
- mediautils::makeTimeCheckStatsForClassMethod(getClassName(), __func__)
-
StreamHalHidl::StreamHalHidl(std::string_view className, IStream *stream)
: CoreConversionHelperHidl(className),
mStream(stream),
@@ -441,7 +441,7 @@
#endif
status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
if (mStream == 0) return NO_INIT;
*written = 0;
@@ -587,7 +587,7 @@
}
status_t StreamOutHalHidl::getRenderPosition(uint32_t *dspFrames) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
if (mStream == 0) return NO_INIT;
Result retval;
Return<void> ret = mStream->getRenderPosition(
@@ -668,7 +668,7 @@
}
status_t StreamOutHalHidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
if (mStream == 0) return NO_INIT;
if (mWriterClient == gettid() && mCommandMQ) {
return callWriterThread(
@@ -1012,7 +1012,7 @@
}
status_t StreamInHalHidl::read(void *buffer, size_t bytes, size_t *read) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
if (mStream == 0) return NO_INIT;
*read = 0;
@@ -1146,7 +1146,7 @@
}
status_t StreamInHalHidl::getCapturePosition(int64_t *frames, int64_t *time) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
if (mStream == 0) return NO_INIT;
if (mReaderClient == gettid() && mCommandMQ) {
ReadParameters params;
@@ -1172,7 +1172,7 @@
#if MAJOR_VERSION == 2
status_t StreamInHalHidl::getActiveMicrophones(
- std::vector<media::MicrophoneInfo> *microphones __unused) {
+ std::vector<media::MicrophoneInfoFw> *microphones __unused) {
if (mStream == 0) return NO_INIT;
return INVALID_OPERATION;
}
@@ -1185,7 +1185,7 @@
#elif MAJOR_VERSION >= 4
status_t StreamInHalHidl::getActiveMicrophones(
- std::vector<media::MicrophoneInfo> *microphonesInfo) {
+ std::vector<media::MicrophoneInfoFw> *microphonesInfo) {
TIME_CHECK();
if (!mStream) return NO_INIT;
Result retval;
@@ -1193,11 +1193,17 @@
[&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
retval = r;
for (size_t k = 0; k < micArrayHal.size(); k++) {
+ // Convert via legacy.
audio_microphone_characteristic_t dst;
- // convert
(void)CoreUtils::microphoneInfoToHal(micArrayHal[k], &dst);
- media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
- microphonesInfo->push_back(microphone);
+ auto conv = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(dst);
+ if (conv.ok()) {
+ microphonesInfo->push_back(conv.value());
+ } else {
+ ALOGW("getActiveMicrophones: could not convert %s to AIDL: %d",
+ toString(micArrayHal[k]).c_str(), conv.error());
+ microphonesInfo->push_back(media::MicrophoneInfoFw{});
+ }
}
});
return processReturn("getActiveMicrophones", ret, retval);
diff --git a/media/libaudiohal/impl/StreamHalHidl.h b/media/libaudiohal/impl/StreamHalHidl.h
index 54fbefe..5361047 100644
--- a/media/libaudiohal/impl/StreamHalHidl.h
+++ b/media/libaudiohal/impl/StreamHalHidl.h
@@ -253,7 +253,7 @@
virtual status_t getCapturePosition(int64_t *frames, int64_t *time);
// Get active microphones
- virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+ status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) override;
// Set microphone direction (for processing)
virtual status_t setPreferredMicrophoneDirection(
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp
new file mode 100644
index 0000000..92b77d8
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionAec"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_aec.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionAec.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::AcousticEchoCanceler;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionAec::setParameter(EffectParamReader& param) {
+ uint32_t type, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type) ||
+ OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ Parameter aidlParam;
+ switch (type) {
+ case AEC_PARAM_ECHO_DELAY:
+ FALLTHROUGH_INTENDED;
+ case AEC_PARAM_PROPERTIES: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_uint32_echoDelay_Parameter_aec(value));
+ break;
+ }
+ case AEC_PARAM_MOBILE_MODE: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_uint32_mobileMode_Parameter_aec(value));
+ break;
+ }
+ default: {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(AcousticEchoCanceler, acousticEchoCanceler, vendor,
+ ext);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam)));
+ break;
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionAec::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type)) {
+ param.setStatus(BAD_VALUE);
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case AEC_PARAM_ECHO_DELAY:
+ FALLTHROUGH_INTENDED;
+ case AEC_PARAM_PROPERTIES: {
+ int32_t delay = 0;
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(AcousticEchoCanceler, acousticEchoCancelerTag,
+ AcousticEchoCanceler::echoDelayUs);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ delay = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_aec_uint32_echoDelay(aidlParam));
+ return param.writeToValue(&delay);
+ }
+ case AEC_PARAM_MOBILE_MODE: {
+ int32_t mode = 0;
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(AcousticEchoCanceler, acousticEchoCancelerTag,
+ AcousticEchoCanceler::mobileMode);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ mode = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_aec_uint32_mobileMode(aidlParam));
+ return param.writeToValue(&mode);
+ }
+ default: {
+ // use vendor extension implementation, the first 32bits (param type) won't pass to HAL
+ VENDOR_EXTENSION_GET_AND_RETURN(AcousticEchoCanceler, acousticEchoCanceler, param);
+ }
+ }
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
new file mode 100644
index 0000000..3ee419a
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionAec : public EffectConversionHelperAidl {
+ public:
+ AidlConversionAec(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionAec() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.cpp
new file mode 100644
index 0000000..1363ba4
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionAgc1"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_agc.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionAgc1.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::AutomaticGainControlV1;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionAgc1::setParameterLevel(EffectParamReader& param) {
+ int16_t level;
+ RETURN_STATUS_IF_ERROR(param.readFromValue(&level));
+ Parameter aidlParam = MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV1, automaticGainControlV1,
+ targetPeakLevelDbFs, level);
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionAgc1::setParameterGain(EffectParamReader& param) {
+ int16_t gain;
+ RETURN_STATUS_IF_ERROR(param.readFromValue(&gain));
+ Parameter aidlParam = MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV1, automaticGainControlV1,
+ maxCompressionGainDb, gain);
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionAgc1::setParameterLimiterEnable(EffectParamReader& param) {
+ bool enable;
+ RETURN_STATUS_IF_ERROR(param.readFromValue(&enable));
+ Parameter aidlParam = MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV1, automaticGainControlV1,
+ enableLimiter, enable);
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionAgc1::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ if (OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ switch (type) {
+ case AGC_PARAM_TARGET_LEVEL: {
+ return setParameterLevel(param);
+ }
+ case AGC_PARAM_COMP_GAIN: {
+ return setParameterGain(param);
+ }
+ case AGC_PARAM_LIMITER_ENA: {
+ return setParameterLimiterEnable(param);
+ }
+ case AGC_PARAM_PROPERTIES: {
+ RETURN_STATUS_IF_ERROR(setParameterLevel(param));
+ RETURN_STATUS_IF_ERROR(setParameterGain(param));
+ RETURN_STATUS_IF_ERROR(setParameterLimiterEnable(param));
+ return OK;
+ }
+ default: {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ Parameter aidlParam = MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV1,
+ automaticGainControlV1, vendor, ext);
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+ }
+ }
+}
+
+status_t AidlConversionAgc1::getParameterLevel(EffectParamWriter& param) {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV1, automaticGainControlV1Tag,
+ AutomaticGainControlV1::targetPeakLevelDbFs);
+ Parameter aidlParam;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ int32_t level = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, AutomaticGainControlV1, automaticGainControlV1,
+ AutomaticGainControlV1::targetPeakLevelDbFs, int32_t));
+ return param.writeToValue(&level);
+}
+
+status_t AidlConversionAgc1::getParameterGain(EffectParamWriter& param) {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV1, automaticGainControlV1Tag,
+ AutomaticGainControlV1::maxCompressionGainDb);
+ Parameter aidlParam;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ int32_t gain = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, AutomaticGainControlV1, automaticGainControlV1,
+ AutomaticGainControlV1::maxCompressionGainDb, int32_t));
+ return param.writeToValue(&gain);
+}
+
+status_t AidlConversionAgc1::getParameterLimiterEnable(EffectParamWriter& param) {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV1, automaticGainControlV1Tag,
+ AutomaticGainControlV1::enableLimiter);
+ Parameter aidlParam;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ bool enable = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, AutomaticGainControlV1, automaticGainControlV1,
+ AutomaticGainControlV1::enableLimiter, bool));
+ return param.writeToValue(&enable);
+}
+
+status_t AidlConversionAgc1::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0;
+ if (OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ switch (type) {
+ case AGC_PARAM_TARGET_LEVEL: {
+ return getParameterLevel(param);
+ }
+ case AGC_PARAM_COMP_GAIN: {
+ return getParameterGain(param);
+ }
+ case AGC_PARAM_LIMITER_ENA: {
+ return getParameterLimiterEnable(param);
+ }
+ case AGC_PARAM_PROPERTIES: {
+ RETURN_STATUS_IF_ERROR(getParameterLevel(param));
+ RETURN_STATUS_IF_ERROR(getParameterGain(param));
+ RETURN_STATUS_IF_ERROR(getParameterLimiterEnable(param));
+ return OK;
+ }
+ default: {
+ VENDOR_EXTENSION_GET_AND_RETURN(AutomaticGainControlV1, automaticGainControlV1, param);
+ }
+ }
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h
new file mode 100644
index 0000000..b0509fd
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionAgc1 : public EffectConversionHelperAidl {
+ public:
+ AidlConversionAgc1(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionAgc1() {}
+
+ private:
+ status_t setParameterLevel(utils::EffectParamReader& param);
+ status_t setParameterGain(utils::EffectParamReader& param);
+ status_t setParameterLimiterEnable(utils::EffectParamReader& param);
+ status_t setParameter(utils::EffectParamReader& param) override;
+
+ status_t getParameterLevel(utils::EffectParamWriter& param);
+ status_t getParameterGain(utils::EffectParamWriter& param);
+ status_t getParameterLimiterEnable(utils::EffectParamWriter& param);
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp
new file mode 100644
index 0000000..b35a1c6
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionAgc2"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_agc2.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionAgc2.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::AutomaticGainControlV2;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionAgc2::setParameter(EffectParamReader& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case AGC2_PARAM_FIXED_DIGITAL_GAIN: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_uint32_fixedDigitalGain_Parameter_agc(value));
+ break;
+ }
+ case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_uint32_levelEstimator_Parameter_agc(value));
+ break;
+ }
+ case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_uint32_saturationMargin_Parameter_agc(value));
+ break;
+ }
+ default: {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV2, automaticGainControlV2,
+ vendor, ext);
+ break;
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionAgc2::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case AGC2_PARAM_FIXED_DIGITAL_GAIN: {
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV2, automaticGainControlV2Tag,
+ AutomaticGainControlV2::fixedDigitalGainMb);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(aidlParam));
+ break;
+ }
+ case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR: {
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV2, automaticGainControlV2Tag,
+ AutomaticGainControlV2::levelEstimator);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_agc_uint32_levelEstimator(aidlParam));
+ break;
+ }
+ case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN: {
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV2, automaticGainControlV2Tag,
+ AutomaticGainControlV2::saturationMarginMb);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_agc_uint32_saturationMargin(aidlParam));
+ break;
+ }
+ default: {
+ VENDOR_EXTENSION_GET_AND_RETURN(AutomaticGainControlV2, automaticGainControlV2, param);
+ }
+ }
+
+ return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
new file mode 100644
index 0000000..8f7eac7
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionAgc2 : public EffectConversionHelperAidl {
+ public:
+ AidlConversionAgc2(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionAgc2() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
new file mode 100644
index 0000000..7c6a5a2
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionBassBoost"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/aidl_effects_utils.h>
+#include <system/audio_effects/effect_bassboost.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionBassBoost.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::convertIntegral;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::BassBoost;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::Range;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionBassBoost::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ uint16_t value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case BASSBOOST_PARAM_STRENGTH: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_uint16_strengthPm_Parameter_BassBoost(value));
+ break;
+ }
+ case BASSBOOST_PARAM_STRENGTH_SUPPORTED: {
+ ALOGW("%s set BASSBOOST_PARAM_STRENGTH_SUPPORTED not supported", __func__);
+ return BAD_VALUE;
+ }
+ default: {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(BassBoost, bassBoost, vendor, ext);
+ break;
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionBassBoost::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case BASSBOOST_PARAM_STRENGTH: {
+ uint16_t value;
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(BassBoost, bassBoostTag, BassBoost::strengthPm);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_BassBoost_uint16_strengthPm(aidlParam));
+ return param.writeToValue(&value);
+ }
+ case BASSBOOST_PARAM_STRENGTH_SUPPORTED: {
+ // an invalid range indicates not setting support for this parameter
+ uint32_t value =
+ ::aidl::android::hardware::audio::effect::isRangeValid<Range::Tag::bassBoost>(
+ BassBoost::strengthPm, mDesc.capability);
+ return param.writeToValue(&value);
+ }
+ default: {
+ VENDOR_EXTENSION_GET_AND_RETURN(BassBoost, bassBoost, param);
+ }
+ }
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
new file mode 100644
index 0000000..9664aa1
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionBassBoost : public EffectConversionHelperAidl {
+ public:
+ AidlConversionBassBoost(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionBassBoost() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.cpp
new file mode 100644
index 0000000..b57971c
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionDownmix"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_downmix.h>
+
+#include <system/audio_effect.h>
+#include <utils/Log.h>
+
+#include "AidlConversionDownmix.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Downmix;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionDownmix::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ int16_t value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(int16_t)) ||
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case DOWNMIX_PARAM_TYPE: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_int16_type_Parameter_Downmix(value));
+ break;
+ }
+ default: {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Downmix, downmix, vendor, ext);
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionDownmix::getParameter(EffectParamWriter& param) {
+ int16_t value = 0;
+ uint32_t type = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type)) {
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case DOWNMIX_PARAM_TYPE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Downmix, downmixTag, Downmix::type);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_Downmix_int16_type(aidlParam));
+ break;
+ }
+ default: {
+ VENDOR_EXTENSION_GET_AND_RETURN(Downmix, downmix, param);
+ }
+ }
+
+ return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
new file mode 100644
index 0000000..8b28ca3
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/BpEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionDownmix : public EffectConversionHelperAidl {
+ public:
+ AidlConversionDownmix(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionDownmix() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
new file mode 100644
index 0000000..fe845ab
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionDp"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effect.h>
+#include <system/audio_effects/effect_dynamicsprocessing.h>
+#include <Utils.h>
+#include <utils/Log.h>
+
+#include "AidlConversionDynamicsProcessing.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::convertIntegral;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Capability;
+using ::aidl::android::hardware::audio::effect::DynamicsProcessing;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::toString;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionDp::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ RETURN_STATUS_IF_ERROR(param.readFromParameter(&type));
+ Parameter aidlParam;
+ switch (type) {
+ case DP_PARAM_INPUT_GAIN: {
+ DynamicsProcessing::InputGain inputGainAidl;
+ RETURN_STATUS_IF_ERROR(param.readFromParameter(&inputGainAidl.channel));
+ RETURN_STATUS_IF_ERROR(param.readFromValue(&inputGainAidl.gainDb));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, inputGain,
+ {inputGainAidl});
+ break;
+ }
+ case DP_PARAM_ENGINE_ARCHITECTURE: {
+ DynamicsProcessing::EngineArchitecture engine =
+ VALUE_OR_RETURN_STATUS(readEngineArchitectureFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing,
+ engineArchitecture, engine);
+ mEngine = engine;
+ break;
+ }
+ case DP_PARAM_PRE_EQ: {
+ DynamicsProcessing::ChannelConfig chConfig =
+ VALUE_OR_RETURN_STATUS(readChannelConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, preEq,
+ {chConfig});
+ break;
+ }
+ case DP_PARAM_POST_EQ: {
+ DynamicsProcessing::ChannelConfig chConfig =
+ VALUE_OR_RETURN_STATUS(readChannelConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, postEq,
+ {chConfig});
+ break;
+ }
+ case DP_PARAM_MBC: {
+ DynamicsProcessing::ChannelConfig chConfig =
+ VALUE_OR_RETURN_STATUS(readChannelConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, mbc,
+ {chConfig});
+ break;
+ }
+ case DP_PARAM_PRE_EQ_BAND: {
+ DynamicsProcessing::EqBandConfig bandConfig =
+ VALUE_OR_RETURN_STATUS(readEqBandConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, preEqBand,
+ {bandConfig});
+ break;
+ }
+ case DP_PARAM_POST_EQ_BAND: {
+ DynamicsProcessing::EqBandConfig bandConfig =
+ VALUE_OR_RETURN_STATUS(readEqBandConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, postEqBand,
+ {bandConfig});
+ break;
+ }
+ case DP_PARAM_MBC_BAND: {
+ DynamicsProcessing::MbcBandConfig bandConfig =
+ VALUE_OR_RETURN_STATUS(readMbcBandConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, mbcBand,
+ {bandConfig});
+ break;
+ }
+ case DP_PARAM_LIMITER: {
+ DynamicsProcessing::LimiterConfig config =
+ VALUE_OR_RETURN_STATUS(readLimiterConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, limiter,
+ {config});
+ break;
+ }
+ default: {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ aidlParam =
+ MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, vendor, ext);
+ break;
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionDp::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0;
+ RETURN_STATUS_IF_ERROR(param.readFromParameter(&type));
+ Parameter aidlParam;
+ switch (type) {
+ case DP_PARAM_INPUT_GAIN: {
+ int32_t channel;
+ RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
+ DynamicsProcessing::inputGain);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+ std::vector<DynamicsProcessing::InputGain> gains =
+ VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing,
+ DynamicsProcessing::inputGain,
+ std::vector<DynamicsProcessing::InputGain>));
+ for (const auto& gain : gains) {
+ if (gain.channel == channel) {
+ return param.writeToValue(&gain.gainDb);
+ }
+ }
+ ALOGE("%s not able to find channel %d", __func__, channel);
+ return BAD_VALUE;
+ }
+ case DP_PARAM_ENGINE_ARCHITECTURE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
+ DynamicsProcessing::engineArchitecture);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+ DynamicsProcessing::EngineArchitecture engine =
+ VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing,
+ DynamicsProcessing::engineArchitecture,
+ DynamicsProcessing::EngineArchitecture));
+ int32_t resolution = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_DynamicsProcessing_ResolutionPreference_int32(
+ engine.resolutionPreference));
+ int32_t preEqInUse =
+ VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.preEqStage.inUse));
+ int32_t mbcInUse =
+ VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.mbcStage.inUse));
+ int32_t postEqInUse =
+ VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.postEqStage.inUse));
+ int32_t limiterInUse =
+ VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.limiterInUse));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&resolution));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&engine.preferredProcessingDurationMs));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&preEqInUse));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&engine.preEqStage.bandCount));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&mbcInUse));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&engine.mbcStage.bandCount));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&postEqInUse));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&engine.postEqStage.bandCount));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&limiterInUse));
+ mEngine = engine;
+ return OK;
+ }
+ case DP_PARAM_PRE_EQ: {
+ return getChannelConfig(DynamicsProcessing::preEq, param);
+ }
+ case DP_PARAM_POST_EQ: {
+ return getChannelConfig(DynamicsProcessing::postEq, param);
+ }
+ case DP_PARAM_MBC: {
+ return getChannelConfig(DynamicsProcessing::mbc, param);
+ }
+ case DP_PARAM_PRE_EQ_BAND: {
+ return getEqBandConfig(DynamicsProcessing::preEqBand, param);
+ }
+ case DP_PARAM_POST_EQ_BAND: {
+ return getEqBandConfig(DynamicsProcessing::postEqBand, param);
+ }
+ case DP_PARAM_MBC_BAND: {
+ return getMbcBandConfig(param);
+ }
+ case DP_PARAM_LIMITER: {
+ return getLimiterConfig(param);
+ }
+ case DP_PARAM_GET_CHANNEL_COUNT: {
+ uint32_t channel = ::aidl::android::hardware::audio::common::getChannelCount(
+ mCommon.input.base.channelMask);
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&channel));
+ return OK;
+ }
+ default: {
+ VENDOR_EXTENSION_GET_AND_RETURN(DynamicsProcessing, dynamicsProcessing, param);
+ }
+ }
+}
+
+ConversionResult<DynamicsProcessing::ChannelConfig>
+AidlConversionDp::readChannelConfigFromParam(EffectParamReader& param) {
+ int32_t enable, channel;
+ RETURN_IF_ERROR(param.readFromParameter(&channel));
+ RETURN_IF_ERROR(param.readFromValue(&enable));
+
+ return DynamicsProcessing::ChannelConfig(
+ {.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable)), .channel = channel});
+}
+
+ConversionResult<DynamicsProcessing::EqBandConfig>
+AidlConversionDp::readEqBandConfigFromParam(EffectParamReader& param) {
+ DynamicsProcessing::EqBandConfig config;
+ int32_t enable;
+ RETURN_IF_ERROR(param.readFromParameter(&config.channel));
+ RETURN_IF_ERROR(param.readFromParameter(&config.band));
+ RETURN_IF_ERROR(param.readFromValue(&enable));
+ RETURN_IF_ERROR(param.readFromValue(&config.cutoffFrequencyHz));
+ RETURN_IF_ERROR(param.readFromValue(&config.gainDb));
+
+ config.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable));
+ return config;
+}
+
+ConversionResult<DynamicsProcessing::MbcBandConfig>
+AidlConversionDp::readMbcBandConfigFromParam(EffectParamReader& param) {
+ DynamicsProcessing::MbcBandConfig config;
+ int32_t enable;
+ RETURN_IF_ERROR(param.readFromParameter(&config.channel));
+ RETURN_IF_ERROR(param.readFromParameter(&config.band));
+ RETURN_IF_ERROR(param.readFromValue(&enable));
+ RETURN_IF_ERROR(param.readFromValue(&config.cutoffFrequencyHz));
+ RETURN_IF_ERROR(param.readFromValue(&config.attackTimeMs));
+ RETURN_IF_ERROR(param.readFromValue(&config.releaseTimeMs));
+ RETURN_IF_ERROR(param.readFromValue(&config.ratio));
+ RETURN_IF_ERROR(param.readFromValue(&config.thresholdDb));
+ RETURN_IF_ERROR(param.readFromValue(&config.kneeWidthDb));
+ RETURN_IF_ERROR(param.readFromValue(&config.noiseGateThresholdDb));
+ RETURN_IF_ERROR(param.readFromValue(&config.expanderRatio));
+ RETURN_IF_ERROR(param.readFromValue(&config.preGainDb));
+ RETURN_IF_ERROR(param.readFromValue(&config.postGainDb));
+
+ config.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable));
+ return config;
+}
+
+ConversionResult<DynamicsProcessing::LimiterConfig>
+AidlConversionDp::readLimiterConfigFromParam(EffectParamReader& param) {
+ DynamicsProcessing::LimiterConfig config;
+ int32_t enable, inUse;
+ RETURN_IF_ERROR(param.readFromParameter(&config.channel));
+ RETURN_IF_ERROR(param.readFromValue(&inUse));
+ RETURN_IF_ERROR(param.readFromValue(&enable));
+ RETURN_IF_ERROR(param.readFromValue(&config.linkGroup));
+ RETURN_IF_ERROR(param.readFromValue(&config.attackTimeMs));
+ RETURN_IF_ERROR(param.readFromValue(&config.releaseTimeMs));
+ RETURN_IF_ERROR(param.readFromValue(&config.ratio));
+ RETURN_IF_ERROR(param.readFromValue(&config.thresholdDb));
+ RETURN_IF_ERROR(param.readFromValue(&config.postGainDb));
+
+ config.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable));
+ return config;
+}
+
+ConversionResult<DynamicsProcessing::EngineArchitecture>
+AidlConversionDp::readEngineArchitectureFromParam(EffectParamReader& param) {
+ DynamicsProcessing::EngineArchitecture engine;
+ int32_t variant, preEqInUse, mbcInUse, postEqInUse, limiterInUse;
+ RETURN_IF_ERROR(param.readFromValue(&variant));
+ RETURN_IF_ERROR(param.readFromValue(&engine.preferredProcessingDurationMs));
+ RETURN_IF_ERROR(param.readFromValue(&preEqInUse));
+ RETURN_IF_ERROR(param.readFromValue(&engine.preEqStage.bandCount));
+ RETURN_IF_ERROR(param.readFromValue(&mbcInUse));
+ RETURN_IF_ERROR(param.readFromValue(&engine.mbcStage.bandCount));
+ RETURN_IF_ERROR(param.readFromValue(&postEqInUse));
+ RETURN_IF_ERROR(param.readFromValue(&engine.postEqStage.bandCount));
+ RETURN_IF_ERROR(param.readFromValue(&limiterInUse));
+
+ engine.resolutionPreference = VALUE_OR_RETURN(
+ aidl::android::legacy2aidl_int32_DynamicsProcessing_ResolutionPreference(variant));
+ engine.preEqStage.inUse = VALUE_OR_RETURN(convertIntegral<bool>(preEqInUse));
+ engine.mbcStage.inUse = VALUE_OR_RETURN(convertIntegral<bool>(mbcInUse));
+ engine.postEqStage.inUse = VALUE_OR_RETURN(convertIntegral<bool>(postEqInUse));
+ engine.limiterInUse = VALUE_OR_RETURN(convertIntegral<bool>(limiterInUse));
+ return engine;
+}
+
+status_t AidlConversionDp::getChannelConfig(DynamicsProcessing::Tag tag, EffectParamWriter& param) {
+ int32_t channel;
+ RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
+
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag, tag);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+ std::vector<DynamicsProcessing::ChannelConfig> channels;
+ int32_t inUse, bandCount;
+ switch (tag) {
+ case DynamicsProcessing::preEq: {
+ inUse = mEngine.preEqStage.inUse;
+ bandCount = mEngine.preEqStage.bandCount;
+ channels = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, DynamicsProcessing::preEq,
+ std::vector<DynamicsProcessing::ChannelConfig>));
+ break;
+ }
+ case DynamicsProcessing::postEq: {
+ inUse = mEngine.postEqStage.inUse;
+ bandCount = mEngine.postEqStage.bandCount;
+ channels = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, DynamicsProcessing::postEq,
+ std::vector<DynamicsProcessing::ChannelConfig>));
+ break;
+ }
+ case DynamicsProcessing::mbc: {
+ inUse = mEngine.mbcStage.inUse;
+ bandCount = mEngine.mbcStage.bandCount;
+ channels = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, DynamicsProcessing::mbc,
+ std::vector<DynamicsProcessing::ChannelConfig>));
+ break;
+ }
+ default: {
+ ALOGE("%s unsupported tag %s", __func__, toString(tag).c_str());
+ return BAD_VALUE;
+ }
+ }
+
+ for (const auto& ch : channels) {
+ if (ch.channel == channel) {
+ int32_t enable = ch.enable;
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&inUse));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&enable));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&bandCount));
+ return OK;
+ }
+ }
+ ALOGE("%s not able to find channel %d", __func__, channel);
+ return BAD_VALUE;
+}
+
+status_t AidlConversionDp::getEqBandConfig(DynamicsProcessing::Tag tag, EffectParamWriter& param) {
+ int32_t channel, band;
+ RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
+ RETURN_STATUS_IF_ERROR(param.readFromParameter(&band));
+
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag, tag);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+ std::vector<DynamicsProcessing::EqBandConfig> bands;
+ if (tag == DynamicsProcessing::preEqBand) {
+ bands = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, preEqBand,
+ std::vector<DynamicsProcessing::EqBandConfig>));
+ } else if (tag == DynamicsProcessing::postEqBand) {
+ bands = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, postEqBand,
+ std::vector<DynamicsProcessing::EqBandConfig>));
+ } else {
+ return BAD_VALUE;
+ }
+
+ for (const auto& bandIt : bands) {
+ if (bandIt.channel == channel && bandIt.band == band) {
+ int32_t enable = bandIt.enable;
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&enable));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.cutoffFrequencyHz));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.gainDb));
+ return OK;
+ }
+ }
+ ALOGE("%s not able to find channel %d band %d", __func__, channel, band);
+ return BAD_VALUE;
+}
+
+status_t AidlConversionDp::getMbcBandConfig(EffectParamWriter& param) {
+ int32_t channel, band;
+ RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
+ RETURN_STATUS_IF_ERROR(param.readFromParameter(&band));
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
+ DynamicsProcessing::mbcBand);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+ std::vector<DynamicsProcessing::MbcBandConfig> bands =
+ VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, mbcBand,
+ std::vector<DynamicsProcessing::MbcBandConfig>));
+
+ for (const auto& bandIt : bands) {
+ if (bandIt.channel == channel && bandIt.band == band) {
+ int32_t enable = bandIt.enable;
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&enable));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.cutoffFrequencyHz));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.attackTimeMs));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.releaseTimeMs));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.ratio));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.thresholdDb));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.kneeWidthDb));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.noiseGateThresholdDb));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.expanderRatio));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.preGainDb));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.postGainDb));
+ return OK;
+ }
+ }
+ ALOGE("%s not able to find channel %d band %d", __func__, channel, band);
+ return BAD_VALUE;
+}
+
+status_t AidlConversionDp::getLimiterConfig(EffectParamWriter& param) {
+ int32_t channel;
+ RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
+ DynamicsProcessing::limiter);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+ std::vector<DynamicsProcessing::LimiterConfig> configs =
+ VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, limiter,
+ std::vector<DynamicsProcessing::LimiterConfig>));
+
+ for (const auto& config : configs) {
+ if (config.channel == channel) {
+ int32_t inUse = mEngine.limiterInUse;
+ int32_t enable = config.enable;
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&inUse));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&enable));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&config.linkGroup));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&config.attackTimeMs));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&config.releaseTimeMs));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&config.ratio));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&config.thresholdDb));
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&config.postGainDb));
+ return OK;
+ }
+ }
+ ALOGE("%s not able to find channel %d", __func__, channel);
+ return BAD_VALUE;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
new file mode 100644
index 0000000..c5d5a54
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/BpEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionDp : public EffectConversionHelperAidl {
+ public:
+ AidlConversionDp(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionDp() {}
+
+ private:
+ aidl::android::hardware::audio::effect::DynamicsProcessing::EngineArchitecture mEngine;
+
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+
+ ConversionResult<
+ aidl::android::hardware::audio::effect::DynamicsProcessing::ChannelConfig>
+ readChannelConfigFromParam(utils::EffectParamReader& param);
+ ConversionResult<aidl::android::hardware::audio::effect::DynamicsProcessing::EqBandConfig>
+ readEqBandConfigFromParam(utils::EffectParamReader& param);
+ ConversionResult<
+ aidl::android::hardware::audio::effect::DynamicsProcessing::MbcBandConfig>
+ readMbcBandConfigFromParam(utils::EffectParamReader& param);
+ ConversionResult<
+ aidl::android::hardware::audio::effect::DynamicsProcessing::LimiterConfig>
+ readLimiterConfigFromParam(utils::EffectParamReader& param);
+ ConversionResult<
+ aidl::android::hardware::audio::effect::DynamicsProcessing::EngineArchitecture>
+ readEngineArchitectureFromParam(utils::EffectParamReader& param);
+
+ status_t getChannelConfig(aidl::android::hardware::audio::effect::DynamicsProcessing::Tag tag,
+ utils::EffectParamWriter& writer);
+ status_t getEqBandConfig(aidl::android::hardware::audio::effect::DynamicsProcessing::Tag tag,
+ utils::EffectParamWriter& param);
+ status_t getMbcBandConfig(utils::EffectParamWriter& param);
+ status_t getLimiterConfig(utils::EffectParamWriter& param);
+
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp
new file mode 100644
index 0000000..754da43
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionEnvReverb"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_environmentalreverb.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionEnvReverb.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::convertIntegral;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::EnvironmentalReverb;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+/**
+ * Macro to get a parameter from effect_param_t wrapper and set it to AIDL effect.
+ *
+ * Return if there is any error, otherwise continue execution.
+ *
+ * @param param EffectParamReader, a reader wrapper of effect_param_t.
+ * @param aidlType Type of the AIDL parameter field, used to construct AIDL Parameter union.
+ * @param valueType Type of the value get from effect_param_t.
+ * @param tag The AIDL parameter union field tag.
+ */
+#define SET_AIDL_PARAMETER(param, aidlType, valueType, tag) \
+ { \
+ Parameter aidlParam; \
+ valueType value; \
+ if (status_t status = param.readFromValue(&value); status != OK) { \
+ ALOGE("%s %s read from parameter failed, ret %d", __func__, #tag, status); \
+ return status; \
+ } \
+ aidlParam = MAKE_SPECIFIC_PARAMETER( \
+ EnvironmentalReverb, environmentalReverb, tag, \
+ VALUE_OR_RETURN_STATUS(aidl::android::convertIntegral<aidlType>(value))); \
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam))); \
+ }
+
+/**
+ * Macro to get a parameter from AIDL effect and write the value to effect_param_t with wrapper.
+ *
+ * Return if there is any error, otherwise continue execution.
+ *
+ * @param param EffectParamWriter, a writer wrapper of effect_param_t.
+ * @param aidlType Type of the AIDL parameter field, used to construct AIDL Parameter union.
+ * @param valueType Type of the value get from effect_param_t.
+ * @param tag The AIDL parameter union field tag.
+ */
+#define GET_AIDL_PARAMETER(param, aidltype, valueType, tag) \
+ { \
+ aidltype value; \
+ Parameter aidlParam; \
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(EnvironmentalReverb, environmentalReverbTag, \
+ EnvironmentalReverb::tag); \
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam))); \
+ value = VALUE_OR_RETURN_STATUS( \
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, EnvironmentalReverb, environmentalReverb, \
+ EnvironmentalReverb::tag, std::decay_t<aidltype>)); \
+ if (status_t status = param.writeToValue((valueType*)&value); status != OK) { \
+ param.setStatus(status); \
+ ALOGE("%s %s write to parameter failed %d, ret %d", __func__, #tag, value, status); \
+ return status; \
+ } \
+ }
+
+status_t AidlConversionEnvReverb::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ if (status_t status = param.readFromParameter(&type); status != OK) {
+ ALOGE("%s failed to read type from %s, ret %d", __func__, param.toString().c_str(), status);
+ return BAD_VALUE;
+ }
+
+ switch (type) {
+ case REVERB_PARAM_ROOM_LEVEL: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+ break;
+ }
+ case REVERB_PARAM_ROOM_HF_LEVEL: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+ break;
+ }
+ case REVERB_PARAM_DECAY_TIME: {
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+ break;
+ }
+ case REVERB_PARAM_DECAY_HF_RATIO: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+ break;
+ }
+ case REVERB_PARAM_REFLECTIONS_LEVEL: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+ break;
+ }
+ case REVERB_PARAM_REFLECTIONS_DELAY: {
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+ break;
+ }
+ case REVERB_PARAM_REVERB_LEVEL: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+ break;
+ }
+ case REVERB_PARAM_REVERB_DELAY: {
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+ break;
+ }
+ case REVERB_PARAM_DIFFUSION: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+ break;
+ }
+ case REVERB_PARAM_DENSITY: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+ break;
+ }
+ case REVERB_PARAM_BYPASS: {
+ SET_AIDL_PARAMETER(param, bool, int32_t, bypass);
+ break;
+ }
+ case REVERB_PARAM_PROPERTIES: {
+ if (sizeof(t_reverb_settings) > param.getValueSize()) {
+ ALOGE("%s vsize %zu less than t_reverb_settings size %zu", __func__,
+ param.getValueSize(), sizeof(t_reverb_settings));
+ return BAD_VALUE;
+ }
+ // this sequency needs to be aligned with t_reverb_settings
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+ break;
+ }
+ default: {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ Parameter aidlParam = MAKE_SPECIFIC_PARAMETER(EnvironmentalReverb,
+ environmentalReverb, vendor, ext);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam)));
+ break;
+ }
+ }
+ return OK;
+}
+
+status_t AidlConversionEnvReverb::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0;
+ if (status_t status = param.readFromParameter(&type); status != OK) {
+ ALOGE("%s failed to read type from %s", __func__, param.toString().c_str());
+ param.setStatus(status);
+ return status;
+ }
+
+ switch (type) {
+ case REVERB_PARAM_ROOM_LEVEL: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+ break;
+ }
+ case REVERB_PARAM_ROOM_HF_LEVEL: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+ break;
+ }
+ case REVERB_PARAM_DECAY_TIME: {
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+ break;
+ }
+ case REVERB_PARAM_DECAY_HF_RATIO: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+ break;
+ }
+ case REVERB_PARAM_REFLECTIONS_LEVEL: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+ break;
+ }
+ case REVERB_PARAM_REFLECTIONS_DELAY: {
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+ break;
+ }
+ case REVERB_PARAM_REVERB_LEVEL: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+ break;
+ }
+ case REVERB_PARAM_REVERB_DELAY: {
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+ break;
+ }
+ case REVERB_PARAM_DIFFUSION: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+ break;
+ }
+ case REVERB_PARAM_DENSITY: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+ break;
+ }
+ case REVERB_PARAM_BYPASS: {
+ GET_AIDL_PARAMETER(param, bool, int32_t, bypass);
+ break;
+ }
+ case REVERB_PARAM_PROPERTIES: {
+ // this sequency needs to be aligned with t_reverb_settings
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+ break;
+ }
+ default: {
+ VENDOR_EXTENSION_GET_AND_RETURN(EnvironmentalReverb, environmentalReverb, param);
+ }
+ }
+ return OK;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
new file mode 100644
index 0000000..8b92374
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionEnvReverb : public EffectConversionHelperAidl {
+ public:
+ AidlConversionEnvReverb(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionEnvReverb() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
new file mode 100644
index 0000000..45b98a1
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionEQ"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_equalizer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionEq.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Equalizer;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::Range;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::base::unexpected;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionEq::setParameter(EffectParamReader& param) {
+ uint32_t type;
+ if (OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ Parameter aidlParam;
+ switch (type) {
+ case EQ_PARAM_CUR_PRESET: {
+ uint16_t value = 0;
+ if (OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, preset, (int)value);
+ break;
+ }
+ case EQ_PARAM_BAND_LEVEL: {
+ int32_t band;
+ int16_t level;
+ if (OK != param.readFromParameter(&band) || OK != param.readFromValue(&level)) {
+ ALOGE("%s invalid bandLevel param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ std::vector<Equalizer::BandLevel> bandLevels = {{.index = band, .levelMb = level}};
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, bandLevels, bandLevels);
+ break;
+ }
+ case EQ_PARAM_PROPERTIES: {
+ int16_t num;
+ if (OK != param.readFromValue(&num)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ // set preset if it's valid
+ if (num >= 0) {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, preset, (int)num);
+ break;
+ }
+ // set bandLevel if no preset was set
+ if (OK != param.readFromValue(&num)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ std::vector<Equalizer::BandLevel> bandLevels;
+ for (int i = 0; i < num; i++) {
+ Equalizer::BandLevel level({.index = i});
+ if (OK != param.readFromValue((uint16_t*)&level.levelMb)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ bandLevels.push_back(level);
+ }
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, bandLevels, bandLevels);
+ break;
+ }
+ default: {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, vendor, ext);
+ break;
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+ConversionResult<Parameter> AidlConversionEq::getAidlParameter(Equalizer::Tag tag) {
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Equalizer, equalizerTag, tag);
+ RETURN_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ return aidlParam;
+}
+
+ConversionResult<int32_t> AidlConversionEq::getParameterPreset() {
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::preset));
+ return VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Equalizer, equalizer,
+ Equalizer::preset, int32_t));
+}
+
+ConversionResult<std::string> AidlConversionEq::getParameterPresetName(
+ EffectParamWriter& param) {
+ int32_t presetIdx;
+ if (OK != param.readFromParameter(&presetIdx)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return unexpected(BAD_VALUE);
+ }
+ Parameter aidlParam = VALUE_OR_RETURN(getAidlParameter(Equalizer::presets));
+ const auto& presets = VALUE_OR_RETURN(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::presets, std::vector<Equalizer::Preset>));
+ for (const auto& preset : presets) {
+ if (presetIdx == preset.index) {
+ return preset.name;
+ }
+ }
+ return unexpected(BAD_VALUE);
+}
+
+status_t AidlConversionEq::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0;
+ if (OK != param.readFromParameter(&type)) {
+ param.setStatus(BAD_VALUE);
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ switch (type) {
+ case EQ_PARAM_NUM_BANDS: {
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
+ const auto& bandLevels = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::bandLevels,
+ std::vector<Equalizer::BandLevel>));
+ uint16_t bands = bandLevels.size();
+ return param.writeToValue(&bands);
+ }
+ case EQ_PARAM_LEVEL_RANGE: {
+ const auto& ranges = mDesc.capability.range.get<Range::equalizer>();
+ for (const auto& r : ranges) {
+ if (r.min.getTag() == Equalizer::bandLevels &&
+ r.max.getTag() == Equalizer::bandLevels) {
+ const auto& aidlMin = r.min.get<Equalizer::bandLevels>();
+ const auto& aidlMax = r.max.get<Equalizer::bandLevels>();
+ int16_t min =
+ std::min_element(aidlMin.begin(), aidlMin.end(), [](auto& a, auto& b) {
+ return a.levelMb < b.levelMb;
+ })->levelMb;
+ int16_t max =
+ std::max_element(aidlMax.begin(), aidlMax.end(), [](auto& a, auto& b) {
+ return a.levelMb < b.levelMb;
+ })->levelMb;
+ return (OK == param.writeToValue(&min) && OK == param.writeToValue(&max))
+ ? OK
+ : BAD_VALUE;
+ }
+ }
+ break;
+ }
+ case EQ_PARAM_BAND_LEVEL: {
+ int32_t bandIdx;
+ if (OK != param.readFromParameter(&bandIdx)) {
+ break;
+ }
+
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
+ const auto& bandLevels = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::bandLevels,
+ std::vector<Equalizer::BandLevel>));
+ for (const auto& band : bandLevels) {
+ if (band.index == bandIdx) {
+ return param.writeToValue((uint16_t *)&band.levelMb);
+ }
+ }
+ break;
+ }
+ case EQ_PARAM_CENTER_FREQ: {
+ int32_t index;
+ if (OK != param.readFromParameter(&index)) {
+ break;
+ }
+
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::centerFreqMh));
+ const auto& freqs = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::centerFreqMh, std::vector<int>));
+ if ((size_t)index >= freqs.size()) {
+ ALOGE("%s index %d exceed size %zu", __func__, index, freqs.size());
+ break;
+ }
+ return param.writeToValue(&freqs[index]);
+ }
+ case EQ_PARAM_BAND_FREQ_RANGE: {
+ int32_t index;
+ if (OK != param.readFromParameter(&index)) {
+ break;
+ }
+
+ Parameter aidlParam =
+ VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandFrequencies));
+ const auto& bands = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::bandFrequencies,
+ std::vector<Equalizer::BandFrequency>));
+ for (const auto& band : bands) {
+ if (band.index == index) {
+ return (OK == param.writeToValue(&band.minMh) &&
+ OK == param.writeToValue(&band.maxMh))
+ ? OK
+ : BAD_VALUE;
+ }
+ }
+ break;
+ }
+ case EQ_PARAM_GET_BAND: {
+ int32_t freq;
+ if (OK != param.readFromParameter(&freq)) {
+ break;
+ }
+
+ Parameter aidlParam =
+ VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandFrequencies));
+ const auto& bands = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::bandFrequencies,
+ std::vector<Equalizer::BandFrequency>));
+ for (const auto& band : bands) {
+ if (freq >= band.minMh && freq <= band.maxMh) {
+ return param.writeToValue((uint16_t*)&band.index);
+ }
+ }
+ break;
+ }
+ case EQ_PARAM_CUR_PRESET: {
+ int32_t preset = VALUE_OR_RETURN_STATUS(getParameterPreset());
+ return param.writeToValue((uint16_t*)&preset);
+ }
+ case EQ_PARAM_GET_NUM_OF_PRESETS: {
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::presets));
+ const auto& presets = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::presets,
+ std::vector<Equalizer::Preset>));
+ uint16_t num = presets.size();
+ return param.writeToValue(&num);
+ }
+ case EQ_PARAM_GET_PRESET_NAME: {
+ std::string name = VALUE_OR_RETURN_STATUS(getParameterPresetName(param));
+ return param.writeToValue(name.c_str(), name.length());
+ }
+ case EQ_PARAM_PROPERTIES: {
+ int32_t preset = VALUE_OR_RETURN_STATUS(getParameterPreset());
+ if (OK != param.writeToValue((uint16_t*)&preset)) {
+ break;
+ }
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
+ std::vector<Equalizer::BandLevel> bandLevels =
+ VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::bandLevels,
+ std::vector<Equalizer::BandLevel>));
+ uint16_t bands = bandLevels.size();
+ if (OK != param.writeToValue(&bands)) {
+ break;
+ }
+ std::sort(bandLevels.begin(), bandLevels.end(),
+ [](const auto& a, const auto& b) { return a.index < b.index; });
+ for (const auto& level : bandLevels) {
+ if (status_t status = param.writeToValue((uint16_t*)&level.levelMb); status != OK) {
+ return status;
+ }
+ }
+ return OK;
+ }
+ default: {
+ VENDOR_EXTENSION_GET_AND_RETURN(Equalizer, equalizer, param);
+ }
+ }
+
+ param.setStatus(BAD_VALUE);
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
new file mode 100644
index 0000000..f94556c
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionEq : public EffectConversionHelperAidl {
+ public:
+ AidlConversionEq(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionEq() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+ ConversionResult<::aidl::android::hardware::audio::effect::Parameter> getAidlParameter(
+ ::aidl::android::hardware::audio::effect::Equalizer::Tag tag);
+ ConversionResult<int32_t> getParameterPreset();
+ ConversionResult<std::string> getParameterPresetName(utils::EffectParamWriter& param);
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp
new file mode 100644
index 0000000..73430ba
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionHapticGenerator"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_hapticgenerator.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionHapticGenerator.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::HapticGenerator;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionHapticGenerator::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case HG_PARAM_HAPTIC_INTENSITY: {
+ int32_t id = 0, scale;
+ if (OK != param.readFromValue(&id) || OK != param.readFromValue(&scale)) {
+ ALOGE("%s invalid intensity %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ HapticGenerator::HapticScale hpScale(
+ {.id = id, .scale = (HapticGenerator::VibratorScale)(scale)});
+ aidlParam = MAKE_SPECIFIC_PARAMETER(HapticGenerator, hapticGenerator, hapticScales,
+ {hpScale});
+ break;
+ }
+ case HG_PARAM_VIBRATOR_INFO: {
+ float resonantFrequencyHz, qFactor, maxAmplitude;
+ if (OK != param.readFromValue(&resonantFrequencyHz) ||
+ OK != param.readFromValue(&qFactor) || OK != param.readFromValue(&maxAmplitude)) {
+ ALOGE("%s invalid vibrator info %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ HapticGenerator::VibratorInformation info({.resonantFrequencyHz = resonantFrequencyHz,
+ .qFactor = qFactor,
+ .maxAmplitude = maxAmplitude});
+ aidlParam =
+ MAKE_SPECIFIC_PARAMETER(HapticGenerator, hapticGenerator, vibratorInfo, info);
+ break;
+ }
+ default: {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(HapticGenerator, hapticGenerator, vendor, ext);
+ break;
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+// No parameter to get for HapticGenerator
+status_t AidlConversionHapticGenerator::getParameter(EffectParamWriter& param) {
+ VENDOR_EXTENSION_GET_AND_RETURN(HapticGenerator, hapticGenerator, param);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
new file mode 100644
index 0000000..03114a5
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionHapticGenerator : public EffectConversionHelperAidl {
+ public:
+ AidlConversionHapticGenerator(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionHapticGenerator() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp
new file mode 100644
index 0000000..31eec65
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionLoudnessEnhancer"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_loudnessenhancer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionLoudnessEnhancer.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::hardware::audio::effect::LoudnessEnhancer;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionLoudnessEnhancer::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ int32_t gain = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&gain)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(LoudnessEnhancer, loudnessEnhancer, gainMb, gain);
+ break;
+ }
+ default: {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(LoudnessEnhancer, loudnessEnhancer, vendor, ext);
+ break;
+ }
+ }
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionLoudnessEnhancer::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ switch (type) {
+ case LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB: {
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(LoudnessEnhancer, loudnessEnhancerTag,
+ LoudnessEnhancer::gainMb);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ int32_t gain = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, LoudnessEnhancer, loudnessEnhancer, LoudnessEnhancer::gainMb,
+ std::decay_t<decltype(gain)>));
+ return param.writeToValue(&gain);
+ }
+ default: {
+ VENDOR_EXTENSION_GET_AND_RETURN(LoudnessEnhancer, loudnessEnhancer, param);
+ }
+ }
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
new file mode 100644
index 0000000..c0402f9
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionLoudnessEnhancer : public EffectConversionHelperAidl {
+ public:
+ AidlConversionLoudnessEnhancer(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionLoudnessEnhancer() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp
new file mode 100644
index 0000000..7c34ed7
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionNoiseSuppression"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_ns.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionNoiseSuppression.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::NoiseSuppression;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionNoiseSuppression::setParameter(EffectParamReader& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case NS_PARAM_LEVEL: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(NoiseSuppression, noiseSuppression, level,
+ static_cast<NoiseSuppression::Level>(value));
+ break;
+ }
+ case NS_PARAM_TYPE: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(NoiseSuppression, noiseSuppression, type,
+ static_cast<NoiseSuppression::Type>(value));
+ break;
+ }
+ default: {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(NoiseSuppression, noiseSuppression, vendor, ext);
+ break;
+ }
+ }
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionNoiseSuppression::getParameter(EffectParamWriter& param) {
+ uint32_t paramType = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(¶mType)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (paramType) {
+ case NS_PARAM_LEVEL: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(NoiseSuppression, noiseSuppressionTag,
+ NoiseSuppression::level);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ NoiseSuppression::Level level = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, NoiseSuppression, noiseSuppression,
+ NoiseSuppression::level, NoiseSuppression::Level));
+ value = static_cast<uint32_t>(level);
+ break;
+ }
+ case NS_PARAM_TYPE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(NoiseSuppression, noiseSuppressionTag,
+ NoiseSuppression::type);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ NoiseSuppression::Type nsType = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, NoiseSuppression, noiseSuppression,
+ NoiseSuppression::type, NoiseSuppression::Type));
+ value = static_cast<uint32_t>(nsType);
+ break;
+ }
+ default: {
+ VENDOR_EXTENSION_GET_AND_RETURN(NoiseSuppression, noiseSuppression, param);
+ }
+ }
+ return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
new file mode 100644
index 0000000..f51e13a
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionNoiseSuppression : public EffectConversionHelperAidl {
+ public:
+ AidlConversionNoiseSuppression(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionNoiseSuppression() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.cpp
new file mode 100644
index 0000000..e936aef
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionPresetReverb"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_presetreverb.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionPresetReverb.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::convertIntegral;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::PresetReverb;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionPresetReverb::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ if (type == REVERB_PARAM_PRESET) {
+ uint16_t value = 0;
+ if (OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid preset value %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ aidlParam = MAKE_SPECIFIC_PARAMETER(PresetReverb, presetReverb, preset,
+ static_cast<PresetReverb::Presets>(value));
+ } else {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(PresetReverb, presetReverb, vendor, ext);
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionPresetReverb::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0;
+ uint16_t value = 0;
+ ALOGE("%s enter %s", __func__, param.toString().c_str());
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ if (type == REVERB_PARAM_PRESET) {
+ Parameter aidlParam;
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(PresetReverb, presetReverbTag, PresetReverb::preset);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ auto aidlPreset = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, PresetReverb, presetReverb,
+ PresetReverb::preset, PresetReverb::Presets));
+ value = static_cast<uint16_t>(aidlPreset);
+ } else {
+ // handle vendor extension
+ VENDOR_EXTENSION_GET_AND_RETURN(PresetReverb, presetReverb, param);
+ }
+ return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
new file mode 100644
index 0000000..397d6e6
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionPresetReverb : public EffectConversionHelperAidl {
+ public:
+ AidlConversionPresetReverb(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionPresetReverb() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
new file mode 100644
index 0000000..eadd6c3
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionSpatializer"
+//#define LOG_NDEBUG 0
+
+#include <aidl/android/hardware/audio/effect/DefaultExtension.h>
+#include <aidl/android/hardware/audio/effect/VendorExtension.h>
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_spatializer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionSpatializer.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::DefaultExtension;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionSpatializer::setParameter(EffectParamReader& param) {
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_EffectParameterReader_ParameterExtension(param));
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionSpatializer::getParameter(EffectParamWriter& param) {
+ DefaultExtension defaultExt;
+ // read parameters into DefaultExtension vector<uint8_t>
+ if (OK != param.readFromParameter(defaultExt.bytes.data(), param.getParameterSize())) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+
+ VendorExtension idTag;
+ idTag.extension.setParcelable(defaultExt);
+ Parameter::Id id = UNION_MAKE(Parameter::Id, vendorEffectTag, idTag);
+ Parameter aidlParam;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ // copy the AIDL extension data back to effect_param_t
+ return VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_ParameterExtension_EffectParameterWriter(aidlParam,
+ param));
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
new file mode 100644
index 0000000..c44567c
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionSpatializer : public EffectConversionHelperAidl {
+ public:
+ AidlConversionSpatializer(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionSpatializer() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp
new file mode 100644
index 0000000..488d5cd
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#include <type_traits>
+#define LOG_TAG "AidlConversionVendorExtension"
+//#define LOG_NDEBUG 0
+
+#include <aidl/android/hardware/audio/effect/DefaultExtension.h>
+#include <aidl/android/hardware/audio/effect/VendorExtension.h>
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionVendorExtension.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::DefaultExtension;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+/**
+ * For all effect types we currently don't support, add a default extension implementation to use
+ * std::vector<uint8_t> to pass through all data in the format of effect_param_t (the data we got
+ * from libaudioclient for now).
+ * This logic will be removed after we adopt to same AIDL parameter union AIDL in libaudioclient,
+ * after that framework doesn't need to do any AIDL conversion, and the vendor extension can be
+ * pass down in Parameter as is.
+ */
+status_t AidlConversionVendorExtension::setParameter(EffectParamReader& param) {
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_EffectParameterReader_ParameterExtension(param));
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionVendorExtension::getParameter(EffectParamWriter& param) {
+ VendorExtension extId = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Param_VendorExtension(param));
+ Parameter::Id id = UNION_MAKE(Parameter::Id, vendorEffectTag, extId);
+ Parameter aidlParam;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ // copy the AIDL extension data back to effect_param_t
+ return VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_ParameterExtension_EffectParameterWriter(aidlParam,
+ param));
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
new file mode 100644
index 0000000..fd22e5c
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionVendorExtension : public EffectConversionHelperAidl {
+ public:
+ AidlConversionVendorExtension(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionVendorExtension() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp
new file mode 100644
index 0000000..c95c3a9
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2023 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionVirtualizer"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/aidl_effects_utils.h>
+#include <system/audio_effects/effect_virtualizer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionVirtualizer.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::Range;
+using ::aidl::android::hardware::audio::effect::Virtualizer;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionVirtualizer::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ if (OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case VIRTUALIZER_PARAM_STRENGTH: {
+ int16_t strength = 0;
+ if (OK != param.readFromValue(&strength)) {
+ ALOGE("%s invalid param %s for type %d", __func__, param.toString().c_str(), type);
+ return BAD_VALUE;
+ }
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Virtualizer, virtualizer, strengthPm, strength);
+ break;
+ }
+ case VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE: {
+ audio_devices_t deviceType;
+ if (OK != param.readFromValue(&deviceType)) {
+ ALOGE("%s invalid param %s for type %d", __func__, param.toString().c_str(), type);
+ return BAD_VALUE;
+ }
+ AudioDeviceDescription deviceDesc = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_devices_t_AudioDeviceDescription(
+ deviceType));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Virtualizer, virtualizer, device, deviceDesc);
+ break;
+ }
+ default: {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Virtualizer, virtualizer, vendor, ext);
+ break;
+ }
+ }
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionVirtualizer::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0;
+ if (OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED: {
+ // an invalid range indicates not setting support for this parameter
+ uint32_t support =
+ ::aidl::android::hardware::audio::effect::isRangeValid<Range::Tag::virtualizer>(
+ Virtualizer::strengthPm, mDesc.capability);
+ return param.writeToValue(&support);
+ }
+ case VIRTUALIZER_PARAM_STRENGTH: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Virtualizer, virtualizerTag,
+ Virtualizer::strengthPm);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ int16_t strength = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Virtualizer, virtualizer, Virtualizer::strengthPm, int32_t));
+ return param.writeToValue(&strength);
+ }
+ case VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES: {
+ audio_channel_mask_t mask;
+ audio_devices_t device;
+ if (OK != param.readFromParameter(&mask) || OK != param.readFromParameter(&device)) {
+ ALOGW("%s illegal param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Virtualizer::SpeakerAnglesPayload payload = {
+ .layout = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+ mask, false)),
+ .device = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_devices_t_AudioDeviceDescription(
+ device))};
+ Virtualizer::Id vId = UNION_MAKE(Virtualizer::Id, speakerAnglesPayload, payload);
+ Parameter::Id id = UNION_MAKE(Parameter::Id, virtualizerTag, vId);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ const auto& angles = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Virtualizer, virtualizer, Virtualizer::speakerAngles,
+ std::vector<Virtualizer::ChannelAngle>));
+ for (const auto& angle : angles) {
+ const audio_channel_mask_t chMask = ::aidl::android::
+ aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+ angle.channel, false);
+ ALOGW("%s aidl %d ch %d", __func__, angle.channel, chMask);
+ if (OK != param.writeToValue(&chMask) ||
+ OK != param.writeToValue(&angle.azimuthDegree) ||
+ OK != param.writeToValue(&angle.elevationDegree)) {
+ ALOGW("%s can't write angles to param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+ return OK;
+ }
+ case VIRTUALIZER_PARAM_VIRTUALIZATION_MODE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Virtualizer, virtualizerTag,
+ Virtualizer::device);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ AudioDeviceDescription device = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Virtualizer, virtualizer,
+ Virtualizer::device, AudioDeviceDescription));
+ const audio_devices_t deviceType = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioDeviceDescription_audio_devices_t(device));
+ return param.writeToValue(&deviceType);
+ }
+ default: {
+ VENDOR_EXTENSION_GET_AND_RETURN(Virtualizer, virtualizer, param);
+ }
+ }
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
new file mode 100644
index 0000000..91c0fcd
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionVirtualizer : public EffectConversionHelperAidl {
+ public:
+ AidlConversionVirtualizer(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionVirtualizer() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
new file mode 100644
index 0000000..2d5af59
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2023 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 <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionVisualizer"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_visualizer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionVisualizer.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::aidl::android::hardware::audio::effect::Visualizer;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionVisualizer::setParameter(EffectParamReader& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case VISUALIZER_PARAM_CAPTURE_SIZE: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, captureSamples, value);
+ break;
+ }
+ case VISUALIZER_PARAM_SCALING_MODE: {
+ Visualizer::ScalingMode mode = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_Parameter_Visualizer_uint32_ScalingMode(value));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, scalingMode, mode);
+ break;
+ }
+ case VISUALIZER_PARAM_LATENCY: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, latencyMs, value);
+ break;
+ }
+ case VISUALIZER_PARAM_MEASUREMENT_MODE: {
+ Visualizer::MeasurementMode mode = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(value));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, measurementMode, mode);
+ break;
+ }
+ default: {
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, vendor, ext);
+ break;
+ }
+ }
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionVisualizer::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(int32_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case VISUALIZER_PARAM_CAPTURE_SIZE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::captureSamples);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Visualizer, visualizer, Visualizer::captureSamples, int32_t));
+ mCaptureSize = value;
+ return param.writeToValue(&value);
+ }
+ case VISUALIZER_PARAM_SCALING_MODE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::scalingMode);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ Visualizer::ScalingMode mode = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Visualizer, visualizer,
+ Visualizer::scalingMode, Visualizer::ScalingMode));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_Visualizer_ScalingMode_uint32(mode));
+ return param.writeToValue(&value);
+ }
+ case VISUALIZER_PARAM_LATENCY: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::latencyMs);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = (int32_t)VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Visualizer, visualizer, Visualizer::latencyMs, int32_t));
+ return param.writeToValue(&value);
+ }
+ case VISUALIZER_PARAM_MEASUREMENT_MODE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::measurementMode);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ Visualizer::MeasurementMode mode = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Visualizer, visualizer, Visualizer::measurementMode,
+ Visualizer::MeasurementMode));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_Visualizer_MeasurementMode_uint32(mode));
+ return param.writeToValue(&value);
+ }
+ default: {
+ VENDOR_EXTENSION_GET_AND_RETURN(Visualizer, visualizer, param);
+ }
+ }
+}
+
+status_t AidlConversionVisualizer::visualizerCapture(uint32_t* replySize, void* pReplyData) {
+ if (!replySize || !pReplyData || *replySize != mCaptureSize) {
+ ALOGE("%s illegal param replySize %p pReplyData %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::captureSampleBuffer);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ const auto& samples = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Visualizer, visualizer,
+ Visualizer::captureSampleBuffer, std::vector<uint8_t>));
+ size_t len = std::min((size_t)*replySize, samples.size());
+ std::memcpy(pReplyData, samples.data(), *replySize = len);
+ return OK;
+}
+
+status_t AidlConversionVisualizer::visualizerMeasure(uint32_t* replySize, void* pReplyData) {
+ if (!replySize || !pReplyData || *replySize != 2 * sizeof(int32_t)) {
+ ALOGE("%s illegal param replySize %p pReplyData %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ Parameter aidlParam;
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag, Visualizer::measurement);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ const auto& measure = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Visualizer, visualizer, Visualizer::measurement, Visualizer::Measurement));
+ int32_t* reply = (int32_t *) pReplyData;
+ *reply++ = measure.rms;
+ *reply = measure.peak;
+ return OK;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
new file mode 100644
index 0000000..e380bc6
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionVisualizer : public EffectConversionHelperAidl {
+ public:
+ AidlConversionVisualizer(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionVisualizer() {}
+
+ private:
+ uint32_t mCaptureSize = 0;
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+ status_t visualizerCapture(uint32_t* replySize, void* pReplyData) override;
+ status_t visualizerMeasure(uint32_t* replySize, void* pReplyData) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/include/media/audiohal/AudioHalVersionInfo.h b/media/libaudiohal/include/media/audiohal/AudioHalVersionInfo.h
new file mode 100644
index 0000000..6e09463
--- /dev/null
+++ b/media/libaudiohal/include/media/audiohal/AudioHalVersionInfo.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 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 <string>
+#include <utility>
+#include <android/media/AudioHalVersion.h>
+
+namespace android::detail {
+
+class AudioHalVersionInfo : public android::media::AudioHalVersion {
+ public:
+ AudioHalVersionInfo(Type halType, int halMajor, int halMinor = 0) {
+ type = halType;
+ major = halMajor;
+ minor = halMinor;
+ }
+
+ Type getType() const { return type; }
+
+ int getMajorVersion() const { return major; }
+
+ int getMinorVersion() const { return minor; }
+
+ /** Keep HIDL version format as is for backward compatibility, only add prefix for AIDL. */
+ std::string toVersionString() const {
+ std::string versionStr =
+ android::internal::ToString(major) + "." + android::internal::ToString(minor);
+ if (type == Type::AIDL) {
+ return "aidl";
+ } else {
+ return versionStr;
+ }
+ }
+};
+
+} // namespace android
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index d27ad4c..c685345 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -21,7 +21,6 @@
#include <android/media/audio/common/AudioMMapPolicyType.h>
#include <error/Result.h>
#include <media/audiohal/EffectHalInterface.h>
-#include <media/MicrophoneInfo.h>
#include <system/audio.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -32,7 +31,7 @@
class StreamInHalInterface;
class StreamOutHalInterface;
-class DeviceHalInterface : public RefBase
+class DeviceHalInterface : public virtual RefBase
{
public:
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
@@ -107,7 +106,7 @@
virtual status_t releaseAudioPatch(audio_patch_handle_t patch) = 0;
// Fills the list of supported attributes for a given audio port.
- virtual status_t getAudioPort(struct audio_port *port) = 0;
+ virtual status_t getAudioPort(struct audio_port* port) = 0;
// Fills the list of supported attributes for a given audio port.
virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
@@ -116,7 +115,8 @@
virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
// List microphones
- virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
+ virtual status_t getMicrophones(
+ std::vector<audio_microphone_characteristic_t>* microphones) = 0;
virtual status_t addDeviceEffect(
audio_port_handle_t device, sp<EffectHalInterface> effect) = 0;
@@ -125,12 +125,16 @@
virtual status_t getMmapPolicyInfos(
media::audio::common::AudioMMapPolicyType policyType,
- std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) = 0;
+ std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) = 0;
virtual int32_t getAAudioMixerBurstCount() = 0;
virtual int32_t getAAudioHardwareBurstMinUsec() = 0;
+ virtual int32_t supportsBluetoothVariableLatency(bool* supports) = 0;
// Update the connection status of an external device.
- virtual status_t setConnectedState(const struct audio_port_v7 *port, bool connected) = 0;
+ virtual status_t setConnectedState(const struct audio_port_v7* port, bool connected) {
+ ALOGE("%s override me port %p connected %d", __func__, port, connected);
+ return OK;
+ }
virtual error::Result<audio_hw_sync_t> getHwAvSync() = 0;
diff --git a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
index 17010e6..be3a723 100644
--- a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
@@ -14,14 +14,15 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_DEVICES_FACTORY_HAL_INTERFACE_H
-#define ANDROID_HARDWARE_DEVICES_FACTORY_HAL_INTERFACE_H
+#pragma once
#include <media/audiohal/DeviceHalInterface.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <vector>
+#include "AudioHalVersionInfo.h"
+
namespace android {
class DevicesFactoryHalCallback : public RefBase
@@ -43,7 +44,7 @@
// The callback can be only set once.
virtual status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) = 0;
- virtual float getHalVersion() const = 0;
+ virtual android::detail::AudioHalVersionInfo getHalVersion() const = 0;
static sp<DevicesFactoryHalInterface> create();
@@ -55,5 +56,3 @@
};
} // namespace android
-
-#endif // ANDROID_HARDWARE_DEVICES_FACTORY_HAL_INTERFACE_H
diff --git a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
index 3e505bd..d740fe9 100644
--- a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
@@ -14,14 +14,16 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
-#define ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
+#pragma once
#include <media/audiohal/EffectHalInterface.h>
#include <system/audio_effect.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
+#include "AudioHalVersionInfo.h"
+#include "FactoryHal.h"
+
namespace android {
class EffectsFactoryHalInterface : public RefBase
@@ -49,16 +51,16 @@
virtual status_t dumpEffects(int fd) = 0;
- virtual float getHalVersion() = 0;
-
static sp<EffectsFactoryHalInterface> create();
virtual status_t allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) = 0;
virtual status_t mirrorBuffer(void* external, size_t size,
sp<EffectBufferHalInterface>* buffer) = 0;
+ virtual android::detail::AudioHalVersionInfo getHalVersion() const = 0;
+
// Helper function to compare effect uuid to EFFECT_UUID_NULL.
- static bool isNullUuid(const effect_uuid_t *pEffectUuid);
+ static bool isNullUuid(const effect_uuid_t* pEffectUuid);
protected:
// Subclasses can not be constructed directly by clients.
@@ -68,5 +70,3 @@
};
} // namespace android
-
-#endif // ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
diff --git a/media/libaudiohal/include/media/audiohal/FactoryHalHidl.h b/media/libaudiohal/include/media/audiohal/FactoryHal.h
similarity index 62%
rename from media/libaudiohal/include/media/audiohal/FactoryHalHidl.h
rename to media/libaudiohal/include/media/audiohal/FactoryHal.h
index 866dd3e..4776d98 100644
--- a/media/libaudiohal/include/media/audiohal/FactoryHalHidl.h
+++ b/media/libaudiohal/include/media/audiohal/FactoryHal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -14,24 +14,19 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
-#define ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
+#pragma once
#include <string>
#include <utility>
-
#include <utils/StrongPointer.h>
+#include "AudioHalVersionInfo.h"
+
namespace android {
-// The pair of the interface's package name and the interface name,
-// e.g. <"android.hardware.audio", "IDevicesFactory">.
-// Splitting is used for easier construction of versioned names (FQNs).
-using InterfaceName = std::pair<std::string, std::string>;
-
namespace detail {
-void* createPreferredImpl(const InterfaceName& iface, const InterfaceName& siblingIface);
+void* createPreferredImpl(bool isCore);
} // namespace detail
@@ -45,17 +40,12 @@
* shared libraries the loader function considers which interface among two has the most
* recent version. Thus, a pair of interface names must be passed in.
*
- * @param iface the interface that needs to be created.
- * @param siblingIface the interface which occupies the same shared library.
+ * @param isCore Indicating if this is audio Core HAL service interface.
* @return the preferred available implementation or nullptr if none are available.
*/
+
template <class Interface>
-static sp<Interface> createPreferredImpl(
- const InterfaceName& iface, const InterfaceName& siblingIface) {
- return sp<Interface>{
- static_cast<Interface*>(detail::createPreferredImpl(iface, siblingIface))};
+static sp<Interface> createPreferredImpl(bool isCore) {
+ return sp<Interface>{static_cast<Interface*>(detail::createPreferredImpl(isCore))};
}
-
} // namespace android
-
-#endif // ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index 1d52b7d..a780a17 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -19,8 +19,8 @@
#include <vector>
+#include <android/media/MicrophoneInfoFw.h>
#include <media/audiohal/EffectHalInterface.h>
-#include <media/MicrophoneInfo.h>
#include <system/audio.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -110,8 +110,8 @@
virtual void onError() {}
protected:
- StreamOutHalInterfaceCallback() {}
- virtual ~StreamOutHalInterfaceCallback() {}
+ StreamOutHalInterfaceCallback() = default;
+ virtual ~StreamOutHalInterfaceCallback() = default;
};
class StreamOutHalInterfaceEventCallback : public virtual RefBase {
@@ -119,8 +119,8 @@
virtual void onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs) = 0;
protected:
- StreamOutHalInterfaceEventCallback() {}
- virtual ~StreamOutHalInterfaceEventCallback() {}
+ StreamOutHalInterfaceEventCallback() = default;
+ virtual ~StreamOutHalInterfaceEventCallback() = default;
};
class StreamOutHalInterfaceLatencyModeCallback : public virtual RefBase {
@@ -131,8 +131,8 @@
virtual void onRecommendedLatencyModeChanged(std::vector<audio_latency_mode_t> modes) = 0;
protected:
- StreamOutHalInterfaceLatencyModeCallback() {}
- virtual ~StreamOutHalInterfaceLatencyModeCallback() {}
+ StreamOutHalInterfaceLatencyModeCallback() = default;
+ virtual ~StreamOutHalInterfaceLatencyModeCallback() = default;
};
class StreamOutHalInterface : public virtual StreamHalInterface {
@@ -273,7 +273,7 @@
virtual status_t getCapturePosition(int64_t *frames, int64_t *time) = 0;
// Get active microphones
- virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
+ virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) = 0;
// Set direction for capture processing
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t) = 0;
diff --git a/media/libaudiohal/tests/Android.bp b/media/libaudiohal/tests/Android.bp
new file mode 100644
index 0000000..2f78dd0
--- /dev/null
+++ b/media/libaudiohal/tests/Android.bp
@@ -0,0 +1,55 @@
+// Copyright (C) 2022 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_license"],
+}
+
+cc_test {
+ name: "EffectsFactoryHalInterfaceTest",
+ test_suites: ["device-tests"],
+
+ srcs: [
+ "EffectsFactoryHalInterface_test.cpp",
+ ],
+
+ defaults: [
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ "-DBACKEND_NDK",
+ ],
+
+ shared_libs: [
+ "audioclient-types-aidl-cpp",
+ "libaudio_aidl_conversion_common_ndk",
+ "libaudiohal",
+ "liblog",
+ "libutils",
+ "libvibrator",
+ ],
+
+ header_libs: [
+ "libaudiohal_headers",
+ ],
+}
diff --git a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
new file mode 100644
index 0000000..c076ccc
--- /dev/null
+++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2022 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
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <memory>
+#include <utility>
+#define LOG_TAG "EffectsFactoryHalInterfaceTest"
+
+#include <aidl/android/media/audio/common/AudioUuid.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <system/audio_effects/audio_effects_utils.h>
+#include <system/audio_effects/effect_aec.h>
+#include <system/audio_effects/effect_agc.h>
+#include <system/audio_effects/effect_agc2.h>
+#include <system/audio_effects/effect_bassboost.h>
+#include <system/audio_effects/effect_downmix.h>
+#include <system/audio_effects/effect_dynamicsprocessing.h>
+#include <system/audio_effects/effect_hapticgenerator.h>
+#include <system/audio_effects/effect_loudnessenhancer.h>
+#include <system/audio_effects/effect_ns.h>
+#include <system/audio_effect.h>
+
+#include <gtest/gtest.h>
+#include <utils/RefBase.h>
+#include <vibrator/ExternalVibrationUtils.h>
+
+namespace android {
+
+using effect::utils::EffectParamReader;
+using effect::utils::EffectParamWriter;
+using ::aidl::android::media::audio::common::AudioUuid;
+
+// EffectsFactoryHalInterface
+TEST(libAudioHalTest, createEffectsFactoryHalInterface) {
+ ASSERT_NE(nullptr, EffectsFactoryHalInterface::create());
+}
+
+TEST(libAudioHalTest, queryNumberEffects) {
+ auto factory = EffectsFactoryHalInterface::create();
+ ASSERT_NE(nullptr, factory);
+
+ uint32_t numEffects = 0;
+ EXPECT_EQ(OK, factory->queryNumberEffects(&numEffects));
+ EXPECT_NE(0ul, numEffects);
+}
+
+TEST(libAudioHalTest, getDescriptorByNumber) {
+ auto factory = EffectsFactoryHalInterface::create();
+ ASSERT_NE(nullptr, factory);
+
+ uint32_t numEffects = 0;
+ EXPECT_EQ(OK, factory->queryNumberEffects(&numEffects));
+ EXPECT_NE(0ul, numEffects);
+
+ effect_descriptor_t desc;
+ for (uint32_t i = 0; i < numEffects; i++) {
+ EXPECT_EQ(OK, factory->getDescriptor(i, &desc));
+ }
+}
+
+TEST(libAudioHalTest, createEffect) {
+ auto factory = EffectsFactoryHalInterface::create();
+ ASSERT_NE(nullptr, factory);
+
+ uint32_t numEffects = 0;
+ EXPECT_EQ(OK, factory->queryNumberEffects(&numEffects));
+ EXPECT_NE(0ul, numEffects);
+
+ effect_descriptor_t desc;
+ for (uint32_t i = 0; i < numEffects; i++) {
+ sp<EffectHalInterface> interface;
+ EXPECT_EQ(OK, factory->getDescriptor(i, &desc));
+ EXPECT_EQ(OK, factory->createEffect(&desc.uuid, 1 /* sessionId */, 1 /* ioId */,
+ 1 /* deviceId */, &interface));
+ }
+}
+
+TEST(libAudioHalTest, getHalVersion) {
+ auto factory = EffectsFactoryHalInterface::create();
+ ASSERT_NE(nullptr, factory);
+
+ auto version = factory->getHalVersion();
+ EXPECT_NE(0, version.getMajorVersion());
+}
+
+class EffectParamCombination {
+ public:
+ template <typename P, typename V>
+ void init(const P& p, const V& v, size_t len) {
+ setBuffer.resize(sizeof(effect_param_t) + sizeof(p) + sizeof(v) + 4);
+ getBuffer.resize(sizeof(effect_param_t) + sizeof(p) + len + 4);
+ expectBuffer.resize(sizeof(effect_param_t) + sizeof(p) + len + 4);
+ parameterSet =
+ std::make_shared<EffectParamReader>(createEffectParam(setBuffer.data(), p, v));
+ parameterGet =
+ std::make_shared<EffectParamReader>(createEffectParam(getBuffer.data(), p, v));
+ parameterExpect =
+ std::make_shared<EffectParamReader>(createEffectParam(expectBuffer.data(), p, v));
+ valueSize = len;
+ }
+
+ std::shared_ptr<EffectParamReader> parameterSet; /* setParameter */
+ std::shared_ptr<EffectParamReader> parameterGet; /* getParameter */
+ std::shared_ptr<EffectParamReader> parameterExpect; /* expected from getParameter */
+ size_t valueSize; /* ValueSize expect to write in reply data buffer */
+
+ private:
+ std::vector<uint8_t> setBuffer;
+ std::vector<uint8_t> getBuffer;
+ std::vector<uint8_t> expectBuffer;
+
+ template <typename P, typename V>
+ EffectParamReader createEffectParam(void* buf, const P& p, const V& v) {
+ effect_param_t* paramRet = (effect_param_t*)buf;
+ paramRet->psize = sizeof(P);
+ paramRet->vsize = sizeof(V);
+ EffectParamWriter writer(*paramRet);
+ EXPECT_EQ(OK, writer.writeToParameter(&p));
+ EXPECT_EQ(OK, writer.writeToValue(&v));
+ writer.finishValueWrite();
+ return writer;
+ }
+};
+
+template <typename P, typename V>
+std::shared_ptr<EffectParamCombination> createEffectParamCombination(const P& p, const V& v,
+ size_t len) {
+ auto comb = std::make_shared<EffectParamCombination>();
+ comb->init(p, v, len);
+ return comb;
+}
+
+enum ParamName { TUPLE_UUID, TUPLE_PARAM_COMBINATION };
+using EffectParamTestTuple =
+ std::tuple<const effect_uuid_t* /* type UUID */, std::shared_ptr<EffectParamCombination>>;
+
+static const effect_uuid_t EXTEND_EFFECT_TYPE_UUID = {
+ 0xfa81dbde, 0x588b, 0x11ed, 0x9b6a, {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+
+std::vector<EffectParamTestTuple> testPairs = {
+ std::make_tuple(FX_IID_AEC,
+ createEffectParamCombination(AEC_PARAM_ECHO_DELAY, 0xff /* echoDelayMs */,
+ sizeof(int32_t) /* returnValueSize */)),
+ std::make_tuple(FX_IID_AGC,
+ createEffectParamCombination(AGC_PARAM_TARGET_LEVEL, 20 /* targetLevel */,
+ sizeof(int16_t) /* returnValueSize */)),
+ std::make_tuple(FX_IID_AGC2, createEffectParamCombination(
+ AGC2_PARAM_FIXED_DIGITAL_GAIN, 15 /* digitalGainDb */,
+ sizeof(int32_t) /* returnValueSize */)),
+ std::make_tuple(SL_IID_BASSBOOST,
+ createEffectParamCombination(BASSBOOST_PARAM_STRENGTH, 20 /* strength */,
+ sizeof(int32_t) /* returnValueSize */)),
+ std::make_tuple(EFFECT_UIID_DOWNMIX,
+ createEffectParamCombination(DOWNMIX_PARAM_TYPE, DOWNMIX_TYPE_FOLD,
+ sizeof(int16_t) /* returnValueSize */)),
+ std::make_tuple(SL_IID_DYNAMICSPROCESSING,
+ createEffectParamCombination(
+ std::array<uint32_t, 2>({DP_PARAM_INPUT_GAIN, 0 /* channel */}),
+ 30 /* gainDb */, sizeof(int32_t) /* returnValueSize */)),
+ std::make_tuple(
+ FX_IID_HAPTICGENERATOR,
+ createEffectParamCombination(
+ HG_PARAM_HAPTIC_INTENSITY,
+ std::array<uint32_t, 2>(
+ {1, uint32_t(::android::os::HapticScale::HIGH) /* scale */}),
+ 0 /* returnValueSize */)),
+ std::make_tuple(
+ FX_IID_LOUDNESS_ENHANCER,
+ createEffectParamCombination(LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB, 5 /* gain */,
+ sizeof(int32_t) /* returnValueSize */)),
+ std::make_tuple(FX_IID_NS,
+ createEffectParamCombination(NS_PARAM_LEVEL, 1 /* level */,
+ sizeof(int32_t) /* returnValueSize */)),
+ std::make_tuple(&EXTEND_EFFECT_TYPE_UUID,
+ createEffectParamCombination(1, 0xbead, sizeof(int32_t)))};
+
+class libAudioHalEffectParamTest : public ::testing::TestWithParam<EffectParamTestTuple> {
+ public:
+ libAudioHalEffectParamTest()
+ : mParamTuple(GetParam()),
+ mFactory(EffectsFactoryHalInterface::create()),
+ mTypeUuid(std::get<TUPLE_UUID>(mParamTuple)),
+ mCombination(std::get<TUPLE_PARAM_COMBINATION>(mParamTuple)),
+ mExpectedValue([&]() {
+ std::vector<uint8_t> expectData(mCombination->valueSize);
+ mCombination->parameterExpect->readFromValue(expectData.data(),
+ mCombination->valueSize);
+ return expectData;
+ }()),
+ mDescs([&]() {
+ std::vector<effect_descriptor_t> descs;
+ if (mFactory && mTypeUuid && OK == mFactory->getDescriptors(mTypeUuid, &descs)) {
+ return descs;
+ }
+ return descs;
+ }()) {}
+
+ void SetUp() override {
+ ASSERT_NE(0ul, mDescs.size());
+ for (const auto& desc : mDescs) {
+ sp<EffectHalInterface> interface = createEffectHal(desc);
+ ASSERT_NE(nullptr, interface);
+ mHalInterfaces.push_back(interface);
+ }
+ }
+
+ void initEffect(const sp<EffectHalInterface>& interface) {
+ uint32_t initReply = 0;
+ uint32_t initReplySize = sizeof(initReply);
+ ASSERT_EQ(OK, interface->command(EFFECT_CMD_INIT, 0, nullptr, &initReplySize, &initReply));
+ }
+
+ void TearDown() override {
+ for (auto& interface : mHalInterfaces) {
+ interface->close();
+ }
+ }
+
+ sp<EffectHalInterface> createEffectHal(const effect_descriptor_t& desc) {
+ sp<EffectHalInterface> interface = nullptr;
+ if (0 == std::memcmp(&desc.type, mTypeUuid, sizeof(effect_uuid_t)) &&
+ OK == mFactory->createEffect(&desc.uuid, 1 /* sessionId */, 1 /* ioId */,
+ 1 /* deviceId */, &interface)) {
+ return interface;
+ }
+ return nullptr;
+ }
+
+ void setAndGetParameter(const sp<EffectHalInterface>& interface) {
+ uint32_t replySize = sizeof(uint32_t);
+ uint8_t reply[replySize];
+ auto parameterSet = mCombination->parameterSet;
+ ASSERT_EQ(OK,
+ interface->command(EFFECT_CMD_SET_PARAM, (uint32_t)parameterSet->getTotalSize(),
+ const_cast<effect_param_t*>(¶meterSet->getEffectParam()),
+ &replySize, &reply))
+ << parameterSet->toString();
+ ASSERT_EQ(replySize, sizeof(uint32_t));
+
+ effect_param_t* getParam =
+ const_cast<effect_param_t*>(&mCombination->parameterGet->getEffectParam());
+ size_t maxReplySize = mCombination->valueSize + sizeof(effect_param_t) +
+ sizeof(parameterSet->getPaddedParameterSize());
+ replySize = maxReplySize;
+ EXPECT_EQ(OK,
+ interface->command(EFFECT_CMD_GET_PARAM, (uint32_t)parameterSet->getTotalSize(),
+ const_cast<effect_param_t*>(¶meterSet->getEffectParam()),
+ &replySize, getParam));
+ EffectParamReader parameterGet(*getParam);
+ EXPECT_EQ(replySize, parameterGet.getTotalSize()) << parameterGet.toString();
+ if (mCombination->valueSize) {
+ std::vector<uint8_t> response(mCombination->valueSize);
+ EXPECT_EQ(OK, parameterGet.readFromValue(response.data(), mCombination->valueSize))
+ << " try get valueSize " << mCombination->valueSize << " from "
+ << parameterGet.toString();
+ EXPECT_EQ(response, mExpectedValue);
+ }
+ }
+
+ const EffectParamTestTuple mParamTuple;
+ const sp<EffectsFactoryHalInterface> mFactory;
+ const effect_uuid_t* mTypeUuid;
+ std::shared_ptr<EffectParamCombination> mCombination;
+ const std::vector<uint8_t> mExpectedValue;
+ const std::vector<effect_descriptor_t> mDescs;
+ std::vector<sp<EffectHalInterface>> mHalInterfaces;
+};
+
+TEST_P(libAudioHalEffectParamTest, setAndGetParam) {
+ for (auto& interface : mHalInterfaces) {
+ EXPECT_NO_FATAL_FAILURE(initEffect(interface));
+ EXPECT_NO_FATAL_FAILURE(setAndGetParameter(interface));
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ libAudioHalEffectParamTest, libAudioHalEffectParamTest, ::testing::ValuesIn(testPairs),
+ [](const testing::TestParamInfo<libAudioHalEffectParamTest::ParamType>& info) {
+ AudioUuid uuid = ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(
+ *std::get<TUPLE_UUID>(info.param))
+ .value();
+ std::string name = "UUID_" + uuid.toString();
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(libAudioHalEffectParamTest);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+
+// TODO: b/263986405 Add multi-thread testing
+
+} // namespace android
diff --git a/media/libaudioprocessing/tests/test-resampler.cpp b/media/libaudioprocessing/tests/test-resampler.cpp
index f178bde..2166a83 100644
--- a/media/libaudioprocessing/tests/test-resampler.cpp
+++ b/media/libaudioprocessing/tests/test-resampler.cpp
@@ -18,6 +18,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
+#include <memory>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -474,7 +475,7 @@
// mono takes left channel only (out of stereo output pair)
// stereo and multichannel preserve all channels.
int32_t* out = (int32_t*) output_vaddr;
- int16_t* convert = (int16_t*) malloc(output_frames * channels * sizeof(int16_t));
+ std::unique_ptr<int16_t[]> convert(new int16_t[output_frames * channels]);
const int volumeShift = 12; // shift requirement for Q4.27 to Q.15
// round to half towards zero and saturate at int16 (non-dithered)
@@ -509,7 +510,7 @@
perror(file_out);
return EXIT_FAILURE;
}
- (void) sf_writef_short(sf, convert, output_frames);
+ (void) sf_writef_short(sf, convert.get(), output_frames);
sf_close(sf);
return EXIT_SUCCESS;
diff --git a/media/libeffects/downmix/Android.bp b/media/libeffects/downmix/Android.bp
index abe622d..a5259aa 100644
--- a/media/libeffects/downmix/Android.bp
+++ b/media/libeffects/downmix/Android.bp
@@ -47,3 +47,30 @@
"libhardware_headers",
],
}
+
+cc_library_shared {
+ name: "libdownmixaidl",
+ srcs: [
+ "aidl/EffectDownmix.cpp",
+ "aidl/DownmixContext.cpp",
+ ":effectCommonFile",
+ ],
+ defaults: [
+ "aidlaudioservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ header_libs: [
+ "libaudioeffects",
+ "libhardware_headers"
+ ],
+ shared_libs: [
+ "libaudioutils",
+ "libcutils",
+ "liblog",
+ ],
+ relative_install_path: "soundfx",
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/media/libeffects/downmix/aidl/DownmixContext.cpp b/media/libeffects/downmix/aidl/DownmixContext.cpp
new file mode 100644
index 0000000..ac893d8
--- /dev/null
+++ b/media/libeffects/downmix/aidl/DownmixContext.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_DownmixContext"
+
+#include <android-base/logging.h>
+
+#include "DownmixContext.h"
+
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::common::getChannelCount;
+using aidl::android::media::audio::common::AudioChannelLayout;
+
+namespace aidl::android::hardware::audio::effect {
+
+DownmixContext::DownmixContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ mState = DOWNMIX_STATE_UNINITIALIZED;
+ init_params(common);
+}
+
+DownmixContext::~DownmixContext() {
+ LOG(DEBUG) << __func__;
+ mState = DOWNMIX_STATE_UNINITIALIZED;
+}
+
+RetCode DownmixContext::enable() {
+ LOG(DEBUG) << __func__;
+ if (mState != DOWNMIX_STATE_INITIALIZED) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = DOWNMIX_STATE_ACTIVE;
+ return RetCode::SUCCESS;
+}
+
+RetCode DownmixContext::disable() {
+ LOG(DEBUG) << __func__;
+ if (mState != DOWNMIX_STATE_ACTIVE) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = DOWNMIX_STATE_INITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+void DownmixContext::reset() {
+ LOG(DEBUG) << __func__;
+ disable();
+ resetBuffer();
+}
+
+IEffect::Status DownmixContext::lvmProcess(float* in, float* out, int samples) {
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+ IEffect::Status status = {EX_ILLEGAL_ARGUMENT, 0, 0};
+
+ if (in == nullptr || out == nullptr || getInputFrameSize() != getOutputFrameSize() ||
+ getInputFrameSize() == 0) {
+ return status;
+ }
+
+ status = {EX_ILLEGAL_STATE, 0, 0};
+ if (mState == DOWNMIX_STATE_UNINITIALIZED) {
+ LOG(ERROR) << __func__ << "Trying to use an uninitialized downmixer";
+ return status;
+ } else if (mState == DOWNMIX_STATE_INITIALIZED) {
+ LOG(ERROR) << __func__ << "Trying to use a non-configured downmixer";
+ return status;
+ }
+
+ LOG(DEBUG) << __func__ << " start processing";
+ bool accumulate = false;
+ int frames = samples * sizeof(float) / getInputFrameSize();
+ if (mType == Downmix::Type::STRIP) {
+ int inputChannelCount = getChannelCount(mChMask);
+ while (frames) {
+ if (accumulate) {
+ out[0] = std::clamp(out[0] + in[0], -1.f, 1.f);
+ out[1] = std::clamp(out[1] + in[1], -1.f, 1.f);
+ } else {
+ out[0] = in[0];
+ out[1] = in[1];
+ }
+ in += inputChannelCount;
+ out += 2;
+ frames--;
+ }
+ } else {
+ int chMask = mChMask.get<AudioChannelLayout::layoutMask>();
+ if (!mChannelMix.process(in, out, frames, accumulate, (audio_channel_mask_t)chMask)) {
+ LOG(ERROR) << "Multichannel configuration " << mChMask.toString()
+ << " is not supported";
+ return status;
+ }
+ }
+ LOG(DEBUG) << __func__ << " done processing";
+ return {STATUS_OK, samples, samples};
+}
+
+void DownmixContext::init_params(const Parameter::Common& common) {
+ // when configuring the effect, do not allow a blank or unsupported channel mask
+ AudioChannelLayout channelMask = common.input.base.channelMask;
+ if (isChannelMaskValid(channelMask)) {
+ LOG(ERROR) << "Downmix_Configure error: input channel mask " << channelMask.toString()
+ << " not supported";
+ } else {
+ mType = Downmix::Type::FOLD;
+ mChMask = channelMask;
+ mState = DOWNMIX_STATE_INITIALIZED;
+ }
+}
+
+bool DownmixContext::isChannelMaskValid(AudioChannelLayout channelMask) {
+ if (channelMask.getTag() == AudioChannelLayout::layoutMask) return false;
+ int chMask = channelMask.get<AudioChannelLayout::layoutMask>();
+ // check against unsupported channels (up to FCC_26)
+ constexpr uint32_t MAXIMUM_CHANNEL_MASK = AudioChannelLayout::LAYOUT_22POINT2 |
+ AudioChannelLayout::CHANNEL_FRONT_WIDE_LEFT |
+ AudioChannelLayout::CHANNEL_FRONT_WIDE_RIGHT;
+ if (chMask & ~MAXIMUM_CHANNEL_MASK) {
+ LOG(ERROR) << "Unsupported channels in " << (chMask & ~MAXIMUM_CHANNEL_MASK);
+ return false;
+ }
+ return true;
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/downmix/aidl/DownmixContext.h b/media/libeffects/downmix/aidl/DownmixContext.h
new file mode 100644
index 0000000..9a9f2da
--- /dev/null
+++ b/media/libeffects/downmix/aidl/DownmixContext.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 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 "effect-impl/EffectContext.h"
+
+#include <audio_utils/ChannelMix.h>
+
+namespace aidl::android::hardware::audio::effect {
+
+enum DownmixState {
+ DOWNMIX_STATE_UNINITIALIZED,
+ DOWNMIX_STATE_INITIALIZED,
+ DOWNMIX_STATE_ACTIVE,
+};
+
+class DownmixContext final : public EffectContext {
+ public:
+ DownmixContext(int statusDepth, const Parameter::Common& common);
+ ~DownmixContext();
+ RetCode enable();
+ RetCode disable();
+ void reset();
+
+ RetCode setDmType(Downmix::Type type) {
+ mType = type;
+ return RetCode::SUCCESS;
+ }
+ Downmix::Type getDmType() const { return mType; }
+
+ RetCode setOutputDevice(
+ const std::vector<::aidl::android::media::audio::common::AudioDeviceDescription>&
+ device) override {
+ // FIXME change type if playing on headset vs speaker
+ mOutputDevice = device;
+ return RetCode::SUCCESS;
+ }
+
+ IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+ private:
+ DownmixState mState;
+ Downmix::Type mType;
+ ::aidl::android::media::audio::common::AudioChannelLayout mChMask;
+ ::android::audio_utils::channels::ChannelMix mChannelMix;
+
+ // Common Params
+ void init_params(const Parameter::Common& common);
+ bool isChannelMaskValid(::aidl::android::media::audio::common::AudioChannelLayout channelMask);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/downmix/aidl/EffectDownmix.cpp b/media/libeffects/downmix/aidl/EffectDownmix.cpp
new file mode 100644
index 0000000..7068c5c
--- /dev/null
+++ b/media/libeffects/downmix/aidl/EffectDownmix.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_DownmixImpl"
+
+#include <android-base/logging.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "EffectDownmix.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::DownmixImpl;
+using aidl::android::hardware::audio::effect::getEffectImplUuidDownmix;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidDownmix()) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<DownmixImpl>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidDownmix()) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ *_aidl_return = DownmixImpl::kDescriptor;
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string DownmixImpl::kEffectName = "Multichannel Downmix To Stereo";
+const Descriptor DownmixImpl::kDescriptor = {
+ .common = {.id = {.type = getEffectTypeUuidDownmix(),
+ .uuid = getEffectImplUuidDownmix(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT, .insert = Flags::Insert::FIRST},
+ .name = DownmixImpl::kEffectName,
+ .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus DownmixImpl::getDescriptor(Descriptor* _aidl_return) {
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DownmixImpl::setParameterCommon(const Parameter& param) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto tag = param.getTag();
+ switch (tag) {
+ case Parameter::common:
+ RETURN_IF(mContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setCommFailed");
+ break;
+ case Parameter::deviceDescription:
+ RETURN_IF(mContext->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
+ break;
+ case Parameter::mode:
+ RETURN_IF(mContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setModeFailed");
+ break;
+ case Parameter::source:
+ RETURN_IF(mContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setSourceFailed");
+ break;
+ case Parameter::volumeStereo:
+ RETURN_IF(mContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed");
+ break;
+ default: {
+ LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commonParamNotSupported");
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DownmixImpl::commandImpl(CommandId command) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (command) {
+ case CommandId::START:
+ mContext->enable();
+ break;
+ case CommandId::STOP:
+ mContext->disable();
+ break;
+ case CommandId::RESET:
+ mContext->reset();
+ break;
+ default:
+ LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commandIdNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DownmixImpl::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::downmix != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& dmParam = specific.get<Parameter::Specific::downmix>();
+ auto tag = dmParam.getTag();
+
+ switch (tag) {
+ case Downmix::type: {
+ RETURN_IF(mContext->setDmType(dmParam.get<Downmix::type>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setTypeFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "DownmixTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus DownmixImpl::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::downmixTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto dmId = id.get<Parameter::Id::downmixTag>();
+ auto dmIdTag = dmId.getTag();
+ switch (dmIdTag) {
+ case Downmix::Id::commonTag:
+ return getParameterDownmix(dmId.get<Downmix::Id::commonTag>(), specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(dmIdTag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "DownmixTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus DownmixImpl::getParameterDownmix(const Downmix::Tag& tag,
+ Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ Downmix dmParam;
+ switch (tag) {
+ case Downmix::type: {
+ dmParam.set<Downmix::type>(mContext->getDmType());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "DownmixTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::downmix>(dmParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> DownmixImpl::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+
+ mContext = std::make_shared<DownmixContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode DownmixImpl::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status DownmixImpl::effectProcessImpl(float* in, float* out, int sampleToProcess) {
+ if (!mContext) {
+ LOG(ERROR) << __func__ << " nullContext";
+ return {EX_NULL_POINTER, 0, 0};
+ }
+ return mContext->lvmProcess(in, out, sampleToProcess);
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/downmix/aidl/EffectDownmix.h b/media/libeffects/downmix/aidl/EffectDownmix.h
new file mode 100644
index 0000000..812d26b
--- /dev/null
+++ b/media/libeffects/downmix/aidl/EffectDownmix.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 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 <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <audio_effects/effect_downmix.h>
+
+#include "DownmixContext.h"
+#include "effect-impl/EffectImpl.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class DownmixImpl final : public EffectImpl {
+ public:
+ static const std::string kEffectName;
+ static const Descriptor kDescriptor;
+ DownmixImpl() { LOG(DEBUG) << __func__; }
+ ~DownmixImpl() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterCommon(const Parameter& param) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ std::shared_ptr<EffectContext> getContext() override { return mContext; }
+ std::string getEffectName() override { return kEffectName; }
+
+ private:
+ std::shared_ptr<DownmixContext> mContext;
+ ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/dynamicsproc/Android.bp b/media/libeffects/dynamicsproc/Android.bp
index 84131a4..736a086 100644
--- a/media/libeffects/dynamicsproc/Android.bp
+++ b/media/libeffects/dynamicsproc/Android.bp
@@ -32,34 +32,67 @@
],
}
+cc_defaults {
+ name : "dynamicsprocessingdefaults",
+ srcs: [
+ "dsp/DPBase.cpp",
+ "dsp/DPFrequency.cpp",
+ ],
+
+ shared_libs: [
+ "libaudioutils",
+ "libbase",
+ "liblog",
+ "libutils",
+ ],
+ header_libs: [
+ "libaudioeffects",
+ "libeigen",
+ ],
+ cflags: [
+ "-Wthread-safety",
+ "-Wall",
+ "-Werror",
+ ],
+ relative_install_path: "soundfx",
+}
+
cc_library_shared {
name: "libdynproc",
vendor: true,
+ defaults: [
+ "dynamicsprocessingdefaults",
+ ],
+
srcs: [
"EffectDynamicsProcessing.cpp",
- "dsp/DPBase.cpp",
- "dsp/DPFrequency.cpp",
],
cflags: [
"-O2",
"-fvisibility=hidden",
+ ],
+}
- "-Wall",
- "-Werror",
+cc_library_shared {
+ name: "libdynamicsprocessingaidl",
+
+ srcs: [
+ "aidl/DynamicsProcessing.cpp",
+ "aidl/DynamicsProcessingContext.cpp",
+ ":effectCommonFile",
],
- shared_libs: [
- "libcutils",
- "liblog",
+ defaults: [
+ "aidlaudioservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "dynamicsprocessingdefaults",
],
- relative_install_path: "soundfx",
-
- header_libs: [
- "libaudioeffects",
- "libeigen",
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
],
}
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
new file mode 100644
index 0000000..e508d48
--- /dev/null
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_DynamicsProcessingLibEffects"
+
+#include <android-base/logging.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "DynamicsProcessing.h"
+
+#include <dsp/DPBase.h>
+#include <dsp/DPFrequency.h>
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::DynamicsProcessingImpl;
+using aidl::android::hardware::audio::effect::getEffectImplUuidDynamicsProcessing;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+using aidl::android::media::audio::common::PcmType;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidDynamicsProcessing()) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<DynamicsProcessingImpl>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidDynamicsProcessing()) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ *_aidl_return = DynamicsProcessingImpl::kDescriptor;
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string DynamicsProcessingImpl::kEffectName = "DynamicsProcessing";
+
+const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMin =
+ DynamicsProcessing::EqBandConfig({.channel = 0,
+ .band = 0,
+ .enable = false,
+ .cutoffFrequencyHz = 220,
+ .gainDb = std::numeric_limits<float>::min()});
+const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMax =
+ DynamicsProcessing::EqBandConfig({.channel = std::numeric_limits<int>::max(),
+ .band = std::numeric_limits<int>::max(),
+ .enable = true,
+ .cutoffFrequencyHz = 20000,
+ .gainDb = std::numeric_limits<float>::max()});
+const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPreEqBandRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
+ {DynamicsProcessingImpl::kEqBandConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
+ {DynamicsProcessingImpl::kEqBandConfigMax})};
+const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPostEqBandRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
+ {DynamicsProcessingImpl::kEqBandConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
+ {DynamicsProcessingImpl::kEqBandConfigMax})};
+const Range DynamicsProcessingImpl::kRange =
+ Range::make<Range::dynamicsProcessing>({DynamicsProcessingImpl::kPreEqBandRange});
+
+const Capability DynamicsProcessingImpl::kCapability = {.range = {DynamicsProcessingImpl::kRange}};
+
+const Descriptor DynamicsProcessingImpl::kDescriptor = {
+ .common = {.id = {.type = getEffectTypeUuidDynamicsProcessing(),
+ .uuid = getEffectImplUuidDynamicsProcessing(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::LAST,
+ .volume = Flags::Volume::CTRL},
+ .name = DynamicsProcessingImpl::kEffectName,
+ .implementor = "The Android Open Source Project"},
+ .capability = DynamicsProcessingImpl::kCapability};
+
+ndk::ScopedAStatus DynamicsProcessingImpl::open(const Parameter::Common& common,
+ const std::optional<Parameter::Specific>& specific,
+ OpenEffectReturn* ret) {
+ LOG(DEBUG) << __func__;
+ // effect only support 32bits float
+ RETURN_IF(common.input.base.format.pcm != common.output.base.format.pcm ||
+ common.input.base.format.pcm != PcmType::FLOAT_32_BIT,
+ EX_ILLEGAL_ARGUMENT, "dataMustBe32BitsFloat");
+ RETURN_OK_IF(mState != State::INIT);
+ auto context = createContext(common);
+ RETURN_IF(!context, EX_NULL_POINTER, "createContextFailed");
+
+ RETURN_IF_ASTATUS_NOT_OK(setParameterCommon(common), "setCommParamErr");
+ if (specific.has_value()) {
+ RETURN_IF_ASTATUS_NOT_OK(setParameterSpecific(specific.value()), "setSpecParamErr");
+ } else {
+ Parameter::Specific defaultSpecific =
+ Parameter::Specific::make<Parameter::Specific::dynamicsProcessing>(
+ DynamicsProcessing::make<DynamicsProcessing::engineArchitecture>(
+ mContext->getEngineArchitecture()));
+ RETURN_IF_ASTATUS_NOT_OK(setParameterSpecific(defaultSpecific), "setDefaultEngineErr");
+ }
+
+ mState = State::IDLE;
+ context->dupeFmq(ret);
+ RETURN_IF(createThread(context, getEffectName()) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
+ "FailedToCreateWorker");
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DynamicsProcessingImpl::getDescriptor(Descriptor* _aidl_return) {
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DynamicsProcessingImpl::commandImpl(CommandId command) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (command) {
+ case CommandId::START:
+ mContext->enable();
+ return ndk::ScopedAStatus::ok();
+ case CommandId::STOP:
+ mContext->disable();
+ return ndk::ScopedAStatus::ok();
+ case CommandId::RESET:
+ mContext->disable();
+ mContext->resetBuffer();
+ return ndk::ScopedAStatus::ok();
+ default:
+ // Need this default handling for vendor extendable CommandId::VENDOR_COMMAND_*
+ LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commandIdNotSupported");
+ }
+}
+
+ndk::ScopedAStatus DynamicsProcessingImpl::setParameterSpecific(
+ const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::dynamicsProcessing != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& param = specific.get<Parameter::Specific::dynamicsProcessing>();
+ // TODO: check range here, dynamicsProcessing need customized method for nested parameters.
+ auto tag = param.getTag();
+
+ switch (tag) {
+ case DynamicsProcessing::engineArchitecture: {
+ RETURN_IF(mContext->setEngineArchitecture(
+ param.get<DynamicsProcessing::engineArchitecture>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setEngineArchitectureFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::preEq: {
+ RETURN_IF(
+ mContext->setPreEq(param.get<DynamicsProcessing::preEq>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setPreEqFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::postEq: {
+ RETURN_IF(mContext->setPostEq(param.get<DynamicsProcessing::postEq>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setPostEqFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::preEqBand: {
+ RETURN_IF(mContext->setPreEqBand(param.get<DynamicsProcessing::preEqBand>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setPreEqBandFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::postEqBand: {
+ RETURN_IF(mContext->setPostEqBand(param.get<DynamicsProcessing::postEqBand>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setPostEqBandFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::mbc: {
+ RETURN_IF(mContext->setMbc(param.get<DynamicsProcessing::mbc>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setMbcFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::mbcBand: {
+ RETURN_IF(mContext->setMbcBand(param.get<DynamicsProcessing::mbcBand>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setMbcBandFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::limiter: {
+ RETURN_IF(mContext->setLimiter(param.get<DynamicsProcessing::limiter>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setLimiterFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::inputGain: {
+ RETURN_IF(mContext->setInputGain(param.get<DynamicsProcessing::inputGain>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setInputGainFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::vendor: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "DPVendorExtensionTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus DynamicsProcessingImpl::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::dynamicsProcessingTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto dpId = id.get<Parameter::Id::dynamicsProcessingTag>();
+ auto dpIdTag = dpId.getTag();
+ switch (dpIdTag) {
+ case DynamicsProcessing::Id::commonTag:
+ return getParameterDynamicsProcessing(dpId.get<DynamicsProcessing::Id::commonTag>(),
+ specific);
+ case DynamicsProcessing::Id::vendorExtensionTag:
+ LOG(ERROR) << __func__ << " unsupported ID: " << toString(dpIdTag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "DPVendorExtensionIdNotSupported");
+ }
+}
+
+ndk::ScopedAStatus DynamicsProcessingImpl::getParameterDynamicsProcessing(
+ const DynamicsProcessing::Tag& tag, Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ switch (tag) {
+ case DynamicsProcessing::engineArchitecture: {
+ specific->set<Parameter::Specific::dynamicsProcessing>(
+ DynamicsProcessing::make<DynamicsProcessing::engineArchitecture>(
+ mContext->getEngineArchitecture()));
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::preEq: {
+ specific->set<Parameter::Specific::dynamicsProcessing>(
+ DynamicsProcessing::make<DynamicsProcessing::preEq>(mContext->getPreEq()));
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::postEq: {
+ specific->set<Parameter::Specific::dynamicsProcessing>(
+ DynamicsProcessing::make<DynamicsProcessing::postEq>(mContext->getPostEq()));
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::preEqBand: {
+ specific->set<Parameter::Specific::dynamicsProcessing>(
+ DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
+ mContext->getPreEqBand()));
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::postEqBand: {
+ specific->set<Parameter::Specific::dynamicsProcessing>(
+ DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
+ mContext->getPostEqBand()));
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::mbc: {
+ specific->set<Parameter::Specific::dynamicsProcessing>(
+ DynamicsProcessing::make<DynamicsProcessing::mbc>(mContext->getMbc()));
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::mbcBand: {
+ specific->set<Parameter::Specific::dynamicsProcessing>(
+ DynamicsProcessing::make<DynamicsProcessing::mbcBand>(mContext->getMbcBand()));
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::limiter: {
+ specific->set<Parameter::Specific::dynamicsProcessing>(
+ DynamicsProcessing::make<DynamicsProcessing::limiter>(mContext->getLimiter()));
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::inputGain: {
+ specific->set<Parameter::Specific::dynamicsProcessing>(
+ DynamicsProcessing::make<DynamicsProcessing::inputGain>(
+ mContext->getInputGain()));
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::vendor: {
+ LOG(ERROR) << __func__ << " wrong vendor tag in CommonTag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "DPVendorExtensionTagInWrongId");
+ }
+ }
+}
+
+std::shared_ptr<EffectContext> DynamicsProcessingImpl::createContext(
+ const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+
+ mContext = std::make_shared<DynamicsProcessingContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode DynamicsProcessingImpl::releaseContext() {
+ if (mContext) {
+ mContext->disable();
+ mContext->resetBuffer();
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status DynamicsProcessingImpl::effectProcessImpl(float* in, float* out, int samples) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!mContext, status, "nullContext");
+ return mContext->lvmProcess(in, out, samples);
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
new file mode 100644
index 0000000..d094c69
--- /dev/null
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "effect-impl/EffectImpl.h"
+#include "DynamicsProcessingContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class DynamicsProcessingImpl final : public EffectImpl {
+ public:
+ static const std::string kEffectName;
+ static const Descriptor kDescriptor;
+ static const Capability kCapability;
+
+ DynamicsProcessingImpl() { LOG(DEBUG) << __func__; }
+ ~DynamicsProcessingImpl() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus open(const Parameter::Common& common,
+ const std::optional<Parameter::Specific>& specific,
+ OpenEffectReturn* ret) override;
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ std::shared_ptr<EffectContext> getContext() override { return mContext; }
+ std::string getEffectName() override { return kEffectName; }
+
+ private:
+ static const DynamicsProcessing::EqBandConfig kEqBandConfigMin;
+ static const DynamicsProcessing::EqBandConfig kEqBandConfigMax;
+ static const Range::DynamicsProcessingRange kPreEqBandRange;
+ static const Range::DynamicsProcessingRange kPostEqBandRange;
+ static const Range kRange;
+ std::shared_ptr<DynamicsProcessingContext> mContext;
+ ndk::ScopedAStatus getParameterDynamicsProcessing(const DynamicsProcessing::Tag& tag,
+ Parameter::Specific* specific);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
new file mode 100644
index 0000000..69ff522
--- /dev/null
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_DPLibEffectsContext"
+
+#include "DynamicsProcessing.h"
+#include "DynamicsProcessingContext.h"
+
+#include <functional>
+#include <sys/param.h>
+#include <unordered_set>
+
+namespace aidl::android::hardware::audio::effect {
+
+DynamicsProcessingContext::DynamicsProcessingContext(int statusDepth,
+ const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ init();
+}
+
+DynamicsProcessingContext::~DynamicsProcessingContext() {
+ LOG(DEBUG) << __func__;
+}
+
+RetCode DynamicsProcessingContext::enable() {
+ std::lock_guard lg(mMutex);
+ if (mState != DYNAMICS_PROCESSING_STATE_INITIALIZED) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = DYNAMICS_PROCESSING_STATE_ACTIVE;
+ return RetCode::SUCCESS;
+}
+
+RetCode DynamicsProcessingContext::disable() {
+ std::lock_guard lg(mMutex);
+ if (mState != DYNAMICS_PROCESSING_STATE_ACTIVE) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = DYNAMICS_PROCESSING_STATE_INITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+void DynamicsProcessingContext::reset() {
+ std::lock_guard lg(mMutex);
+ if (mDpFreq != nullptr) {
+ mDpFreq.reset();
+ }
+}
+
+RetCode DynamicsProcessingContext::setCommon(const Parameter::Common& common) {
+ mCommon = common;
+ init();
+ LOG(INFO) << __func__ << common.toString();
+ return RetCode::SUCCESS;
+}
+
+void DynamicsProcessingContext::dpSetFreqDomainVariant_l(
+ const DynamicsProcessing::EngineArchitecture& engine) {
+ mDpFreq.reset(new dp_fx::DPFrequency());
+ mDpFreq->init(mChannelCount, engine.preEqStage.inUse, engine.preEqStage.bandCount,
+ engine.mbcStage.inUse, engine.mbcStage.bandCount, engine.postEqStage.inUse,
+ engine.postEqStage.bandCount, engine.limiterInUse);
+
+ int32_t sampleRate = mCommon.input.base.sampleRate;
+ int32_t minBlockSize = (int32_t)dp_fx::DPFrequency::getMinBockSize();
+ int32_t block = engine.preferredProcessingDurationMs * sampleRate / 1000.0f;
+ LOG(INFO) << __func__ << " sampleRate " << sampleRate << " block length "
+ << engine.preferredProcessingDurationMs << " ms (" << block << "samples)";
+ if (block < minBlockSize) {
+ block = minBlockSize;
+ } else if (!powerof2(block)) {
+ //find next highest power of 2.
+ block = 1 << (32 - __builtin_clz(block));
+ }
+ mDpFreq->configure(block, block >> 1, sampleRate);
+}
+
+RetCode DynamicsProcessingContext::setEngineArchitecture(
+ const DynamicsProcessing::EngineArchitecture& engineArchitecture) {
+ RETURN_VALUE_IF(!validateEngineConfig(engineArchitecture), RetCode::ERROR_ILLEGAL_PARAMETER,
+ "illegalEngineConfig");
+
+ std::lock_guard lg(mMutex);
+ if (!mEngineInited || mEngineArchitecture != engineArchitecture) {
+ if (engineArchitecture.resolutionPreference ==
+ DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION) {
+ dpSetFreqDomainVariant_l(engineArchitecture);
+ } else {
+ LOG(WARNING) << __func__ << toString(engineArchitecture.resolutionPreference)
+ << " not available now";
+ }
+ mEngineInited = true;
+ mEngineArchitecture = engineArchitecture;
+ }
+ LOG(INFO) << __func__ << engineArchitecture.toString();
+ return RetCode::SUCCESS;
+}
+
+RetCode DynamicsProcessingContext::setPreEq(
+ const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
+ std::lock_guard lg(mMutex);
+ return setDpChannels_l<dp_fx::DPEq>(channels, mEngineArchitecture.preEqStage.inUse,
+ StageType::PREEQ);
+}
+
+RetCode DynamicsProcessingContext::setPostEq(
+ const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
+ std::lock_guard lg(mMutex);
+ return setDpChannels_l<dp_fx::DPEq>(channels, mEngineArchitecture.postEqStage.inUse,
+ StageType::POSTEQ);
+}
+
+RetCode DynamicsProcessingContext::setMbc(
+ const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
+ std::lock_guard lg(mMutex);
+ return setDpChannels_l<dp_fx::DPMbc>(channels, mEngineArchitecture.mbcStage.inUse,
+ StageType::MBC);
+}
+
+RetCode DynamicsProcessingContext::setPreEqBand(
+ const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+ "postEqNotInUse");
+ return setBands_l<DynamicsProcessing::EqBandConfig>(
+ bands, mEngineArchitecture.preEqStage.bandCount, StageType::PREEQ);
+}
+
+RetCode DynamicsProcessingContext::setPostEqBand(
+ const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+ "postEqNotInUse");
+ return setBands_l<DynamicsProcessing::EqBandConfig>(
+ bands, mEngineArchitecture.postEqStage.bandCount, StageType::POSTEQ);
+}
+
+RetCode DynamicsProcessingContext::setMbcBand(
+ const std::vector<DynamicsProcessing::MbcBandConfig>& bands) {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(!mEngineArchitecture.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+ "mbcNotInUse");
+ return setBands_l<DynamicsProcessing::MbcBandConfig>(
+ bands, mEngineArchitecture.preEqStage.bandCount, StageType::MBC);
+}
+
+RetCode DynamicsProcessingContext::setLimiter(
+ const std::vector<DynamicsProcessing::LimiterConfig>& limiters) {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(!mEngineArchitecture.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+ "limiterNotInUse");
+ return setBands_l<DynamicsProcessing::LimiterConfig>(limiters, -1, StageType::LIMITER);
+}
+
+RetCode DynamicsProcessingContext::setInputGain(
+ const std::vector<DynamicsProcessing::InputGain>& inputGains) {
+ std::lock_guard lg(mMutex);
+ return setBands_l<DynamicsProcessing::InputGain>(inputGains, -1, StageType::INPUTGAIN);
+}
+
+DynamicsProcessing::EngineArchitecture DynamicsProcessingContext::getEngineArchitecture() {
+ std::lock_guard lg(mMutex);
+ LOG(INFO) << __func__ << mEngineArchitecture.toString();
+ return mEngineArchitecture;
+}
+
+std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getPreEq() {
+ return getChannelConfig(StageType::PREEQ);
+}
+
+std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getPostEq() {
+ return getChannelConfig(StageType::POSTEQ);
+}
+
+std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getPreEqBand() {
+ return getEqBandConfigs(StageType::PREEQ);
+}
+
+std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getPostEqBand() {
+ return getEqBandConfigs(StageType::POSTEQ);
+}
+
+std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getMbc() {
+ return getChannelConfig(StageType::MBC);
+}
+
+std::vector<DynamicsProcessing::MbcBandConfig> DynamicsProcessingContext::getMbcBand() {
+ std::vector<DynamicsProcessing::MbcBandConfig> bands;
+
+ std::lock_guard lg(mMutex);
+ auto maxBand = mEngineArchitecture.mbcStage.bandCount;
+ for (int32_t ch = 0; ch < mChannelCount; ch++) {
+ auto mbc = getMbc_l(ch);
+ if (!mbc) {
+ continue;
+ }
+ for (int32_t bandId = 0; bandId < maxBand; bandId++) {
+ auto band = mbc->getBand(bandId);
+ if (!band) {
+ continue;
+ }
+ bands.push_back({.channel = ch,
+ .band = bandId,
+ .enable = band->isEnabled(),
+ .cutoffFrequencyHz = band->getCutoffFrequency(),
+ .attackTimeMs = band->getAttackTime(),
+ .releaseTimeMs = band->getReleaseTime(),
+ .ratio = band->getRatio(),
+ .thresholdDb = band->getThreshold(),
+ .kneeWidthDb = band->getKneeWidth(),
+ .noiseGateThresholdDb = band->getNoiseGateThreshold(),
+ .expanderRatio = band->getExpanderRatio(),
+ .preGainDb = band->getPreGain(),
+ .postGainDb = band->getPostGain()});
+ }
+ }
+ return bands;
+}
+
+std::vector<DynamicsProcessing::LimiterConfig> DynamicsProcessingContext::getLimiter() {
+ std::vector<DynamicsProcessing::LimiterConfig> ret;
+
+ std::lock_guard lg(mMutex);
+ for (int32_t ch = 0; ch < mChannelCount; ch++) {
+ auto limiter = getLimiter_l(ch);
+ if (!limiter) {
+ continue;
+ }
+ ret.push_back({.channel = ch,
+ .enable = limiter->isEnabled(),
+ .linkGroup = static_cast<int32_t>(limiter->getLinkGroup()),
+ .attackTimeMs = limiter->getAttackTime(),
+ .releaseTimeMs = limiter->getReleaseTime(),
+ .ratio = limiter->getRatio(),
+ .thresholdDb = limiter->getThreshold(),
+ .postGainDb = limiter->getPostGain()});
+ }
+ return ret;
+}
+
+std::vector<DynamicsProcessing::InputGain> DynamicsProcessingContext::getInputGain() {
+ std::vector<DynamicsProcessing::InputGain> ret;
+
+ std::lock_guard lg(mMutex);
+ for (int32_t ch = 0; ch < mChannelCount; ch++) {
+ auto channel = getChannel_l(ch);
+ if (!channel) {
+ continue;
+ }
+ ret.push_back({.channel = ch, .gainDb = channel->getInputGain()});
+ }
+ return ret;
+}
+
+IEffect::Status DynamicsProcessingContext::lvmProcess(float* in, float* out, int samples) {
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!in, status, "nullInput");
+ RETURN_VALUE_IF(!out, status, "nullOutput");
+ status = {EX_ILLEGAL_STATE, 0, 0};
+
+ LOG(DEBUG) << __func__ << " start processing";
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(mState != DynamicsProcessingState::DYNAMICS_PROCESSING_STATE_ACTIVE, status,
+ "notInActiveState");
+ RETURN_VALUE_IF(!mDpFreq, status, "engineNotInited");
+ mDpFreq->processSamples(in, out, samples);
+ }
+ return {STATUS_OK, samples, samples};
+}
+
+void DynamicsProcessingContext::init() {
+ std::lock_guard lg(mMutex);
+ mState = DYNAMICS_PROCESSING_STATE_INITIALIZED;
+ mChannelCount = ::aidl::android::hardware::audio::common::getChannelCount(
+ mCommon.input.base.channelMask);
+}
+
+dp_fx::DPChannel* DynamicsProcessingContext::getChannel_l(int channel) {
+ RETURN_VALUE_IF(mDpFreq == nullptr, nullptr, "DPFreqNotInited");
+
+ return mDpFreq->getChannel(channel);
+}
+
+dp_fx::DPEq* DynamicsProcessingContext::getPreEq_l(int ch) {
+ auto channel = getChannel_l(ch);
+ RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
+
+ return channel->getPreEq();
+}
+
+dp_fx::DPEq* DynamicsProcessingContext::getPostEq_l(int ch) {
+ auto channel = getChannel_l(ch);
+ RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
+
+ return channel->getPostEq();
+}
+
+dp_fx::DPMbc* DynamicsProcessingContext::getMbc_l(int ch) {
+ auto channel = getChannel_l(ch);
+ RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
+
+ return channel->getMbc();
+}
+
+dp_fx::DPLimiter* DynamicsProcessingContext::getLimiter_l(int ch) {
+ auto channel = getChannel_l(ch);
+ RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
+
+ return channel->getLimiter();
+}
+
+dp_fx::DPBandStage* DynamicsProcessingContext::getStageWithType_l(
+ DynamicsProcessingContext::StageType type, int ch) {
+ switch (type) {
+ case StageType::PREEQ: {
+ return getEqWithType_l(type, ch);
+ }
+ case StageType::POSTEQ: {
+ return getEqWithType_l(type, ch);
+ }
+ case StageType::MBC: {
+ return getMbc_l(ch);
+ }
+ case StageType::LIMITER:
+ FALLTHROUGH_INTENDED;
+ case StageType::INPUTGAIN: {
+ return nullptr;
+ }
+ }
+}
+
+dp_fx::DPEq* DynamicsProcessingContext::getEqWithType_l(DynamicsProcessingContext::StageType type,
+ int ch) {
+ switch (type) {
+ case StageType::PREEQ: {
+ return getPreEq_l(ch);
+ }
+ case StageType::POSTEQ: {
+ return getPostEq_l(ch);
+ }
+ case StageType::MBC:
+ FALLTHROUGH_INTENDED;
+ case StageType::LIMITER:
+ FALLTHROUGH_INTENDED;
+ case StageType::INPUTGAIN: {
+ return nullptr;
+ }
+ }
+}
+
+std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getChannelConfig(
+ StageType type) {
+ std::vector<DynamicsProcessing::ChannelConfig> ret;
+
+ std::lock_guard lg(mMutex);
+ for (int32_t ch = 0; ch < mChannelCount; ch++) {
+ auto stage = getStageWithType_l(type, ch);
+ if (!stage) {
+ continue;
+ }
+ ret.push_back({.channel = ch, .enable = stage->isEnabled()});
+ }
+ return ret;
+}
+
+std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getEqBandConfigs(
+ StageType type) {
+ std::vector<DynamicsProcessing::EqBandConfig> eqBands;
+
+ std::lock_guard lg(mMutex);
+ auto maxBand = mEngineArchitecture.preEqStage.bandCount;
+ for (int32_t ch = 0; ch < mChannelCount; ch++) {
+ auto eq = getEqWithType_l(type, ch);
+ if (!eq) {
+ continue;
+ }
+ for (int32_t bandId = 0; bandId < maxBand; bandId++) {
+ auto band = eq->getBand(bandId);
+ if (!band) {
+ continue;
+ }
+ eqBands.push_back({.channel = ch,
+ .band = bandId,
+ .enable = band->isEnabled(),
+ .cutoffFrequencyHz = band->getCutoffFrequency(),
+ .gainDb = band->getGain()});
+ }
+ }
+ return eqBands;
+}
+
+/**
+ * When StageEnablement is in use, bandCount needs to be positive.
+ */
+bool DynamicsProcessingContext::validateStageEnablement(
+ const DynamicsProcessing::StageEnablement& enablement) {
+ return !enablement.inUse || (enablement.inUse && enablement.bandCount > 0);
+}
+
+bool DynamicsProcessingContext::validateEngineConfig(
+ const DynamicsProcessing::EngineArchitecture& engine) {
+ return engine.preferredProcessingDurationMs >= 0 &&
+ validateStageEnablement(engine.preEqStage) &&
+ validateStageEnablement(engine.postEqStage) && validateStageEnablement(engine.mbcStage);
+}
+
+bool DynamicsProcessingContext::validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band,
+ int maxChannel, int maxBand) {
+ return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand);
+}
+
+bool DynamicsProcessingContext::validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band,
+ int maxChannel, int maxBand) {
+ return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand) &&
+ validateTime(band.attackTimeMs) && validateTime(band.releaseTimeMs) &&
+ validateRatio(band.ratio) && validateBandDb(band.thresholdDb) &&
+ validateBandDb(band.kneeWidthDb) && validateBandDb(band.noiseGateThresholdDb) &&
+ validateRatio(band.expanderRatio);
+}
+
+bool DynamicsProcessingContext::validateLimiterConfig(
+ const DynamicsProcessing::LimiterConfig& limiter, int maxChannel) {
+ return validateChannel(limiter.channel, maxChannel) && validateTime(limiter.attackTimeMs) &&
+ validateTime(limiter.releaseTimeMs) && validateRatio(limiter.ratio) &&
+ validateBandDb(limiter.thresholdDb);
+}
+
+bool DynamicsProcessingContext::validateInputGainConfig(const DynamicsProcessing::InputGain& gain,
+ int maxChannel) {
+ return validateChannel(gain.channel, maxChannel);
+}
+
+template <typename D>
+RetCode DynamicsProcessingContext::setDpChannels_l(
+ const std::vector<DynamicsProcessing::ChannelConfig>& channels, bool stageInUse,
+ StageType type) {
+ RetCode ret = RetCode::SUCCESS;
+ std::unordered_set<int> channelSet;
+
+ RETURN_VALUE_IF(!stageInUse, RetCode::ERROR_ILLEGAL_PARAMETER, "stageNotInUse");
+ for (auto& it : channels) {
+ if (0 != channelSet.count(it.channel)) {
+ LOG(WARNING) << __func__ << " duplicated channel " << it.channel;
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ } else {
+ channelSet.insert(it.channel);
+ }
+ if (it.channel < 0 || it.channel >= mChannelCount) {
+ LOG(WARNING) << __func__ << " skip illegal ChannelConfig " << it.toString() << " max "
+ << mChannelCount;
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ continue;
+ }
+ auto dp = getStageWithType_l(type, it.channel);
+ if (!dp) {
+ LOG(WARNING) << __func__ << " channel " << it.channel << " not exist";
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ continue;
+ }
+ if (dp->isEnabled() != it.enable) {
+ LOG(INFO) << __func__ << it.toString();
+ dp->setEnabled(it.enable);
+ }
+ }
+ return ret;
+}
+
+RetCode DynamicsProcessingContext::setDpChannelBand_l(const std::any& anyConfig, StageType type,
+ int maxCh, int maxBand,
+ std::set<std::pair<int, int>>& chBandSet) {
+ RETURN_VALUE_IF(!anyConfig.has_value(), RetCode::ERROR_ILLEGAL_PARAMETER, "bandInvalid");
+ RetCode ret = RetCode::SUCCESS;
+ std::pair<int, int> chBandKey;
+ switch (type) {
+ case StageType::PREEQ:
+ FALLTHROUGH_INTENDED;
+ case StageType::POSTEQ: {
+ dp_fx::DPEq* dp;
+ const auto& config = std::any_cast<DynamicsProcessing::EqBandConfig>(anyConfig);
+ RETURN_VALUE_IF(!validateEqBandConfig(config, maxCh, maxBand),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
+ RETURN_VALUE_IF(
+ nullptr == (dp = getEqWithType_l(type, config.channel)) || !dp->isEnabled(),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "dpEqNotExist");
+ dp_fx::DPEqBand band;
+ band.init(config.enable, config.cutoffFrequencyHz, config.gainDb);
+ dp->setBand(config.band, band);
+ chBandKey = {config.channel, config.band};
+ break;
+ }
+ case StageType::MBC: {
+ dp_fx::DPMbc* dp;
+ const auto& config = std::any_cast<DynamicsProcessing::MbcBandConfig>(anyConfig);
+ RETURN_VALUE_IF(!validateMbcBandConfig(config, maxCh, maxBand),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "mbcBandNotValid");
+ RETURN_VALUE_IF(nullptr == (dp = getMbc_l(config.channel)) || !dp->isEnabled(),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "dpMbcNotExist");
+ dp_fx::DPMbcBand band;
+ band.init(config.enable, config.cutoffFrequencyHz, config.attackTimeMs,
+ config.releaseTimeMs, config.ratio, config.thresholdDb, config.kneeWidthDb,
+ config.noiseGateThresholdDb, config.expanderRatio, config.preGainDb,
+ config.postGainDb);
+ dp->setBand(config.band, band);
+ chBandKey = {config.channel, config.band};
+ break;
+ }
+ case StageType::LIMITER: {
+ dp_fx::DPChannel* dp;
+ const auto& config = std::any_cast<DynamicsProcessing::LimiterConfig>(anyConfig);
+ RETURN_VALUE_IF(!validateLimiterConfig(config, maxCh),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "limiterBandNotValid");
+ RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
+ dp_fx::DPLimiter limiter;
+ limiter.init(mEngineArchitecture.limiterInUse, config.enable, config.linkGroup,
+ config.attackTimeMs, config.releaseTimeMs, config.ratio,
+ config.thresholdDb, config.postGainDb);
+ dp->setLimiter(limiter);
+ chBandKey = {config.channel, 0};
+ break;
+ }
+ case StageType::INPUTGAIN: {
+ dp_fx::DPChannel* dp;
+ const auto& config = std::any_cast<DynamicsProcessing::InputGain>(anyConfig);
+ RETURN_VALUE_IF(!validateInputGainConfig(config, maxCh),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "inputGainNotValid");
+ RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
+ dp->setInputGain(config.gainDb);
+ chBandKey = {config.channel, 0};
+ break;
+ }
+ }
+ RETURN_VALUE_IF(0 != chBandSet.count(chBandKey), RetCode::ERROR_ILLEGAL_PARAMETER,
+ "duplicatedBand");
+ chBandSet.insert(chBandKey);
+ return ret;
+}
+
+template <typename T /* BandConfig */>
+RetCode DynamicsProcessingContext::setBands_l(
+ const std::vector<T>& bands, int maxBand, StageType type) {
+ RetCode ret = RetCode::SUCCESS;
+ std::set<std::pair<int /* channel */, int /* band */>> bandSet;
+
+ for (const auto& it : bands) {
+ if (RetCode::SUCCESS !=
+ setDpChannelBand_l(std::make_any<T>(it), type, mChannelCount, maxBand, bandSet)) {
+ LOG(WARNING) << __func__ << " skipping band " << it.toString();
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ continue;
+ }
+ LOG(INFO) << __func__ << it.toString();
+ }
+ return ret;
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
new file mode 100644
index 0000000..8be784e
--- /dev/null
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2023 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 <android-base/thread_annotations.h>
+#include <audio_effects/effect_dynamicsprocessing.h>
+
+#include "effect-impl/EffectContext.h"
+
+#include <any>
+#include <cstddef>
+#include <dsp/DPBase.h>
+#include <dsp/DPFrequency.h>
+
+namespace aidl::android::hardware::audio::effect {
+
+enum DynamicsProcessingState {
+ DYNAMICS_PROCESSING_STATE_UNINITIALIZED,
+ DYNAMICS_PROCESSING_STATE_INITIALIZED,
+ DYNAMICS_PROCESSING_STATE_ACTIVE,
+};
+
+class DynamicsProcessingContext final : public EffectContext {
+ public:
+ DynamicsProcessingContext(int statusDepth, const Parameter::Common& common);
+ ~DynamicsProcessingContext();
+
+ RetCode enable();
+ RetCode disable();
+ void reset();
+
+ // override EffectContext::setCommon to update mChannelCount
+ RetCode setCommon(const Parameter::Common& common) override;
+
+ RetCode setEngineArchitecture(const DynamicsProcessing::EngineArchitecture& engineArchitecture);
+ RetCode setPreEq(const std::vector<DynamicsProcessing::ChannelConfig>& eqChannels);
+ RetCode setPostEq(const std::vector<DynamicsProcessing::ChannelConfig>& eqChannels);
+ RetCode setPreEqBand(const std::vector<DynamicsProcessing::EqBandConfig>& eqBands);
+ RetCode setPostEqBand(const std::vector<DynamicsProcessing::EqBandConfig>& eqBands);
+ RetCode setMbc(const std::vector<DynamicsProcessing::ChannelConfig>& mbcChannels);
+ RetCode setMbcBand(const std::vector<DynamicsProcessing::MbcBandConfig>& eqBands);
+ RetCode setLimiter(const std::vector<DynamicsProcessing::LimiterConfig>& limiters);
+ RetCode setInputGain(const std::vector<DynamicsProcessing::InputGain>& gain);
+
+ DynamicsProcessing::EngineArchitecture getEngineArchitecture();
+ std::vector<DynamicsProcessing::ChannelConfig> getPreEq();
+ std::vector<DynamicsProcessing::ChannelConfig> getPostEq();
+ std::vector<DynamicsProcessing::EqBandConfig> getPreEqBand();
+ std::vector<DynamicsProcessing::EqBandConfig> getPostEqBand();
+ std::vector<DynamicsProcessing::ChannelConfig> getMbc();
+ std::vector<DynamicsProcessing::MbcBandConfig> getMbcBand();
+ std::vector<DynamicsProcessing::LimiterConfig> getLimiter();
+ std::vector<DynamicsProcessing::InputGain> getInputGain();
+
+ IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+ private:
+ static constexpr float kPreferredProcessingDurationMs = 10.0f;
+ static constexpr int kBandCount = 5;
+ std::mutex mMutex;
+ size_t mChannelCount GUARDED_BY(mMutex) = 0;
+ DynamicsProcessingState mState GUARDED_BY(mMutex) = DYNAMICS_PROCESSING_STATE_UNINITIALIZED;
+ std::unique_ptr<dp_fx::DPFrequency> mDpFreq GUARDED_BY(mMutex) = nullptr;
+ bool mEngineInited GUARDED_BY(mMutex) = false;
+ DynamicsProcessing::EngineArchitecture mEngineArchitecture GUARDED_BY(mMutex) = {
+ .resolutionPreference =
+ DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
+ .preferredProcessingDurationMs = kPreferredProcessingDurationMs,
+ .preEqStage = {.inUse = true, .bandCount = kBandCount},
+ .postEqStage = {.inUse = true, .bandCount = kBandCount},
+ .mbcStage = {.inUse = true, .bandCount = kBandCount},
+ .limiterInUse = true,
+ };
+
+ enum class StageType { PREEQ, POSTEQ, MBC, LIMITER, INPUTGAIN };
+
+ void init();
+
+ void dpSetFreqDomainVariant_l(const DynamicsProcessing::EngineArchitecture& engine)
+ REQUIRES(mMutex);
+ dp_fx::DPChannel* getChannel_l(int ch) REQUIRES(mMutex);
+ dp_fx::DPEq* getPreEq_l(int ch) REQUIRES(mMutex);
+ dp_fx::DPEq* getPostEq_l(int ch) REQUIRES(mMutex);
+ dp_fx::DPMbc* getMbc_l(int ch) REQUIRES(mMutex);
+ dp_fx::DPLimiter* getLimiter_l(int ch) REQUIRES(mMutex);
+ dp_fx::DPBandStage* getStageWithType_l(StageType type, int ch) REQUIRES(mMutex);
+ dp_fx::DPEq* getEqWithType_l(StageType type, int ch) REQUIRES(mMutex);
+ template <typename D>
+ RetCode setDpChannels_l(const std::vector<DynamicsProcessing::ChannelConfig>& channels,
+ bool stageInUse, StageType type) REQUIRES(mMutex);
+ template <typename T /* BandConfig */>
+ RetCode setBands_l(const std::vector<T>& bands, int maxBand, StageType type) REQUIRES(mMutex);
+ RetCode setDpChannelBand_l(const std::any& anyConfig, StageType type, int maxCh, int maxBand,
+ std::set<std::pair<int, int>>& chBandSet) REQUIRES(mMutex);
+
+ std::vector<DynamicsProcessing::EqBandConfig> getEqBandConfigs(StageType type);
+ std::vector<DynamicsProcessing::ChannelConfig> getChannelConfig(StageType type);
+
+ bool validateStageEnablement(const DynamicsProcessing::StageEnablement& enablement);
+ bool validateEngineConfig(const DynamicsProcessing::EngineArchitecture& engine);
+ bool validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band, int maxChannel,
+ int maxBand);
+ bool validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band, int maxChannel,
+ int maxBand);
+ bool validateLimiterConfig(const DynamicsProcessing::LimiterConfig& limiter, int maxChannel);
+ bool validateInputGainConfig(const DynamicsProcessing::InputGain& gain, int maxChannel);
+
+ inline bool validateCutoffFrequency(float freq);
+ inline bool validateChannel(int ch, int maxCh) { return ch >= 0 && ch < maxCh; }
+ inline bool validateBand(int band, int maxBand) { return band >= 0 && band < maxBand; }
+ inline bool validateTime(int time) { return time >= 0; }
+ inline bool validateRatio(int ratio) { return ratio >= 0; }
+ inline bool validateBandDb(int db) { return db <= 0; }
+};
+
+} // namespace aidl::android::hardware::audio::effect
\ No newline at end of file
diff --git a/media/libeffects/hapticgenerator/Android.bp b/media/libeffects/hapticgenerator/Android.bp
index 03ce329..fc80211 100644
--- a/media/libeffects/hapticgenerator/Android.bp
+++ b/media/libeffects/hapticgenerator/Android.bp
@@ -22,6 +22,24 @@
default_applicable_licenses: ["frameworks_av_license"],
}
+cc_defaults {
+ name : "hapticgeneratordefaults",
+ srcs: [
+ "Processors.cpp",
+ ],
+ shared_libs: [
+ "libaudioutils",
+ "libbase",
+ "liblog",
+ "libutils",
+ "libvibratorutils",
+ ],
+ header_libs: [
+ "libaudioeffects",
+ ],
+ relative_install_path: "soundfx",
+}
+
cc_library_shared {
name: "libhapticgenerator",
@@ -29,7 +47,10 @@
srcs: [
"EffectHapticGenerator.cpp",
- "Processors.cpp",
+ ],
+
+ defaults: [
+ "hapticgeneratordefaults",
],
cflags: [
@@ -42,19 +63,29 @@
// with/without `-ffast-math` for more context.
"-fvisibility=hidden",
],
+}
- shared_libs: [
- "libaudioutils",
- "libbase",
- "libbinder",
- "liblog",
- "libutils",
- "libvibrator",
+cc_library_shared {
+ name: "libhapticgeneratoraidl",
+
+ srcs: [
+ "aidl/EffectHapticGenerator.cpp",
+ "aidl/HapticGeneratorContext.cpp",
+ ":effectCommonFile",
],
- relative_install_path: "soundfx",
+ defaults: [
+ "aidlaudioservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "hapticgeneratordefaults",
+ ],
- header_libs: [
- "libaudioeffects",
+ cflags: [
+ "-Wthread-safety",
+ ],
+
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
],
}
diff --git a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp
new file mode 100644
index 0000000..031477f
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_HapticGeneratorImpl"
+
+#include <android-base/logging.h>
+#include <audio_effects/effect_hapticgenerator.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "EffectHapticGenerator.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::getEffectImplUuidHapticGenerator;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator;
+using aidl::android::hardware::audio::effect::HapticGeneratorImpl;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidHapticGenerator()) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<HapticGeneratorImpl>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidHapticGenerator()) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ *_aidl_return = HapticGeneratorImpl::kDescriptor;
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string HapticGeneratorImpl::kEffectName = "Haptic Generator";
+const Descriptor HapticGeneratorImpl::kDescriptor = {
+ .common = {.id = {.type = getEffectTypeUuidHapticGenerator(),
+ .uuid = getEffectImplUuidHapticGenerator(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT, .insert = Flags::Insert::FIRST},
+ .name = HapticGeneratorImpl::kEffectName,
+ .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus HapticGeneratorImpl::getDescriptor(Descriptor* _aidl_return) {
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::commandImpl(CommandId command) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (command) {
+ case CommandId::START:
+ mContext->enable();
+ break;
+ case CommandId::STOP:
+ mContext->disable();
+ break;
+ case CommandId::RESET:
+ mContext->reset();
+ break;
+ default:
+ LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commandIdNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::hapticGenerator != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& hgParam = specific.get<Parameter::Specific::hapticGenerator>();
+ auto tag = hgParam.getTag();
+
+ switch (tag) {
+ case HapticGenerator::hapticScales: {
+ RETURN_IF(mContext->setHgHapticScales(hgParam.get<HapticGenerator::hapticScales>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setHapticScaleFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case HapticGenerator::vibratorInfo: {
+ RETURN_IF(mContext->setHgVibratorInformation(
+ hgParam.get<HapticGenerator::vibratorInfo>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setVibratorInfoFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::hapticGeneratorTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto hgId = id.get<Parameter::Id::hapticGeneratorTag>();
+ auto hgIdTag = hgId.getTag();
+ switch (hgIdTag) {
+ case HapticGenerator::Id::commonTag:
+ return getParameterHapticGenerator(hgId.get<HapticGenerator::Id::commonTag>(),
+ specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(hgIdTag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::getParameterHapticGenerator(const HapticGenerator::Tag& tag,
+ Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ HapticGenerator hgParam;
+ switch (tag) {
+ case HapticGenerator::hapticScales: {
+ hgParam.set<HapticGenerator::hapticScales>(mContext->getHgHapticScales());
+ break;
+ }
+ case HapticGenerator::vibratorInfo: {
+ hgParam.set<HapticGenerator::vibratorInfo>(mContext->getHgVibratorInformation());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::hapticGenerator>(hgParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> HapticGeneratorImpl::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+
+ mContext = std::make_shared<HapticGeneratorContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode HapticGeneratorImpl::releaseContext() {
+ if (mContext) {
+ mContext->reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status HapticGeneratorImpl::effectProcessImpl(float* in, float* out, int samples) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!mContext, status, "nullContext");
+ return mContext->lvmProcess(in, out, samples);
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
new file mode 100644
index 0000000..fe9616a
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 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 <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "HapticGeneratorContext.h"
+#include "effect-impl/EffectImpl.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class HapticGeneratorImpl final : public EffectImpl {
+ public:
+ static const std::string kEffectName;
+ static const Descriptor kDescriptor;
+ HapticGeneratorImpl() { LOG(DEBUG) << __func__; }
+ ~HapticGeneratorImpl() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ std::shared_ptr<EffectContext> getContext() override { return mContext; }
+ std::string getEffectName() override { return kEffectName; }
+
+ private:
+ std::shared_ptr<HapticGeneratorContext> mContext;
+ ndk::ScopedAStatus getParameterHapticGenerator(const HapticGenerator::Tag& tag,
+ Parameter::Specific* specific);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
new file mode 100644
index 0000000..de44e05
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_HapticGeneratorContext"
+
+#include <Utils.h>
+#include <android-base/logging.h>
+#include <android-base/parsedouble.h>
+#include <android-base/properties.h>
+
+#include "HapticGeneratorContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+HapticGeneratorContext::HapticGeneratorContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ mState = HAPTIC_GENERATOR_STATE_UNINITIALIZED;
+ mSampleRate = common.input.base.sampleRate;
+ mFrameCount = common.input.frameCount;
+ init_params(common.input.base.channelMask, common.output.base.channelMask);
+}
+
+HapticGeneratorContext::~HapticGeneratorContext() {
+ LOG(DEBUG) << __func__;
+ mState = HAPTIC_GENERATOR_STATE_UNINITIALIZED;
+}
+
+RetCode HapticGeneratorContext::enable() {
+ if (mState != HAPTIC_GENERATOR_STATE_INITIALIZED) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = HAPTIC_GENERATOR_STATE_ACTIVE;
+ return RetCode::SUCCESS;
+}
+
+RetCode HapticGeneratorContext::disable() {
+ if (mState != HAPTIC_GENERATOR_STATE_ACTIVE) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = HAPTIC_GENERATOR_STATE_INITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+void HapticGeneratorContext::reset() {
+ for (auto& filter : mProcessorsRecord.filters) {
+ filter->clear();
+ }
+ for (auto& slowEnv : mProcessorsRecord.slowEnvs) {
+ slowEnv->clear();
+ }
+ for (auto& distortion : mProcessorsRecord.distortions) {
+ distortion->clear();
+ }
+}
+
+RetCode HapticGeneratorContext::setHgHapticScales(
+ const std::vector<HapticGenerator::HapticScale>& hapticScales) {
+ std::lock_guard lg(mMutex);
+ for (auto hapticScale : hapticScales) {
+ mParams.mHapticScales.insert_or_assign(hapticScale.id, hapticScale.scale);
+ }
+ mParams.mMaxVibratorScale = HapticGenerator::VibratorScale::MUTE;
+ for (const auto& [id, vibratorScale] : mParams.mHapticScales) {
+ mParams.mMaxVibratorScale = std::max(mParams.mMaxVibratorScale, vibratorScale);
+ }
+ return RetCode::SUCCESS;
+}
+
+HapticGenerator::VibratorInformation HapticGeneratorContext::getHgVibratorInformation() {
+ std::lock_guard lg(mMutex);
+ return mParams.mVibratorInfo;
+}
+
+std::vector<HapticGenerator::HapticScale> HapticGeneratorContext::getHgHapticScales() {
+ std::vector<HapticGenerator::HapticScale> result;
+ std::lock_guard lg(mMutex);
+ for (const auto& [id, vibratorScale] : mParams.mHapticScales) {
+ result.push_back({id, vibratorScale});
+ }
+ return result;
+}
+
+RetCode HapticGeneratorContext::setHgVibratorInformation(
+ const HapticGenerator::VibratorInformation& vibratorInfo) {
+ {
+ std::lock_guard lg(mMutex);
+ mParams.mVibratorInfo = vibratorInfo;
+
+ if (mProcessorsRecord.bpf != nullptr) {
+ mProcessorsRecord.bpf->setCoefficients(
+ ::android::audio_effect::haptic_generator::bpfCoefs(
+ mParams.mVibratorInfo.resonantFrequencyHz, DEFAULT_BPF_Q, mSampleRate));
+ }
+ if (mProcessorsRecord.bsf != nullptr) {
+ mProcessorsRecord.bsf->setCoefficients(
+ ::android::audio_effect::haptic_generator::bsfCoefs(
+ mParams.mVibratorInfo.resonantFrequencyHz,
+ mParams.mVibratorInfo.qFactor, mParams.mVibratorInfo.qFactor / 2.0f,
+ mSampleRate));
+ }
+ }
+ configure();
+ return RetCode::SUCCESS;
+}
+
+IEffect::Status HapticGeneratorContext::lvmProcess(float* in, float* out, int samples) {
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!in, status, "nullInput");
+ RETURN_VALUE_IF(!out, status, "nullOutput");
+ status = {EX_ILLEGAL_STATE, 0, 0};
+ RETURN_VALUE_IF(getInputFrameSize() != getOutputFrameSize(), status, "FrameSizeMismatch");
+ auto frameSize = getInputFrameSize();
+ RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
+
+ LOG(DEBUG) << __func__ << " start processing";
+ // The audio data must not be modified but just written to
+ // output buffer according the access mode.
+ bool accumulate = false;
+ if (in != out) {
+ for (int i = 0; i < samples; i++) {
+ if (accumulate) {
+ out[i] += in[i];
+ } else {
+ out[i] = in[i];
+ }
+ }
+ }
+
+ if (mState != HAPTIC_GENERATOR_STATE_ACTIVE) {
+ return status;
+ }
+
+ std::lock_guard lg(mMutex);
+ if (mParams.mMaxVibratorScale == HapticGenerator::VibratorScale::MUTE) {
+ // Haptic channels are muted, not need to generate haptic data.
+ return {STATUS_OK, samples, samples};
+ }
+
+ // Resize buffer if the haptic sample count is greater than buffer size.
+ size_t hapticSampleCount = mFrameCount * mParams.mHapticChannelCount;
+ if (hapticSampleCount > mInputBuffer.size()) {
+ // The inputBuffer and outputBuffer must have the same size, which must be at least
+ // the haptic sample count.
+ mInputBuffer.resize(hapticSampleCount);
+ mOutputBuffer.resize(hapticSampleCount);
+ }
+
+ // Construct input buffer according to haptic channel source
+ for (size_t i = 0; i < mFrameCount; ++i) {
+ for (size_t j = 0; j < mParams.mHapticChannelCount; ++j) {
+ mInputBuffer[i * mParams.mHapticChannelCount + j] =
+ in[i * mParams.mAudioChannelCount + mParams.mHapticChannelSource[j]];
+ }
+ }
+
+ float* hapticOutBuffer =
+ runProcessingChain(mInputBuffer.data(), mOutputBuffer.data(), mFrameCount);
+ ::android::os::scaleHapticData(
+ hapticOutBuffer, hapticSampleCount,
+ static_cast<::android::os::HapticScale>(mParams.mMaxVibratorScale),
+ mParams.mVibratorInfo.qFactor);
+
+ // For haptic data, the haptic playback thread will copy the data from effect input
+ // buffer, which contains haptic data at the end of the buffer, directly to sink buffer.
+ // In that case, copy haptic data to input buffer instead of output buffer.
+ // Note: this may not work with rpc/binder calls
+ int offset = samples;
+ for (int i = 0; i < hapticSampleCount; ++i) {
+ in[samples + i] = hapticOutBuffer[i];
+ }
+ return {STATUS_OK, samples, static_cast<int32_t>(samples + hapticSampleCount)};
+}
+
+void HapticGeneratorContext::init_params(media::audio::common::AudioChannelLayout inputChMask,
+ media::audio::common::AudioChannelLayout outputChMask) {
+ std::lock_guard lg(mMutex);
+ mParams.mMaxVibratorScale = HapticGenerator::VibratorScale::MUTE;
+ mParams.mVibratorInfo.resonantFrequencyHz = DEFAULT_RESONANT_FREQUENCY;
+ mParams.mVibratorInfo.qFactor = DEFAULT_BSF_ZERO_Q;
+
+ mParams.mAudioChannelCount = ::aidl::android::hardware::audio::common::getChannelCount(
+ inputChMask, ~media::audio::common::AudioChannelLayout::LAYOUT_HAPTIC_AB);
+ mParams.mHapticChannelCount = ::aidl::android::hardware::audio::common::getChannelCount(
+ outputChMask, media::audio::common::AudioChannelLayout::LAYOUT_HAPTIC_AB);
+ LOG_ALWAYS_FATAL_IF(mParams.mHapticChannelCount > 2, "haptic channel count is too large");
+ for (size_t i = 0; i < mParams.mHapticChannelCount; ++i) {
+ // By default, use the first audio channel to generate haptic channels.
+ mParams.mHapticChannelSource[i] = 0;
+ }
+
+ mState = HAPTIC_GENERATOR_STATE_INITIALIZED;
+}
+
+float HapticGeneratorContext::getDistortionOutputGain() {
+ float distortionOutputGain = getFloatProperty(
+ "vendor.audio.hapticgenerator.distortion.output.gain", DEFAULT_DISTORTION_OUTPUT_GAIN);
+ LOG(DEBUG) << "Using distortion output gain as " << distortionOutputGain;
+ return distortionOutputGain;
+}
+
+float HapticGeneratorContext::getFloatProperty(const std::string& key, float defaultValue) {
+ float result;
+ std::string value = ::android::base::GetProperty(key, "");
+ if (!value.empty() && ::android::base::ParseFloat(value, &result)) {
+ return result;
+ }
+ return defaultValue;
+}
+
+void HapticGeneratorContext::addBiquadFilter(std::shared_ptr<HapticBiquadFilter> filter) {
+ // The process chain captures the shared pointer of the filter in lambda.
+ // The process record will keep a shared pointer to the filter so that it is possible to
+ // access the filter outside of the process chain.
+ mProcessorsRecord.filters.push_back(filter);
+ mProcessingChain.push_back([filter](float* out, const float* in, size_t frameCount) {
+ filter->process(out, in, frameCount);
+ });
+}
+
+/**
+ * Build haptic generator processing chain.
+ */
+void HapticGeneratorContext::buildProcessingChain() {
+ std::lock_guard lg(mMutex);
+ const size_t channelCount = mParams.mHapticChannelCount;
+ float highPassCornerFrequency = 50.0f;
+ auto hpf = ::android::audio_effect::haptic_generator::createHPF2(highPassCornerFrequency,
+ mSampleRate, channelCount);
+ addBiquadFilter(hpf);
+ float lowPassCornerFrequency = 9000.0f;
+ auto lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency,
+ mSampleRate, channelCount);
+ addBiquadFilter(lpf);
+
+ auto ramp = std::make_shared<::android::audio_effect::haptic_generator::Ramp>(
+ channelCount); // ramp = half-wave rectifier.
+ // The process chain captures the shared pointer of the ramp in lambda. It will be the only
+ // reference to the ramp.
+ // The process record will keep a weak pointer to the ramp so that it is possible to access
+ // the ramp outside of the process chain.
+ mProcessorsRecord.ramps.push_back(ramp);
+ mProcessingChain.push_back([ramp](float* out, const float* in, size_t frameCount) {
+ ramp->process(out, in, frameCount);
+ });
+
+ highPassCornerFrequency = 60.0f;
+ hpf = ::android::audio_effect::haptic_generator::createHPF2(highPassCornerFrequency,
+ mSampleRate, channelCount);
+ addBiquadFilter(hpf);
+ lowPassCornerFrequency = 700.0f;
+ lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency, mSampleRate,
+ channelCount);
+ addBiquadFilter(lpf);
+
+ lowPassCornerFrequency = 400.0f;
+ lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency, mSampleRate,
+ channelCount);
+ addBiquadFilter(lpf);
+ lowPassCornerFrequency = 500.0f;
+ lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency, mSampleRate,
+ channelCount);
+ addBiquadFilter(lpf);
+
+ auto bpf = ::android::audio_effect::haptic_generator::createBPF(
+ mParams.mVibratorInfo.resonantFrequencyHz, DEFAULT_BPF_Q, mSampleRate, channelCount);
+ mProcessorsRecord.bpf = bpf;
+ addBiquadFilter(bpf);
+
+ float normalizationPower = DEFAULT_SLOW_ENV_NORMALIZATION_POWER;
+ // The process chain captures the shared pointer of the slow envelope in lambda. It will
+ // be the only reference to the slow envelope.
+ // The process record will keep a weak pointer to the slow envelope so that it is possible
+ // to access the slow envelope outside of the process chain.
+ // SlowEnvelope = partial normalizer, or AGC.
+ auto slowEnv = std::make_shared<::android::audio_effect::haptic_generator::SlowEnvelope>(
+ 5.0f /*envCornerFrequency*/, mSampleRate, normalizationPower, 0.01f /*envOffset*/,
+ channelCount);
+ mProcessorsRecord.slowEnvs.push_back(slowEnv);
+ mProcessingChain.push_back([slowEnv](float* out, const float* in, size_t frameCount) {
+ slowEnv->process(out, in, frameCount);
+ });
+
+ auto bsf = ::android::audio_effect::haptic_generator::createBSF(
+ mParams.mVibratorInfo.resonantFrequencyHz, mParams.mVibratorInfo.qFactor,
+ mParams.mVibratorInfo.qFactor / 2.0f, mSampleRate, channelCount);
+ mProcessorsRecord.bsf = bsf;
+ addBiquadFilter(bsf);
+
+ // The process chain captures the shared pointer of the Distortion in lambda. It will
+ // be the only reference to the Distortion.
+ // The process record will keep a weak pointer to the Distortion so that it is possible
+ // to access the Distortion outside of the process chain.
+ auto distortion = std::make_shared<::android::audio_effect::haptic_generator::Distortion>(
+ DEFAULT_DISTORTION_CORNER_FREQUENCY, mSampleRate, DEFAULT_DISTORTION_INPUT_GAIN,
+ DEFAULT_DISTORTION_CUBE_THRESHOLD, getDistortionOutputGain(), channelCount);
+ mProcessorsRecord.distortions.push_back(distortion);
+ mProcessingChain.push_back([distortion](float* out, const float* in, size_t frameCount) {
+ distortion->process(out, in, frameCount);
+ });
+}
+
+void HapticGeneratorContext::configure() {
+ mProcessingChain.clear();
+ mProcessorsRecord.filters.clear();
+ mProcessorsRecord.ramps.clear();
+ mProcessorsRecord.slowEnvs.clear();
+ mProcessorsRecord.distortions.clear();
+
+ buildProcessingChain();
+}
+
+/**
+ * Run the processing chain to generate haptic data from audio data
+ *
+ * @param buf1 a buffer contains raw audio data
+ * @param buf2 a buffer that is large enough to keep all the data
+ * @param frameCount frame count of the data
+ *
+ * @return a pointer to the output buffer
+ */
+float* HapticGeneratorContext::runProcessingChain(float* buf1, float* buf2, size_t frameCount) {
+ float* in = buf1;
+ float* out = buf2;
+ for (const auto processingFunc : mProcessingChain) {
+ processingFunc(out, in, frameCount);
+ std::swap(in, out);
+ }
+ return in;
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
new file mode 100644
index 0000000..a0a0a4c
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 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 <android-base/thread_annotations.h>
+#include <vibrator/ExternalVibrationUtils.h>
+#include <map>
+
+#include "Processors.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+enum HapticGeneratorState {
+ HAPTIC_GENERATOR_STATE_UNINITIALIZED,
+ HAPTIC_GENERATOR_STATE_INITIALIZED,
+ HAPTIC_GENERATOR_STATE_ACTIVE,
+};
+
+struct HapticGeneratorParam {
+ // The audio channels used to generate haptic channels. The first channel will be used to
+ // generate HAPTIC_A, The second channel will be used to generate HAPTIC_B.
+ // The value will be offset of audio channel
+ int mHapticChannelSource[2];
+
+ int mHapticChannelCount;
+ int mAudioChannelCount;
+
+ HapticGenerator::HapticScale mHapticScale;
+ std::map<int, HapticGenerator::VibratorScale> mHapticScales;
+ // max intensity will be used to scale haptic data.
+ HapticGenerator::VibratorScale mMaxVibratorScale;
+
+ HapticGenerator::VibratorInformation mVibratorInfo;
+};
+
+// A structure to keep all shared pointers for all processors in HapticGenerator.
+struct HapticGeneratorProcessorsRecord {
+ std::vector<std::shared_ptr<HapticBiquadFilter>> filters;
+ std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::Ramp>> ramps;
+ std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::SlowEnvelope>> slowEnvs;
+ std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::Distortion>> distortions;
+
+ // Cache band-pass filter and band-stop filter for updating parameters
+ // according to vibrator info
+ std::shared_ptr<HapticBiquadFilter> bpf;
+ std::shared_ptr<HapticBiquadFilter> bsf;
+};
+
+class HapticGeneratorContext final : public EffectContext {
+ public:
+ HapticGeneratorContext(int statusDepth, const Parameter::Common& common);
+ ~HapticGeneratorContext();
+ RetCode enable();
+ RetCode disable();
+ void reset();
+
+ RetCode setHgHapticScales(const std::vector<HapticGenerator::HapticScale>& hapticScales);
+ std::vector<HapticGenerator::HapticScale> getHgHapticScales();
+
+ RetCode setHgVibratorInformation(const HapticGenerator::VibratorInformation& vibratorInfo);
+ HapticGenerator::VibratorInformation getHgVibratorInformation();
+
+ IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+ private:
+ static constexpr float DEFAULT_RESONANT_FREQUENCY = 150.0f;
+ static constexpr float DEFAULT_BSF_ZERO_Q = 8.0f;
+ static constexpr float DEFAULT_BSF_POLE_Q = 4.0f;
+ static constexpr float DEFAULT_DISTORTION_OUTPUT_GAIN = 1.5f;
+ static constexpr float DEFAULT_BPF_Q = 1.0f;
+ static constexpr float DEFAULT_SLOW_ENV_NORMALIZATION_POWER = -0.8f;
+ static constexpr float DEFAULT_DISTORTION_CORNER_FREQUENCY = 300.0f;
+ static constexpr float DEFAULT_DISTORTION_INPUT_GAIN = 0.3f;
+ static constexpr float DEFAULT_DISTORTION_CUBE_THRESHOLD = 0.1f;
+
+ std::mutex mMutex;
+ HapticGeneratorState mState;
+ HapticGeneratorParam mParams GUARDED_BY(mMutex);
+ int mSampleRate;
+ int mFrameCount = 0;
+
+ // A cache for all shared pointers of the HapticGenerator
+ struct HapticGeneratorProcessorsRecord mProcessorsRecord;
+
+ // Using a vector of functions to record the processing chain for haptic-generating algorithm.
+ // The three parameters of the processing functions are pointer to output buffer, pointer to
+ // input buffer and frame count.
+ std::vector<std::function<void(float*, const float*, size_t)>> mProcessingChain;
+
+ // inputBuffer is where to keep input buffer for the generating algorithm. It will be
+ // constructed according to hapticChannelSource.
+ std::vector<float> mInputBuffer;
+
+ // outputBuffer is a buffer having the same length as inputBuffer. It can be used as
+ // intermediate buffer in the generating algorithm.
+ std::vector<float> mOutputBuffer;
+
+ void init_params(media::audio::common::AudioChannelLayout inputChMask,
+ media::audio::common::AudioChannelLayout outputChMask);
+ void configure();
+
+ float getDistortionOutputGain();
+ float getFloatProperty(const std::string& key, float defaultValue);
+ void addBiquadFilter(std::shared_ptr<HapticBiquadFilter> filter);
+ void buildProcessingChain();
+ float* runProcessingChain(float* buf1, float* buf2, size_t frameCount);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/Android.bp b/media/libeffects/loudness/Android.bp
index bcd6947..7acba11 100644
--- a/media/libeffects/loudness/Android.bp
+++ b/media/libeffects/loudness/Android.bp
@@ -44,3 +44,33 @@
header_libs: ["libaudioeffects"],
}
+
+cc_library_shared {
+ name: "libloudnessenhanceraidl",
+ srcs: [
+ "aidl/EffectLoudnessEnhancer.cpp",
+ "aidl/LoudnessEnhancerContext.cpp",
+ "dsp/core/dynamic_range_compression.cpp",
+ ":effectCommonFile",
+ ],
+ defaults: [
+ "aidlaudioservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ header_libs: [
+ "libaudioeffects",
+ "libhardware_headers",
+ ],
+ cflags: [
+ "-Wthread-safety",
+ ],
+ shared_libs: [
+ "libcutils",
+ "liblog",
+ ],
+ relative_install_path: "soundfx",
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp
new file mode 100644
index 0000000..a7d9282
--- /dev/null
+++ b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_LoudnessEnhancerImpl"
+
+#include <android-base/logging.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "EffectLoudnessEnhancer.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::getEffectImplUuidLoudnessEnhancer;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::LoudnessEnhancerImpl;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidLoudnessEnhancer()) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<LoudnessEnhancerImpl>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidLoudnessEnhancer()) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ *_aidl_return = LoudnessEnhancerImpl::kDescriptor;
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string LoudnessEnhancerImpl::kEffectName = "Loudness Enhancer";
+const Descriptor LoudnessEnhancerImpl::kDescriptor = {
+ .common = {.id = {.type = getEffectTypeUuidLoudnessEnhancer(),
+ .uuid = getEffectImplUuidLoudnessEnhancer(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT, .insert = Flags::Insert::FIRST},
+ .name = LoudnessEnhancerImpl::kEffectName,
+ .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::getDescriptor(Descriptor* _aidl_return) {
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::commandImpl(CommandId command) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (command) {
+ case CommandId::START:
+ mContext->enable();
+ break;
+ case CommandId::STOP:
+ mContext->disable();
+ break;
+ case CommandId::RESET:
+ mContext->disable();
+ mContext->resetBuffer();
+ break;
+ default:
+ LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commandIdNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::loudnessEnhancer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& leParam = specific.get<Parameter::Specific::loudnessEnhancer>();
+ auto tag = leParam.getTag();
+
+ switch (tag) {
+ case LoudnessEnhancer::gainMb: {
+ RETURN_IF(mContext->setLeGain(leParam.get<LoudnessEnhancer::gainMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setGainMbFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::loudnessEnhancerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto leId = id.get<Parameter::Id::loudnessEnhancerTag>();
+ auto leIdTag = leId.getTag();
+ switch (leIdTag) {
+ case LoudnessEnhancer::Id::commonTag:
+ return getParameterLoudnessEnhancer(leId.get<LoudnessEnhancer::Id::commonTag>(),
+ specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(leIdTag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::getParameterLoudnessEnhancer(
+ const LoudnessEnhancer::Tag& tag, Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ LoudnessEnhancer leParam;
+ switch (tag) {
+ case LoudnessEnhancer::gainMb: {
+ leParam.set<LoudnessEnhancer::gainMb>(mContext->getLeGain());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::loudnessEnhancer>(leParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> LoudnessEnhancerImpl::createContext(
+ const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+
+ mContext = std::make_shared<LoudnessEnhancerContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode LoudnessEnhancerImpl::releaseContext() {
+ if (mContext) {
+ mContext->disable();
+ mContext->resetBuffer();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status LoudnessEnhancerImpl::effectProcessImpl(float* in, float* out, int samples) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!mContext, status, "nullContext");
+ return mContext->lvmProcess(in, out, samples);
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
new file mode 100644
index 0000000..5b9e924
--- /dev/null
+++ b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 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 <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "effect-impl/EffectImpl.h"
+#include "LoudnessEnhancerContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class LoudnessEnhancerImpl final : public EffectImpl {
+ public:
+ static const std::string kEffectName;
+ static const Descriptor kDescriptor;
+ LoudnessEnhancerImpl() { LOG(DEBUG) << __func__; }
+ ~LoudnessEnhancerImpl() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ std::shared_ptr<EffectContext> getContext() override { return mContext; }
+ std::string getEffectName() override { return kEffectName; }
+
+ private:
+ std::shared_ptr<LoudnessEnhancerContext> mContext;
+ ndk::ScopedAStatus getParameterLoudnessEnhancer(const LoudnessEnhancer::Tag& tag,
+ Parameter::Specific* specific);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp
new file mode 100644
index 0000000..bc3fa45
--- /dev/null
+++ b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LoudnessEnhancerContext"
+
+#include <Utils.h>
+
+#include "LoudnessEnhancerContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+LoudnessEnhancerContext::LoudnessEnhancerContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ init_params();
+}
+
+LoudnessEnhancerContext::~LoudnessEnhancerContext() {
+ LOG(DEBUG) << __func__;
+}
+
+RetCode LoudnessEnhancerContext::enable() {
+ std::lock_guard lg(mMutex);
+ if (mState != LOUDNESS_ENHANCER_STATE_INITIALIZED) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = LOUDNESS_ENHANCER_STATE_ACTIVE;
+ return RetCode::SUCCESS;
+}
+
+RetCode LoudnessEnhancerContext::disable() {
+ std::lock_guard lg(mMutex);
+ if (mState != LOUDNESS_ENHANCER_STATE_ACTIVE) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = LOUDNESS_ENHANCER_STATE_INITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+void LoudnessEnhancerContext::reset() {
+ float targetAmp = pow(10, mGain / 2000.0f); // mB to linear amplification
+ std::lock_guard lg(mMutex);
+ if (mCompressor != nullptr) {
+ // Get samplingRate from input
+ mCompressor->Initialize(targetAmp, mCommon.input.base.sampleRate);
+ }
+}
+
+RetCode LoudnessEnhancerContext::setLeGain(int gainMb) {
+ mGain = gainMb;
+ reset(); // apply parameter update
+ return RetCode::SUCCESS;
+}
+
+IEffect::Status LoudnessEnhancerContext::lvmProcess(float* in, float* out, int samples) {
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!in, status, "nullInput");
+ RETURN_VALUE_IF(!out, status, "nullOutput");
+ status = {EX_ILLEGAL_STATE, 0, 0};
+ RETURN_VALUE_IF(getInputFrameSize() != getOutputFrameSize(), status, "FrameSizeMismatch");
+ auto frameSize = getInputFrameSize();
+ RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
+
+ std::lock_guard lg(mMutex);
+ status = {STATUS_INVALID_OPERATION, 0, 0};
+ RETURN_VALUE_IF(mState != LOUDNESS_ENHANCER_STATE_ACTIVE, status, "stateNotActive");
+
+ LOG(DEBUG) << __func__ << " start processing";
+ // PcmType is always expected to be Float 32 bit.
+ constexpr float scale = 1 << 15; // power of 2 is lossless conversion to int16_t range
+ constexpr float inverseScale = 1.f / scale;
+ const float inputAmp = pow(10, mGain / 2000.0f) * scale;
+ float leftSample, rightSample;
+
+ if (mCompressor != nullptr) {
+ for (int inIdx = 0; inIdx < samples; inIdx += 2) {
+ // makeup gain is applied on the input of the compressor
+ leftSample = inputAmp * in[inIdx];
+ rightSample = inputAmp * in[inIdx + 1];
+ mCompressor->Compress(&leftSample, &rightSample);
+ in[inIdx] = leftSample * inverseScale;
+ in[inIdx + 1] = rightSample * inverseScale;
+ }
+ } else {
+ for (int inIdx = 0; inIdx < samples; inIdx += 2) {
+ leftSample = inputAmp * in[inIdx];
+ rightSample = inputAmp * in[inIdx + 1];
+ in[inIdx] = leftSample * inverseScale;
+ in[inIdx + 1] = rightSample * inverseScale;
+ }
+ }
+ bool accumulate = false;
+ if (in != out) {
+ for (int i = 0; i < samples; i++) {
+ if (accumulate) {
+ out[i] += in[i];
+ } else {
+ out[i] = in[i];
+ }
+ }
+ }
+ return {STATUS_OK, samples, samples};
+}
+
+void LoudnessEnhancerContext::init_params() {
+ int channelCount = ::aidl::android::hardware::audio::common::getChannelCount(
+ mCommon.input.base.channelMask);
+ LOG_ALWAYS_FATAL_IF(channelCount != 2, "channel count %d not supported", channelCount);
+
+ mGain = LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB;
+ float targetAmp = pow(10, mGain / 2000.0f); // mB to linear amplification
+ LOG(DEBUG) << __func__ << "Target gain = " << mGain << "mB <=> factor = " << targetAmp;
+
+ std::lock_guard lg(mMutex);
+ mCompressor = std::make_unique<le_fx::AdaptiveDynamicRangeCompression>();
+ mCompressor->Initialize(targetAmp, mCommon.input.base.sampleRate);
+ mState = LOUDNESS_ENHANCER_STATE_INITIALIZED;
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h
new file mode 100644
index 0000000..9a1ec4c
--- /dev/null
+++ b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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 <android-base/thread_annotations.h>
+#include <audio_effects/effect_loudnessenhancer.h>
+
+#include "dsp/core/dynamic_range_compression.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+enum LoudnessEnhancerState {
+ LOUDNESS_ENHANCER_STATE_UNINITIALIZED,
+ LOUDNESS_ENHANCER_STATE_INITIALIZED,
+ LOUDNESS_ENHANCER_STATE_ACTIVE,
+};
+
+class LoudnessEnhancerContext final : public EffectContext {
+ public:
+ LoudnessEnhancerContext(int statusDepth, const Parameter::Common& common);
+ ~LoudnessEnhancerContext();
+
+ RetCode enable();
+ RetCode disable();
+ void reset();
+
+ RetCode setLeGain(int gainMb);
+ int getLeGain() const { return mGain; }
+
+ IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+ private:
+ std::mutex mMutex;
+ LoudnessEnhancerState mState GUARDED_BY(mMutex) = LOUDNESS_ENHANCER_STATE_UNINITIALIZED;
+ int mGain = LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB;
+ // In this implementation, there is no coupling between the compression on the left and right
+ // channels
+ std::unique_ptr<le_fx::AdaptiveDynamicRangeCompression> mCompressor GUARDED_BY(mMutex);
+
+ void init_params();
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/tests/Android.bp b/media/libeffects/lvm/tests/Android.bp
index 8870bb0..0568fbd 100644
--- a/media/libeffects/lvm/tests/Android.bp
+++ b/media/libeffects/lvm/tests/Android.bp
@@ -11,52 +11,33 @@
cc_test {
name: "EffectReverbTest",
- vendor: true,
- gtest: true,
- host_supported: true,
- // TODO(b/269868814)
- test_options: {
- unit_test: false,
- },
+ defaults: [
+ "libeffects-test-defaults",
+ ],
srcs: [
"EffectReverbTest.cpp",
- "EffectTestHelper.cpp",
],
static_libs: [
- "libaudioutils",
"libreverb",
"libreverbwrapper",
],
- shared_libs: [
- "liblog",
- ],
header_libs: [
"libaudioeffects",
- "libhardware_headers",
],
}
cc_test {
name: "EffectBundleTest",
- vendor: true,
- gtest: true,
- host_supported: true,
- test_suites: ["device-tests"],
+ defaults: [
+ "libeffects-test-defaults",
+ ],
srcs: [
"EffectBundleTest.cpp",
- "EffectTestHelper.cpp",
],
static_libs: [
- "libaudioutils",
"libbundlewrapper",
"libmusicbundle",
],
- shared_libs: [
- "liblog",
- ],
- header_libs: [
- "libhardware_headers",
- ],
}
cc_test {
diff --git a/media/libeffects/lvm/tests/EffectReverbTest.cpp b/media/libeffects/lvm/tests/EffectReverbTest.cpp
index 59453eb..aaac782 100644
--- a/media/libeffects/lvm/tests/EffectReverbTest.cpp
+++ b/media/libeffects/lvm/tests/EffectReverbTest.cpp
@@ -33,6 +33,27 @@
constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
+static constexpr audio_channel_mask_t kChMasks[] = {
+ AUDIO_CHANNEL_OUT_MONO, AUDIO_CHANNEL_OUT_STEREO,
+ AUDIO_CHANNEL_OUT_2POINT1, AUDIO_CHANNEL_OUT_5POINT1,
+ AUDIO_CHANNEL_OUT_7POINT1POINT4, AUDIO_CHANNEL_INDEX_MASK_23,
+ AUDIO_CHANNEL_OUT_22POINT2,
+};
+
+static constexpr size_t kNumChMasks = std::size(kChMasks);
+
+static constexpr size_t kSampleRates[] = {8000, 11025, 44100, 48000, 192000};
+
+static constexpr size_t kNumSampleRates = std::size(kSampleRates);
+
+static constexpr size_t kFrameCounts[] = {4, 512};
+
+static constexpr size_t kNumFrameCounts = std::size(kFrameCounts);
+
+static constexpr size_t kLoopCounts[] = {1, 4};
+
+static constexpr size_t kNumLoopCounts = std::size(kLoopCounts);
+
static bool isAuxMode(const effect_uuid_t* uuid) {
// Update this, if the order of effects in kEffectUuids is updated
return (uuid == &kEffectUuids[2] || uuid == &kEffectUuids[3]);
@@ -50,15 +71,15 @@
class SingleEffectTest : public ::testing::TestWithParam<SingleEffectTestParam> {
public:
SingleEffectTest()
- : mSampleRate(EffectTestHelper::kSampleRates[std::get<1>(GetParam())]),
- mFrameCount(EffectTestHelper::kFrameCounts[std::get<2>(GetParam())]),
- mLoopCount(EffectTestHelper::kLoopCounts[std::get<3>(GetParam())]),
+ : mSampleRate(kSampleRates[std::get<1>(GetParam())]),
+ mFrameCount(kFrameCounts[std::get<2>(GetParam())]),
+ mLoopCount(kLoopCounts[std::get<3>(GetParam())]),
mTotalFrameCount(mFrameCount * mLoopCount),
mUuid(&kEffectUuids[std::get<4>(GetParam())]),
mInChMask(isAuxMode(mUuid) ? AUDIO_CHANNEL_OUT_MONO
- : EffectTestHelper::kChMasks[std::get<0>(GetParam())]),
+ : kChMasks[std::get<0>(GetParam())]),
mInChannelCount(audio_channel_count_from_out_mask(mInChMask)),
- mOutChMask(EffectTestHelper::kChMasks[std::get<0>(GetParam())]),
+ mOutChMask(kChMasks[std::get<0>(GetParam())]),
mOutChannelCount(audio_channel_count_from_out_mask(mOutChMask)),
mPreset(kPresets[std::get<5>(GetParam())]) {}
@@ -100,10 +121,10 @@
INSTANTIATE_TEST_SUITE_P(
EffectReverbTestAll, SingleEffectTest,
- ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumChMasks),
- ::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
- ::testing::Range(0, (int)EffectTestHelper::kNumFrameCounts),
- ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
+ ::testing::Combine(::testing::Range(0, (int)kNumChMasks),
+ ::testing::Range(0, (int)kNumSampleRates),
+ ::testing::Range(0, (int)kNumFrameCounts),
+ ::testing::Range(0, (int)kNumLoopCounts),
::testing::Range(0, (int)kNumEffectUuids),
::testing::Range(0, (int)kNumPresets)));
@@ -112,9 +133,9 @@
: public ::testing::TestWithParam<SingleEffectComparisonTestParam> {
public:
SingleEffectComparisonTest()
- : mSampleRate(EffectTestHelper::kSampleRates[std::get<0>(GetParam())]),
- mFrameCount(EffectTestHelper::kFrameCounts[std::get<1>(GetParam())]),
- mLoopCount(EffectTestHelper::kLoopCounts[std::get<2>(GetParam())]),
+ : mSampleRate(kSampleRates[std::get<0>(GetParam())]),
+ mFrameCount(kFrameCounts[std::get<1>(GetParam())]),
+ mLoopCount(kLoopCounts[std::get<2>(GetParam())]),
mTotalFrameCount(mFrameCount * mLoopCount),
mUuid(&kEffectUuids[std::get<3>(GetParam())]),
mPreset(kPresets[std::get<4>(GetParam())]) {}
@@ -173,7 +194,7 @@
std::vector<int16_t> monoRefI16(mTotalFrameCount);
memcpy_to_i16_from_float(monoRefI16.data(), monoOutput.data(), mTotalFrameCount);
- for (size_t outChMask : EffectTestHelper::kChMasks) {
+ for (size_t outChMask : kChMasks) {
size_t outChannelCount = audio_channel_count_from_out_mask(outChMask);
size_t inChMask = isAuxMode(mUuid) ? AUDIO_CHANNEL_OUT_MONO : outChMask;
@@ -225,9 +246,9 @@
INSTANTIATE_TEST_SUITE_P(
EffectReverbTestAll, SingleEffectComparisonTest,
- ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
- ::testing::Range(0, (int)EffectTestHelper::kNumFrameCounts),
- ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
+ ::testing::Combine(::testing::Range(0, (int)kNumSampleRates),
+ ::testing::Range(0, (int)kNumFrameCounts),
+ ::testing::Range(0, (int)kNumLoopCounts),
::testing::Range(0, (int)kNumEffectUuids),
::testing::Range(0, (int)kNumPresets)));
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
new file mode 100644
index 0000000..d026e2b
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -0,0 +1,851 @@
+/*
+ * Copyright (C) 2022 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 <cstddef>
+
+#define LOG_TAG "BundleContext"
+#include <android-base/logging.h>
+#include <Utils.h>
+
+#include "BundleContext.h"
+#include "BundleTypes.h"
+#include "math.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+using ::aidl::android::media::audio::common::AudioChannelLayout;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+using ::aidl::android::media::audio::common::AudioDeviceType;
+
+RetCode BundleContext::init() {
+ std::lock_guard lg(mMutex);
+ // init with pre-defined preset NORMAL
+ for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ mBandGaindB[i] = lvm::kSoftPresets[0 /* normal */][i];
+ }
+
+ // allocate lvm instance
+ LVM_ReturnStatus_en status;
+ LVM_InstParams_t params = {.BufferMode = LVM_UNMANAGED_BUFFERS,
+ .MaxBlockSize = lvm::MAX_CALL_SIZE,
+ .EQNB_NumBands = lvm::MAX_NUM_BANDS,
+ .PSA_Included = LVM_PSA_ON};
+ status = LVM_GetInstanceHandle(&mInstance, ¶ms);
+ GOTO_IF_LVM_ERROR(status, deinit, "LVM_GetInstanceHandleFailed");
+
+ // set control
+ LVM_ControlParams_t controlParams;
+ initControlParameter(controlParams);
+ status = LVM_SetControlParameters(mInstance, &controlParams);
+ GOTO_IF_LVM_ERROR(status, deinit, "LVM_SetControlParametersFailed");
+
+ /* Set the headroom parameters */
+ LVM_HeadroomParams_t headroomParams;
+ initHeadroomParameter(headroomParams);
+ status = LVM_SetHeadroomParams(mInstance, &headroomParams);
+ GOTO_IF_LVM_ERROR(status, deinit, "LVM_SetHeadroomParamsFailed");
+
+ return RetCode::SUCCESS;
+
+deinit:
+ deInit();
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+}
+
+void BundleContext::deInit() {
+ std::lock_guard lg(mMutex);
+ if (mInstance) {
+ LVM_DelInstanceHandle(&mInstance);
+ mInstance = nullptr;
+ }
+}
+
+RetCode BundleContext::enable() {
+ if (mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
+ // Bass boost or Virtualizer can be temporarily disabled if playing over device speaker due to
+ // their nature.
+ bool tempDisabled = false;
+ switch (mType) {
+ case lvm::BundleEffectType::EQUALIZER:
+ LOG(DEBUG) << __func__ << " enable bundle EQ";
+ if (mSamplesToExitCountEq <= 0) mNumberEffectsEnabled++;
+ mSamplesToExitCountEq = (mSamplesPerSecond * 0.1);
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
+ break;
+ case lvm::BundleEffectType::BASS_BOOST:
+ LOG(DEBUG) << __func__ << " enable bundle BB";
+ if (mSamplesToExitCountBb <= 0) mNumberEffectsEnabled++;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
+ mSamplesToExitCountBb = (mSamplesPerSecond * 0.1);
+ tempDisabled = mBassTempDisabled;
+ break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ LOG(DEBUG) << __func__ << " enable bundle VR";
+ if (mSamplesToExitCountVirt <= 0) mNumberEffectsEnabled++;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+ mSamplesToExitCountVirt = (mSamplesPerSecond * 0.1);
+ tempDisabled = mVirtualizerTempDisabled;
+ break;
+ case lvm::BundleEffectType::VOLUME:
+ LOG(DEBUG) << __func__ << " enable bundle VOL";
+ if ((mEffectInDrain & (1 << int(lvm::BundleEffectType::VOLUME))) == 0)
+ mNumberEffectsEnabled++;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
+ break;
+ }
+ mEnabled = true;
+ return (tempDisabled ? RetCode::SUCCESS : enableOperatingMode());
+}
+
+RetCode BundleContext::enableOperatingMode() {
+ LVM_ControlParams_t params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "failGetControlParams");
+ switch (mType) {
+ case lvm::BundleEffectType::EQUALIZER:
+ LOG(DEBUG) << __func__ << " enable bundle EQ";
+ params.EQNB_OperatingMode = LVM_EQNB_ON;
+ break;
+ case lvm::BundleEffectType::BASS_BOOST:
+ LOG(DEBUG) << __func__ << " enable bundle BB";
+ params.BE_OperatingMode = LVM_BE_ON;
+ break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ LOG(DEBUG) << __func__ << " enable bundle VR";
+ params.VirtualizerOperatingMode = LVM_MODE_ON;
+ break;
+ case lvm::BundleEffectType::VOLUME:
+ LOG(DEBUG) << __func__ << " enable bundle VOL";
+ break;
+ }
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
+ }
+ return limitLevel();
+}
+
+RetCode BundleContext::disable() {
+ if (!mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
+ switch (mType) {
+ case lvm::BundleEffectType::EQUALIZER:
+ LOG(DEBUG) << __func__ << " disable bundle EQ";
+ mEffectInDrain |= 1 << int(lvm::BundleEffectType::EQUALIZER);
+ break;
+ case lvm::BundleEffectType::BASS_BOOST:
+ LOG(DEBUG) << __func__ << " disable bundle BB";
+ mEffectInDrain |= 1 << int(lvm::BundleEffectType::BASS_BOOST);
+ break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ LOG(DEBUG) << __func__ << " disable bundle VR";
+ mEffectInDrain |= 1 << int(lvm::BundleEffectType::VIRTUALIZER);
+ break;
+ case lvm::BundleEffectType::VOLUME:
+ LOG(DEBUG) << __func__ << " disable bundle VOL";
+ mEffectInDrain |= 1 << int(lvm::BundleEffectType::VOLUME);
+ break;
+ }
+ mEnabled = false;
+ return disableOperatingMode();
+}
+
+RetCode BundleContext::disableOperatingMode() {
+ LVM_ControlParams_t params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "failGetControlParams");
+ switch (mType) {
+ case lvm::BundleEffectType::EQUALIZER:
+ LOG(DEBUG) << __func__ << " disable bundle EQ";
+ params.EQNB_OperatingMode = LVM_EQNB_OFF;
+ break;
+ case lvm::BundleEffectType::BASS_BOOST:
+ LOG(DEBUG) << __func__ << " disable bundle BB";
+ params.BE_OperatingMode = LVM_BE_OFF;
+ break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ LOG(DEBUG) << __func__ << " disable bundle VR";
+ params.VirtualizerOperatingMode = LVM_MODE_OFF;
+ break;
+ case lvm::BundleEffectType::VOLUME:
+ LOG(DEBUG) << __func__ << " disable bundle VOL";
+ break;
+ }
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
+ }
+ mEnabled = false;
+ return limitLevel();
+}
+
+RetCode BundleContext::limitLevel() {
+ int gainCorrection = 0;
+ // Count the energy contribution per band for EQ and BassBoost only if they are active.
+ float energyContribution = 0;
+ float energyCross = 0;
+ float energyBassBoost = 0;
+ float crossCorrection = 0;
+ LVM_ControlParams_t params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ bool eqEnabled = params.EQNB_OperatingMode == LVM_EQNB_ON;
+ bool bbEnabled = params.BE_OperatingMode == LVM_BE_ON;
+ bool viEnabled = params.VirtualizerOperatingMode == LVM_MODE_ON;
+
+ if (eqEnabled) {
+ for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ float bandFactor = mBandGaindB[i] / 15.0;
+ float bandCoefficient = lvm::kBandEnergyCoefficient[i];
+ float bandEnergy = bandFactor * bandCoefficient * bandCoefficient;
+ if (bandEnergy > 0) energyContribution += bandEnergy;
+ }
+
+ // cross EQ coefficients
+ float bandFactorSum = 0;
+ for (int i = 0; i < lvm::MAX_NUM_BANDS - 1; i++) {
+ float bandFactor1 = mBandGaindB[i] / 15.0;
+ float bandFactor2 = mBandGaindB[i + 1] / 15.0;
+
+ if (bandFactor1 > 0 && bandFactor2 > 0) {
+ float crossEnergy =
+ bandFactor1 * bandFactor2 * lvm::kBandEnergyCrossCoefficient[i];
+ bandFactorSum += bandFactor1 * bandFactor2;
+
+ if (crossEnergy > 0) energyCross += crossEnergy;
+ }
+ }
+ bandFactorSum -= 1.0;
+ if (bandFactorSum > 0) crossCorrection = bandFactorSum * 0.7;
+ }
+ // BassBoost contribution
+ if (bbEnabled) {
+ float boostFactor = mBassStrengthSaved / 1000.0;
+ float boostCoefficient = lvm::kBassBoostEnergyCoefficient;
+
+ energyContribution += boostFactor * boostCoefficient * boostCoefficient;
+
+ if (eqEnabled) {
+ for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ float bandFactor = mBandGaindB[i] / 15.0;
+ float bandCrossCoefficient = lvm::kBassBoostEnergyCrossCoefficient[i];
+ float bandEnergy = boostFactor * bandFactor * bandCrossCoefficient;
+ if (bandEnergy > 0) energyBassBoost += bandEnergy;
+ }
+ }
+ }
+ // Virtualizer contribution
+ if (viEnabled) {
+ energyContribution += lvm::kVirtualizerContribution * lvm::kVirtualizerContribution;
+ }
+
+ double totalEnergyEstimation =
+ sqrt(energyContribution + energyCross + energyBassBoost) - crossCorrection;
+ LOG(INFO) << " TOTAL energy estimation: " << totalEnergyEstimation << " dB";
+
+ // roundoff
+ int maxLevelRound = (int)(totalEnergyEstimation + 0.99);
+ if (maxLevelRound + mVolume > 0) {
+ gainCorrection = maxLevelRound + mVolume;
+ }
+
+ params.VC_EffectLevel = mVolume - gainCorrection;
+ if (params.VC_EffectLevel < -96) {
+ params.VC_EffectLevel = -96;
+ }
+ LOG(INFO) << "\tVol: " << mVolume << ", GainCorrection: " << gainCorrection
+ << ", Actual vol: " << params.VC_EffectLevel;
+
+ /* Activate the initial settings */
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+
+ if (mFirstVolume) {
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetVolumeNoSmoothing(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setVolumeNoSmoothingFailed");
+ LOG(INFO) << "\tLVM_VOLUME: Disabling Smoothing for first volume change to remove "
+ "spikes/clicks";
+ mFirstVolume = false;
+ }
+ }
+
+ return RetCode::SUCCESS;
+}
+
+bool BundleContext::isDeviceSupportedBassBoost(
+ const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& devices) {
+ for (const auto& device : devices) {
+ if (device != AudioDeviceDescription{AudioDeviceType::OUT_SPEAKER, ""} &&
+ device != AudioDeviceDescription{AudioDeviceType::OUT_CARKIT,
+ AudioDeviceDescription::CONNECTION_BT_SCO} &&
+ device != AudioDeviceDescription{AudioDeviceType::OUT_SPEAKER,
+ AudioDeviceDescription::CONNECTION_BT_A2DP}) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool BundleContext::isDeviceSupportedVirtualizer(
+ const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& devices) {
+ for (const auto& device : devices) {
+ if (device != AudioDeviceDescription{AudioDeviceType::OUT_HEADSET,
+ AudioDeviceDescription::CONNECTION_ANALOG} &&
+ device != AudioDeviceDescription{AudioDeviceType::OUT_HEADPHONE,
+ AudioDeviceDescription::CONNECTION_ANALOG} &&
+ device != AudioDeviceDescription{AudioDeviceType::OUT_HEADPHONE,
+ AudioDeviceDescription::CONNECTION_BT_A2DP} &&
+ device != AudioDeviceDescription{AudioDeviceType::OUT_HEADSET,
+ AudioDeviceDescription::CONNECTION_USB}) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool BundleContext::isConfigSupportedVirtualizer(size_t channelCount,
+ const AudioDeviceDescription& device) {
+ return (channelCount >= 1 && channelCount <= FCC_2) && isDeviceSupportedVirtualizer({device});
+}
+
+RetCode BundleContext::setOutputDevice(
+ const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& devices) {
+ mOutputDevice = devices;
+ switch (mType) {
+ case lvm::BundleEffectType::BASS_BOOST:
+ if (!isDeviceSupportedBassBoost(devices)) {
+ // If a device doesn't support bass boost, the effect must be temporarily disabled.
+ // The effect must still report its original state as this can only be changed by
+ // the start/stop commands.
+ if (mEnabled) {
+ disableOperatingMode();
+ }
+ mBassTempDisabled = true;
+ } else {
+ // If a device supports bass boost and the effect has been temporarily disabled
+ // previously then re-enable it
+ if (!mEnabled) {
+ enableOperatingMode();
+ }
+ mBassTempDisabled = false;
+ }
+ break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ if (!isDeviceSupportedVirtualizer(devices)) {
+ if (mEnabled) {
+ disableOperatingMode();
+ }
+ mVirtualizerTempDisabled = true;
+ } else {
+ if (!mEnabled) {
+ enableOperatingMode();
+ }
+ mVirtualizerTempDisabled = false;
+ }
+ break;
+ default:
+ break;
+ }
+ return RetCode::SUCCESS;
+}
+
+LVM_INT16 BundleContext::LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const {
+ LVM_INT16 db_fix;
+ LVM_INT16 Shift;
+ LVM_INT16 SmallRemainder;
+ LVM_UINT32 Remainder = (LVM_UINT32)Lin_fix;
+
+ /* Count leading bits, 1 cycle in assembly*/
+ for (Shift = 0; Shift < 32; Shift++) {
+ if ((Remainder & 0x80000000U) != 0) {
+ break;
+ }
+ Remainder = Remainder << 1;
+ }
+
+ /*
+ * Based on the approximation equation (for Q11.4 format):
+ *
+ * dB = -96 * Shift + 16 * (8 * Remainder - 2 * Remainder^2)
+ */
+ db_fix = (LVM_INT16)(-96 * Shift); /* Six dB steps in Q11.4 format*/
+ SmallRemainder = (LVM_INT16)((Remainder & 0x7fffffff) >> 24);
+ db_fix = (LVM_INT16)(db_fix + SmallRemainder);
+ SmallRemainder = (LVM_INT16)(SmallRemainder * SmallRemainder);
+ db_fix = (LVM_INT16)(db_fix - (LVM_INT16)((LVM_UINT16)SmallRemainder >> 9));
+
+ /* Correct for small offset */
+ db_fix = (LVM_INT16)(db_fix - 5);
+
+ return db_fix;
+}
+
+// TODO: replace with more generic approach, like: audio_utils_power_from_amplitude
+int16_t BundleContext::VolToDb(uint32_t vol) const {
+ int16_t dB;
+
+ dB = LVC_ToDB_s32Tos16(vol << 7);
+ dB = (dB + 8) >> 4;
+ dB = (dB < -96) ? -96 : dB;
+
+ return dB;
+}
+
+RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) {
+ LVM_ControlParams_t params;
+ LVM_ReturnStatus_en status = LVM_SUCCESS;
+
+ // Convert volume to dB
+ int leftdB = VolToDb(volume.left);
+ int rightdB = VolToDb(volume.right);
+ int maxdB = std::max(leftdB, rightdB);
+ int pandB = rightdB - leftdB;
+ setVolumeLevel(maxdB * 100);
+ LOG(DEBUG) << __func__ << " pandB: " << pandB << " maxdB " << maxdB;
+
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "");
+ params.VC_Balance = pandB;
+
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "");
+ }
+ mVolumeStereo = volume;
+ return RetCode::SUCCESS;
+}
+
+RetCode BundleContext::setEqualizerPreset(const std::size_t presetIdx) {
+ if (presetIdx < 0 || presetIdx >= lvm::MAX_NUM_PRESETS) {
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+
+ std::vector<Equalizer::BandLevel> bandLevels;
+ bandLevels.reserve(lvm::MAX_NUM_BANDS);
+ for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ bandLevels.emplace_back(
+ Equalizer::BandLevel{static_cast<int32_t>(i), lvm::kSoftPresets[presetIdx][i]});
+ }
+
+ RetCode ret = updateControlParameter(bandLevels);
+ if (RetCode::SUCCESS == ret) {
+ mCurPresetIdx = presetIdx;
+ LOG(INFO) << __func__ << " success with " << presetIdx;
+ } else {
+ LOG(ERROR) << __func__ << " failed to setPreset " << presetIdx;
+ }
+ return ret;
+}
+
+RetCode BundleContext::setEqualizerBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels) {
+ RETURN_VALUE_IF(bandLevels.size() > lvm::MAX_NUM_BANDS || bandLevels.empty(),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "sizeExceedMax");
+ RetCode ret = updateControlParameter(bandLevels);
+ if (RetCode::SUCCESS == ret) {
+ mCurPresetIdx = lvm::PRESET_CUSTOM;
+ LOG(INFO) << __func__ << " succeed with " << ::android::internal::ToString(bandLevels);
+ } else {
+ LOG(ERROR) << __func__ << " failed with " << ::android::internal::ToString(bandLevels);
+ }
+ return ret;
+}
+
+std::vector<Equalizer::BandLevel> BundleContext::getEqualizerBandLevels() const {
+ std::vector<Equalizer::BandLevel> bandLevels;
+ bandLevels.reserve(lvm::MAX_NUM_BANDS);
+ for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ bandLevels.emplace_back(Equalizer::BandLevel{static_cast<int32_t>(i), mBandGaindB[i]});
+ }
+ return bandLevels;
+}
+
+std::vector<int32_t> BundleContext::getEqualizerCenterFreqs() {
+ std::vector<int32_t> freqs;
+
+ LVM_ControlParams_t params;
+ {
+ std::lock_guard lg(mMutex);
+ /* Get the current settings */
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms), freqs,
+ " getControlParamFailed");
+ for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ freqs.push_back((int32_t)params.pEQNB_BandDefinition[i].Frequency * 1000);
+ }
+ }
+
+ return freqs;
+}
+
+bool BundleContext::isBandLevelIndexInRange(
+ const std::vector<Equalizer::BandLevel>& bandLevels) const {
+ const auto [min, max] =
+ std::minmax_element(bandLevels.begin(), bandLevels.end(),
+ [](const auto& a, const auto& b) { return a.index < b.index; });
+ return min->index >= 0 && max->index < lvm::MAX_NUM_BANDS;
+}
+
+RetCode BundleContext::updateControlParameter(const std::vector<Equalizer::BandLevel>& bandLevels) {
+ RETURN_VALUE_IF(!isBandLevelIndexInRange(bandLevels), RetCode::ERROR_ILLEGAL_PARAMETER,
+ "indexOutOfRange");
+
+ std::array<int, lvm::MAX_NUM_BANDS> tempLevel;
+ for (const auto& it : bandLevels) {
+ tempLevel[it.index] = it.levelMb;
+ }
+
+ LVM_ControlParams_t params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ params.pEQNB_BandDefinition[i].Frequency = lvm::kPresetsFrequencies[i];
+ params.pEQNB_BandDefinition[i].QFactor = lvm::kPresetsQFactors[i];
+ params.pEQNB_BandDefinition[i].Gain = tempLevel[i];
+ }
+
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ }
+ mBandGaindB = tempLevel;
+ LOG(INFO) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGaindB);
+
+ return RetCode::SUCCESS;
+}
+
+RetCode BundleContext::setBassBoostStrength(int strength) {
+ // Update Control Parameter
+ LVM_ControlParams_t params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ params.BE_EffectLevel = (LVM_INT16)((15 * strength) / 1000);
+ params.BE_CentreFreq = LVM_BE_CENTRE_90Hz;
+
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ }
+ mBassStrengthSaved = strength;
+ LOG(INFO) << __func__ << " success with strength " << strength;
+ return limitLevel();
+}
+
+RetCode BundleContext::setVolumeLevel(int level) {
+ if (mMuteEnabled) {
+ mLevelSaved = level / 100;
+ } else {
+ mVolume = level / 100;
+ }
+ LOG(INFO) << __func__ << " success with level " << level;
+ return limitLevel();
+}
+
+int BundleContext::getVolumeLevel() const {
+ return (mMuteEnabled ? mLevelSaved * 100 : mVolume * 100);
+}
+
+RetCode BundleContext::setVolumeMute(bool mute) {
+ mMuteEnabled = mute;
+ if (mMuteEnabled) {
+ mLevelSaved = mVolume;
+ mVolume = -96;
+ } else {
+ mVolume = mLevelSaved;
+ }
+ return limitLevel();
+}
+
+RetCode BundleContext::setVirtualizerStrength(int strength) {
+ // Update Control Parameter
+ LVM_ControlParams_t params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ params.CS_EffectLevel = ((strength * 32767) / 1000);
+
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ }
+
+ mVirtStrengthSaved = strength;
+ LOG(INFO) << __func__ << " success with strength " << strength;
+ return limitLevel();
+}
+
+
+RetCode BundleContext::setForcedDevice(
+ const ::aidl::android::media::audio::common::AudioDeviceDescription& device) {
+ RETURN_VALUE_IF(true != isDeviceSupportedVirtualizer({device}), RetCode::ERROR_EFFECT_LIB_ERROR,
+ " deviceNotSupportVirtualizer");
+ mForceDevice = device;
+ return RetCode::SUCCESS;
+}
+
+void BundleContext::initControlParameter(LVM_ControlParams_t& params) const {
+ /* General parameters */
+ params.OperatingMode = LVM_MODE_ON;
+ params.SampleRate = LVM_FS_44100;
+ params.SourceFormat = LVM_STEREO;
+ params.SpeakerType = LVM_HEADPHONES;
+
+ /* Concert Sound parameters */
+ params.VirtualizerOperatingMode = LVM_MODE_OFF;
+ params.VirtualizerType = LVM_CONCERTSOUND;
+ params.VirtualizerReverbLevel = 100;
+ params.CS_EffectLevel = LVM_CS_EFFECT_NONE;
+
+ params.EQNB_OperatingMode = LVM_EQNB_OFF;
+ params.EQNB_NBands = lvm::MAX_NUM_BANDS;
+ params.pEQNB_BandDefinition = getDefaultEqualizerBandDefs();
+
+ /* Volume Control parameters */
+ params.VC_EffectLevel = 0;
+ params.VC_Balance = 0;
+
+ /* Treble Enhancement parameters */
+ params.TE_OperatingMode = LVM_TE_OFF;
+ params.TE_EffectLevel = 0;
+
+ /* PSA Control parameters */
+ params.PSA_Enable = LVM_PSA_OFF;
+ params.PSA_PeakDecayRate = (LVM_PSA_DecaySpeed_en)0;
+
+ /* Bass Enhancement parameters */
+ params.BE_OperatingMode = LVM_BE_OFF;
+ params.BE_EffectLevel = 0;
+ params.BE_CentreFreq = LVM_BE_CENTRE_90Hz;
+ params.BE_HPF = LVM_BE_HPF_ON;
+
+ /* PSA Control parameters */
+ params.PSA_Enable = LVM_PSA_OFF;
+ params.PSA_PeakDecayRate = LVM_PSA_SPEED_MEDIUM;
+
+ /* TE Control parameters */
+ params.TE_OperatingMode = LVM_TE_OFF;
+ params.TE_EffectLevel = 0;
+
+ params.NrChannels = audio_channel_count_from_out_mask(AUDIO_CHANNEL_OUT_STEREO);
+ params.ChMask = AUDIO_CHANNEL_OUT_STEREO;
+ params.SourceFormat = LVM_STEREO;
+}
+
+void BundleContext::initHeadroomParameter(LVM_HeadroomParams_t& params) const {
+ params.pHeadroomDefinition = getDefaultEqualizerHeadroomBanDefs();
+ params.NHeadroomBands = 2;
+ params.Headroom_OperatingMode = LVM_HEADROOM_OFF;
+}
+
+LVM_EQNB_BandDef_t *BundleContext::getDefaultEqualizerBandDefs() {
+ static LVM_EQNB_BandDef_t* BandDefs = []() {
+ static LVM_EQNB_BandDef_t tempDefs[lvm::MAX_NUM_BANDS];
+ /* N-Band Equaliser parameters */
+ for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ tempDefs[i].Frequency = lvm::kPresetsFrequencies[i];
+ tempDefs[i].QFactor = lvm::kPresetsQFactors[i];
+ tempDefs[i].Gain = lvm::kSoftPresets[0/* normal */][i];
+ }
+ return tempDefs;
+ }();
+
+ return BandDefs;
+}
+
+LVM_HeadroomBandDef_t *BundleContext::getDefaultEqualizerHeadroomBanDefs() {
+ static LVM_HeadroomBandDef_t HeadroomBandDef[LVM_HEADROOM_MAX_NBANDS] = {
+ {
+ .Limit_Low = 20,
+ .Limit_High = 4999,
+ .Headroom_Offset = 0,
+ },
+ {
+ .Limit_Low = 5000,
+ .Limit_High = 24000,
+ .Headroom_Offset = 0,
+ },
+ };
+ return HeadroomBandDef;
+}
+
+std::vector<Virtualizer::ChannelAngle> BundleContext::getSpeakerAngles(
+ const Virtualizer::SpeakerAnglesPayload payload) {
+ std::vector<Virtualizer::ChannelAngle> angles;
+ auto chCount = ::aidl::android::hardware::audio::common::getChannelCount(payload.layout);
+ RETURN_VALUE_IF(!isConfigSupportedVirtualizer(chCount, payload.device), angles,
+ "payloadNotSupported");
+
+ if (chCount == 1) {
+ angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT,
+ .azimuthDegree = 0,
+ .elevationDegree = 0}};
+ } else {
+ angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT,
+ .azimuthDegree = -90,
+ .elevationDegree = 0},
+ {.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_RIGHT,
+ .azimuthDegree = 90,
+ .elevationDegree = 0}};
+ }
+ return angles;
+}
+
+IEffect::Status BundleContext::lvmProcess(float* in, float* out, int samples) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!in, status, "nullInput");
+ RETURN_VALUE_IF(!out, status, "nullOutput");
+ status = {EX_ILLEGAL_STATE, 0, 0};
+ int64_t inputFrameCount = getCommon().input.frameCount;
+ int64_t outputFrameCount = getCommon().output.frameCount;
+ RETURN_VALUE_IF(inputFrameCount != outputFrameCount, status, "FrameCountMismatch");
+ int isDataAvailable = true;
+
+ auto frameSize = getInputFrameSize();
+ RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
+
+ LOG(DEBUG) << __func__ << " start processing";
+ if ((mEffectProcessCalled & 1 << int(mType)) != 0) {
+ const int undrainedEffects = mEffectInDrain & ~mEffectProcessCalled;
+ if ((undrainedEffects & 1 << int(lvm::BundleEffectType::EQUALIZER)) != 0) {
+ LOG(DEBUG) << "Draining EQUALIZER";
+ mSamplesToExitCountEq = 0;
+ --mNumberEffectsEnabled;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
+ }
+ if ((undrainedEffects & 1 << int(lvm::BundleEffectType::BASS_BOOST)) != 0) {
+ LOG(DEBUG) << "Draining BASS_BOOST";
+ mSamplesToExitCountBb = 0;
+ --mNumberEffectsEnabled;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
+ }
+ if ((undrainedEffects & 1 << int(lvm::BundleEffectType::VIRTUALIZER)) != 0) {
+ LOG(DEBUG) << "Draining VIRTUALIZER";
+ mSamplesToExitCountVirt = 0;
+ --mNumberEffectsEnabled;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+ }
+ if ((undrainedEffects & 1 << int(lvm::BundleEffectType::VOLUME)) != 0) {
+ LOG(DEBUG) << "Draining VOLUME";
+ --mNumberEffectsEnabled;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
+ }
+ }
+ mEffectProcessCalled |= 1 << int(mType);
+ if (!mEnabled) {
+ switch (mType) {
+ case lvm::BundleEffectType::EQUALIZER:
+ if (mSamplesToExitCountEq > 0) {
+ mSamplesToExitCountEq -= samples;
+ }
+ if (mSamplesToExitCountEq <= 0) {
+ isDataAvailable = false;
+ if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::EQUALIZER)) != 0) {
+ mNumberEffectsEnabled--;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
+ }
+ LOG(DEBUG) << "Effect_process() this is the last frame for EQUALIZER";
+ }
+ break;
+ case lvm::BundleEffectType::BASS_BOOST:
+ if (mSamplesToExitCountBb > 0) {
+ mSamplesToExitCountBb -= samples;
+ }
+ if (mSamplesToExitCountBb <= 0) {
+ isDataAvailable = false;
+ if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::BASS_BOOST)) != 0) {
+ mNumberEffectsEnabled--;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
+ }
+ LOG(DEBUG) << "Effect_process() this is the last frame for BASS_BOOST";
+ }
+ break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ if (mSamplesToExitCountVirt > 0) {
+ mSamplesToExitCountVirt -= samples;
+ }
+ if (mSamplesToExitCountVirt <= 0) {
+ isDataAvailable = false;
+ if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::VIRTUALIZER)) != 0) {
+ mNumberEffectsEnabled--;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+ }
+ LOG(DEBUG) << "Effect_process() this is the last frame for VIRTUALIZER";
+ }
+ break;
+ case lvm::BundleEffectType::VOLUME:
+ isDataAvailable = false;
+ if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::VOLUME)) != 0) {
+ mNumberEffectsEnabled--;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
+ }
+ LOG(DEBUG) << "Effect_process() LVM_VOLUME Effect is not enabled";
+ break;
+ }
+ }
+ if (isDataAvailable) {
+ mNumberEffectsCalled++;
+ }
+ bool accumulate = false;
+ if (mNumberEffectsCalled >= mNumberEffectsEnabled) {
+ // We expect the # effects called to be equal to # effects enabled in sequence (including
+ // draining effects). Warn if this is not the case due to inconsistent calls.
+ ALOGW_IF(mNumberEffectsCalled > mNumberEffectsEnabled,
+ "%s Number of effects called %d is greater than number of effects enabled %d",
+ __func__, mNumberEffectsCalled, mNumberEffectsEnabled);
+ mEffectProcessCalled = 0; // reset our consistency check.
+ if (!isDataAvailable) {
+ LOG(DEBUG) << "Effect_process() processing last frame";
+ }
+ mNumberEffectsCalled = 0;
+ LVM_UINT16 frames = samples * sizeof(float) / frameSize;
+ float* outTmp = (accumulate ? getWorkBuffer() : out);
+ /* Process the samples */
+ LVM_ReturnStatus_en lvmStatus;
+ {
+ std::lock_guard lg(mMutex);
+ lvmStatus = LVM_Process(mInstance, in, outTmp, frames, 0);
+ if (lvmStatus != LVM_SUCCESS) {
+ LOG(ERROR) << __func__ << lvmStatus;
+ return {EX_UNSUPPORTED_OPERATION, 0, 0};
+ }
+ if (accumulate) {
+ for (int i = 0; i < samples; i++) {
+ out[i] += outTmp[i];
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < samples; i++) {
+ if (accumulate) {
+ out[i] += in[i];
+ } else {
+ out[i] = in[i];
+ }
+ }
+ }
+ LOG(DEBUG) << __func__ << " done processing";
+ return {STATUS_OK, samples, samples};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
new file mode 100644
index 0000000..47d5e5a
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2022 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 <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+#include <array>
+#include <cstddef>
+
+#include "BundleTypes.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class BundleContext final : public EffectContext {
+ public:
+ BundleContext(int statusDepth, const Parameter::Common& common,
+ const lvm::BundleEffectType& type)
+ : EffectContext(statusDepth, common), mType(type) {
+ LOG(DEBUG) << __func__ << type;
+ }
+ ~BundleContext() override {
+ LOG(DEBUG) << __func__;
+ deInit();
+ }
+
+ RetCode init();
+ void deInit();
+ lvm::BundleEffectType getBundleType() const { return mType; }
+
+ RetCode enable();
+ RetCode enableOperatingMode();
+ RetCode disable();
+ RetCode disableOperatingMode();
+
+ void setSampleRate(const int sampleRate) { mSampleRate = sampleRate; }
+ int getSampleRate() const { return mSampleRate; }
+
+ void setChannelMask(const aidl::android::media::audio::common::AudioChannelLayout& chMask) {
+ mChMask = chMask;
+ }
+ aidl::android::media::audio::common::AudioChannelLayout getChannelMask() const {
+ return mChMask;
+ }
+ bool isDeviceSupportedBassBoost(
+ const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>&
+ devices);
+ bool isDeviceSupportedVirtualizer(
+ const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>&
+ devices);
+ bool isConfigSupportedVirtualizer(
+ size_t channelCount,
+ const aidl::android::media::audio::common::AudioDeviceDescription& device);
+
+ RetCode setOutputDevice(
+ const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& devices)
+ override;
+
+ RetCode setEqualizerPreset(const std::size_t presetIdx);
+ int getEqualizerPreset() const { return mCurPresetIdx; }
+ RetCode setEqualizerBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels);
+ std::vector<Equalizer::BandLevel> getEqualizerBandLevels() const;
+
+ std::vector<int32_t> getEqualizerCenterFreqs();
+
+ RetCode setBassBoostStrength(int strength);
+ int getBassBoostStrength() const { return mBassStrengthSaved; }
+
+ RetCode setVolumeLevel(int level);
+ int getVolumeLevel() const;
+
+ RetCode setVolumeMute(bool mute);
+ int getVolumeMute() const { return mMuteEnabled; }
+
+ RetCode setVirtualizerStrength(int strength);
+ int getVirtualizerStrength() const { return mVirtStrengthSaved; }
+
+ RetCode setForcedDevice(
+ const ::aidl::android::media::audio::common::AudioDeviceDescription& device);
+ aidl::android::media::audio::common::AudioDeviceDescription getForcedDevice() const {
+ return mForceDevice;
+ }
+ std::vector<Virtualizer::ChannelAngle> getSpeakerAngles(
+ const Virtualizer::SpeakerAnglesPayload payload);
+
+ RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
+ Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
+
+ IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+ IEffect::Status processEffect(float* in, float* out, int sampleToProcess);
+
+ private:
+ std::mutex mMutex;
+ const lvm::BundleEffectType mType;
+ bool mEnabled = false;
+ LVM_Handle_t mInstance GUARDED_BY(mMutex);
+
+ aidl::android::media::audio::common::AudioDeviceDescription mVirtualizerForcedDevice;
+ aidl::android::media::audio::common::AudioChannelLayout mChMask;
+
+ int mSampleRate = LVM_FS_44100;
+ int mSamplesPerSecond = 0;
+ int mSamplesToExitCountEq = 0;
+ int mSamplesToExitCountBb = 0;
+ int mSamplesToExitCountVirt = 0;
+ int mFrameCount = 0;
+
+ /* Bitmask whether drain is in progress due to disabling the effect.
+ The corresponding bit to an effect is set by 1 << lvm_effect_en. */
+ int mEffectInDrain = 0;
+
+ /* Bitmask whether process() was called for a particular effect.
+ The corresponding bit to an effect is set by 1 << lvm_effect_en. */
+ int mEffectProcessCalled = 0;
+ int mNumberEffectsEnabled = 0;
+ int mNumberEffectsCalled = 0;
+ bool mFirstVolume = true;
+ // Bass
+ bool mBassTempDisabled = false;
+ int mBassStrengthSaved = 0;
+ // Equalizer
+ int mCurPresetIdx = lvm::PRESET_CUSTOM; /* Current preset being used */
+ std::array<int, lvm::MAX_NUM_BANDS> mBandGaindB;
+ // Virtualizer
+ int mVirtStrengthSaved = 0; /* Conversion between Get/Set */
+ bool mVirtualizerTempDisabled = false;
+ ::aidl::android::media::audio::common::AudioDeviceDescription mForceDevice;
+ // Volume
+ int mLevelSaved = 0; /* for when mute is set, level must be saved */
+ int mVolume = 0;
+ bool mMuteEnabled = false; /* Must store as mute = -96dB level */
+
+ void initControlParameter(LVM_ControlParams_t& params) const;
+ void initHeadroomParameter(LVM_HeadroomParams_t& params) const;
+ RetCode limitLevel();
+ int16_t VolToDb(uint32_t vol) const;
+ LVM_INT16 LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const;
+ RetCode updateControlParameter(const std::vector<Equalizer::BandLevel>& bandLevels);
+ bool isBandLevelIndexInRange(const std::vector<Equalizer::BandLevel>& bandLevels) const;
+ static LVM_EQNB_BandDef_t* getDefaultEqualizerBandDefs();
+ static LVM_HeadroomBandDef_t* getDefaultEqualizerHeadroomBanDefs();
+};
+
+} // namespace aidl::android::hardware::audio::effect
+
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
new file mode 100644
index 0000000..b3371a3
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2022 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 <array>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "effect-impl/EffectTypes.h"
+#include "LVM.h"
+
+namespace aidl::android::hardware::audio::effect {
+namespace lvm {
+
+constexpr inline size_t MAX_NUM_PRESETS = 10;
+constexpr inline size_t MAX_NUM_BANDS = 5;
+constexpr inline size_t MAX_CALL_SIZE = 256;
+constexpr inline int BASS_BOOST_CUP_LOAD_ARM9E = 150; // Expressed in 0.1 MIPS
+constexpr inline int VIRTUALIZER_CUP_LOAD_ARM9E = 120; // Expressed in 0.1 MIPS
+constexpr inline int EQUALIZER_CUP_LOAD_ARM9E = 220; // Expressed in 0.1 MIPS
+constexpr inline int VOLUME_CUP_LOAD_ARM9E = 0; // Expressed in 0.1 MIPS
+constexpr inline int BUNDLE_MEM_USAGE = 25; // Expressed in kB
+constexpr inline int PRESET_CUSTOM = -1;
+
+static const std::vector<Equalizer::BandFrequency> kEqBandFrequency = {{0, 30000, 120000},
+ {1, 120001, 460000},
+ {2, 460001, 1800000},
+ {3, 1800001, 7000000},
+ {4, 7000001, 20000000}};
+
+/*
+Frequencies in Hz
+Note: If these frequencies change, please update LimitLevel values accordingly.
+*/
+constexpr inline std::array<uint16_t, MAX_NUM_BANDS> kPresetsFrequencies = {60, 230, 910, 3600,
+ 14000};
+
+/* Q factor multiplied by 100 */
+constexpr inline std::array<uint16_t, MAX_NUM_BANDS> kPresetsQFactors = {96, 96, 96, 96, 96};
+
+constexpr inline std::array<std::array<int16_t, MAX_NUM_BANDS>, MAX_NUM_PRESETS> kSoftPresets = {
+ {{3, 0, 0, 0, 3}, /* Normal Preset */
+ {5, 3, -2, 4, 4}, /* Classical Preset */
+ {6, 0, 2, 4, 1}, /* Dance Preset */
+ {0, 0, 0, 0, 0}, /* Flat Preset */
+ {3, 0, 0, 2, -1}, /* Folk Preset */
+ {4, 1, 9, 3, 0}, /* Heavy Metal Preset */
+ {5, 3, 0, 1, 3}, /* Hip Hop Preset */
+ {4, 2, -2, 2, 5}, /* Jazz Preset */
+ {-1, 2, 5, 1, -2}, /* Pop Preset */
+ {5, 3, -1, 3, 5}}}; /* Rock Preset */
+
+static const std::vector<Equalizer::Preset> kEqPresets = {
+ {0, "Normal"}, {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
+ {5, "Heavy Metal"}, {6, "Hip Hop"}, {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}};
+
+
+const std::vector<Range::EqualizerRange> kEqRanges = {
+ MAKE_RANGE(Equalizer, preset, 0, MAX_NUM_PRESETS - 1),
+ MAKE_RANGE(Equalizer, bandLevels,
+ std::vector<Equalizer::BandLevel>{
+ Equalizer::BandLevel({.index = 0, .levelMb = -15})},
+ std::vector<Equalizer::BandLevel>{
+ Equalizer::BandLevel({.index = MAX_NUM_BANDS - 1, .levelMb = 15})}),
+ /* capability definition */
+ MAKE_RANGE(Equalizer, bandFrequencies, kEqBandFrequency, kEqBandFrequency),
+ MAKE_RANGE(Equalizer, presets, kEqPresets, kEqPresets),
+ /* get only parameters with range min > max */
+ MAKE_RANGE(Equalizer, centerFreqMh, std::vector<int>({1}), std::vector<int>({}))};
+static const Capability kEqCap = {.range = kEqRanges};
+static const std::string kEqualizerEffectName = "EqualizerBundle";
+static const Descriptor kEqualizerDesc = {
+ .common = {.id = {.type = getEffectTypeUuidEqualizer(),
+ .uuid = getEffectImplUuidEqualizerBundle(),
+ .proxy = getEffectImplUuidEqualizerProxy()},
+
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = kEqualizerEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = kEqCap};
+
+static const int mMaxStrengthSupported = 1000;
+static const std::vector<Range::BassBoostRange> kBassBoostRanges = {
+ MAKE_RANGE(BassBoost, strengthPm, 0, mMaxStrengthSupported)};
+static const Capability kBassBoostCap = {.range = kBassBoostRanges};
+static const std::string kBassBoostEffectName = "Dynamic Bass Boost";
+static const Descriptor kBassBoostDesc = {
+ .common = {.id = {.type = getEffectTypeUuidBassBoost(),
+ .uuid = getEffectImplUuidBassBoostBundle(),
+ .proxy = getEffectImplUuidBassBoostProxy()},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL,
+ .deviceIndication = true},
+ .cpuLoad = BASS_BOOST_CUP_LOAD_ARM9E,
+ .memoryUsage = BUNDLE_MEM_USAGE,
+ .name = kBassBoostEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = kBassBoostCap};
+
+static const std::vector<Range::VirtualizerRange> kVirtualizerRanges = {
+ MAKE_RANGE(Virtualizer, strengthPm, 0, mMaxStrengthSupported)};
+static const Capability kVirtualizerCap = {.range = kVirtualizerRanges};
+static const std::string kVirtualizerEffectName = "Virtualizer";
+
+static const Descriptor kVirtualizerDesc = {
+ .common = {.id = {.type = getEffectTypeUuidVirtualizer(),
+ .uuid = getEffectImplUuidVirtualizerBundle(),
+ .proxy = getEffectImplUuidVirtualizerProxy()},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::LAST,
+ .volume = Flags::Volume::CTRL,
+ .deviceIndication = true},
+ .cpuLoad = VIRTUALIZER_CUP_LOAD_ARM9E,
+ .memoryUsage = BUNDLE_MEM_USAGE,
+ .name = kVirtualizerEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = kVirtualizerCap};
+
+static const std::vector<Range::VolumeRange> kVolumeRanges = {
+ MAKE_RANGE(Volume, levelDb, -9600, 0)};
+static const Capability kVolumeCap = {.range = kVolumeRanges};
+static const std::string kVolumeEffectName = "Volume";
+static const Descriptor kVolumeDesc = {
+ .common = {.id = {.type = getEffectTypeUuidVolume(),
+ .uuid = getEffectImplUuidVolumeBundle(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::LAST,
+ .volume = Flags::Volume::CTRL},
+ .cpuLoad = VOLUME_CUP_LOAD_ARM9E,
+ .memoryUsage = BUNDLE_MEM_USAGE,
+ .name = kVolumeEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = kVolumeCap};
+
+/* The following tables have been computed using the actual levels measured by the output of
+ * white noise or pink noise (IEC268-1) for the EQ and BassBoost Effects. These are estimates of
+ * the actual energy that 'could' be present in the given band.
+ * If the frequency values in EQNB_5BandPresetsFrequencies change, these values might need to be
+ * updated.
+ */
+constexpr inline std::array<float, MAX_NUM_BANDS> kBandEnergyCoefficient = {7.56, 9.69, 9.59, 7.37,
+ 2.88};
+
+constexpr inline std::array<float, MAX_NUM_BANDS - 1> kBandEnergyCrossCoefficient = {126.0, 115.0,
+ 125.0, 104.0};
+
+constexpr inline std::array<float, MAX_NUM_BANDS> kBassBoostEnergyCrossCoefficient = {
+ 221.21, 208.10, 28.16, 0.0, 0.0};
+
+constexpr inline float kBassBoostEnergyCoefficient = 9.00;
+
+constexpr inline float kVirtualizerContribution = 1.9;
+
+enum class BundleEffectType {
+ BASS_BOOST,
+ VIRTUALIZER,
+ EQUALIZER,
+ VOLUME,
+};
+
+inline std::ostream& operator<<(std::ostream& out, const BundleEffectType& type) {
+ switch (type) {
+ case BundleEffectType::BASS_BOOST:
+ return out << "BASS_BOOST";
+ case BundleEffectType::VIRTUALIZER:
+ return out << "VIRTUALIZER";
+ case BundleEffectType::EQUALIZER:
+ return out << "EQUALIZER";
+ case BundleEffectType::VOLUME:
+ return out << "VOLUME";
+ }
+ return out << "EnumBundleEffectTypeError";
+}
+
+inline std::ostream& operator<<(std::ostream& out, const LVM_ReturnStatus_en& status) {
+ switch (status) {
+ case LVM_SUCCESS:
+ return out << "LVM_SUCCESS";
+ case LVM_ALIGNMENTERROR:
+ return out << "LVM_ALIGNMENTERROR";
+ case LVM_NULLADDRESS:
+ return out << "LVM_NULLADDRESS";
+ case LVM_OUTOFRANGE:
+ return out << "LVM_OUTOFRANGE";
+ case LVM_INVALIDNUMSAMPLES:
+ return out << "LVM_INVALIDNUMSAMPLES";
+ case LVM_WRONGAUDIOTIME:
+ return out << "LVM_WRONGAUDIOTIME";
+ case LVM_ALGORITHMDISABLED:
+ return out << "LVM_ALGORITHMDISABLED";
+ case LVM_ALGORITHMPSA:
+ return out << "LVM_ALGORITHMPSA";
+ case LVM_RETURNSTATUS_DUMMY:
+ return out << "LVM_RETURNSTATUS_DUMMY";
+ }
+ return out << "EnumLvmRetStatusError";
+}
+
+#define GOTO_IF_LVM_ERROR(status, tag, log) \
+ do { \
+ LVM_ReturnStatus_en temp = (status); \
+ if (temp != LVM_SUCCESS) { \
+ LOG(ERROR) << __func__ << " return status: " << temp << " " << (log); \
+ goto tag; \
+ } \
+ } while (0)
+
+} // namespace lvm
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
new file mode 100644
index 0000000..cd9fb60
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) 2022 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 "BundleTypes.h"
+#define LOG_TAG "EffectBundleAidl"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+#include <audio_effects/effect_bassboost.h>
+#include <audio_effects/effect_equalizer.h>
+#include <audio_effects/effect_virtualizer.h>
+
+#include "EffectBundleAidl.h"
+#include <LVM.h>
+#include <limits.h>
+
+using aidl::android::hardware::audio::effect::getEffectImplUuidBassBoostBundle;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectBundleAidl;
+using aidl::android::hardware::audio::effect::getEffectImplUuidEqualizerBundle;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::hardware::audio::effect::getEffectImplUuidVirtualizerBundle;
+using aidl::android::hardware::audio::effect::getEffectImplUuidVolumeBundle;
+using aidl::android::media::audio::common::AudioUuid;
+
+bool isUuidSupported(const AudioUuid* uuid) {
+ return (*uuid == getEffectImplUuidBassBoostBundle() ||
+ *uuid == getEffectImplUuidEqualizerBundle() ||
+ *uuid == getEffectImplUuidVirtualizerBundle() ||
+ *uuid == getEffectImplUuidVolumeBundle());
+}
+
+extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (uuid == nullptr || !isUuidSupported(uuid)) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<EffectBundleAidl>(*uuid);
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || !isUuidSupported(in_impl_uuid)) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (*in_impl_uuid == getEffectImplUuidEqualizerBundle()) {
+ *_aidl_return = aidl::android::hardware::audio::effect::lvm::kEqualizerDesc;
+ } else if (*in_impl_uuid == getEffectImplUuidBassBoostBundle()) {
+ *_aidl_return = aidl::android::hardware::audio::effect::lvm:: kBassBoostDesc;
+ } else if (*in_impl_uuid == getEffectImplUuidVirtualizerBundle()) {
+ *_aidl_return = aidl::android::hardware::audio::effect::lvm::kVirtualizerDesc;
+ } else if (*in_impl_uuid == getEffectImplUuidVolumeBundle()) {
+ *_aidl_return = aidl::android::hardware::audio::effect::lvm::kVolumeDesc;
+ }
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+EffectBundleAidl::EffectBundleAidl(const AudioUuid& uuid) {
+ LOG(DEBUG) << __func__ << uuid.toString();
+ if (uuid == getEffectImplUuidEqualizerBundle()) {
+ mType = lvm::BundleEffectType::EQUALIZER;
+ mDescriptor = &lvm::kEqualizerDesc;
+ mEffectName = &lvm::kEqualizerEffectName;
+ } else if (uuid == getEffectImplUuidBassBoostBundle()) {
+ mType = lvm::BundleEffectType::BASS_BOOST;
+ mDescriptor = &lvm::kBassBoostDesc;
+ mEffectName = &lvm::kBassBoostEffectName;
+ } else if (uuid == getEffectImplUuidVirtualizerBundle()) {
+ mType = lvm::BundleEffectType::VIRTUALIZER;
+ mDescriptor = &lvm::kVirtualizerDesc;
+ mEffectName = &lvm::kVirtualizerEffectName;
+ } else if (uuid == getEffectImplUuidVolumeBundle()) {
+ mType = lvm::BundleEffectType::VOLUME;
+ mDescriptor = &lvm::kVolumeDesc;
+ mEffectName = &lvm::kVolumeEffectName;
+ } else {
+ LOG(ERROR) << __func__ << uuid.toString() << " not supported!";
+ }
+}
+
+EffectBundleAidl::~EffectBundleAidl() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getDescriptor(Descriptor* _aidl_return) {
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ LOG(DEBUG) << _aidl_return->toString();
+ *_aidl_return = *mDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterCommon(const Parameter& param) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto tag = param.getTag();
+ switch (tag) {
+ case Parameter::common:
+ RETURN_IF(mContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setCommFailed");
+ break;
+ case Parameter::deviceDescription:
+ RETURN_IF(mContext->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
+ break;
+ case Parameter::mode:
+ RETURN_IF(mContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setModeFailed");
+ break;
+ case Parameter::source:
+ RETURN_IF(mContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setSourceFailed");
+ break;
+ case Parameter::volumeStereo:
+ RETURN_IF(mContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed");
+ break;
+ default: {
+ LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commonParamNotSupported");
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterSpecific(const Parameter::Specific& specific) {
+ LOG(DEBUG) << __func__ << " specific " << specific.toString();
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto tag = specific.getTag();
+ switch (tag) {
+ case Parameter::Specific::equalizer:
+ return setParameterEqualizer(specific);
+ case Parameter::Specific::bassBoost:
+ return setParameterBassBoost(specific);
+ case Parameter::Specific::virtualizer:
+ return setParameterVirtualizer(specific);
+ case Parameter::Specific::volume:
+ return setParameterVolume(specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "specificParamNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterEqualizer(const Parameter::Specific& specific) {
+ auto& eq = specific.get<Parameter::Specific::equalizer>();
+ RETURN_IF(!inRange(eq, lvm::kEqRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+ auto eqTag = eq.getTag();
+ switch (eqTag) {
+ case Equalizer::preset:
+ RETURN_IF(mContext->setEqualizerPreset(eq.get<Equalizer::preset>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
+ return ndk::ScopedAStatus::ok();
+ case Equalizer::bandLevels:
+ RETURN_IF(mContext->setEqualizerBandLevels(eq.get<Equalizer::bandLevels>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
+ return ndk::ScopedAStatus::ok();
+ default:
+ LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "eqTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterBassBoost(const Parameter::Specific& specific) {
+ auto& bb = specific.get<Parameter::Specific::bassBoost>();
+ RETURN_IF(!inRange(bb, lvm::kBassBoostRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+ auto bbTag = bb.getTag();
+ switch (bbTag) {
+ case BassBoost::strengthPm: {
+ RETURN_IF(mContext->setBassBoostStrength(bb.get<BassBoost::strengthPm>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setStrengthFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default:
+ LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "bbTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterVirtualizer(const Parameter::Specific& specific) {
+ auto& vr = specific.get<Parameter::Specific::virtualizer>();
+ RETURN_IF(!inRange(vr, lvm::kVirtualizerRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+ auto vrTag = vr.getTag();
+ switch (vrTag) {
+ case Virtualizer::strengthPm: {
+ RETURN_IF(mContext->setVirtualizerStrength(vr.get<Virtualizer::strengthPm>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setStrengthFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Virtualizer::device: {
+ RETURN_IF(mContext->setForcedDevice(vr.get<Virtualizer::device>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Virtualizer::speakerAngles:
+ FALLTHROUGH_INTENDED;
+ case Virtualizer::vendor: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(vrTag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VirtualizerTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterVolume(const Parameter::Specific& specific) {
+ auto& vol = specific.get<Parameter::Specific::volume>();
+ RETURN_IF(!inRange(vol, lvm::kVolumeRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+ auto volTag = vol.getTag();
+ switch (volTag) {
+ case Volume::levelDb: {
+ RETURN_IF(mContext->setVolumeLevel(vol.get<Volume::levelDb>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setLevelFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Volume::mute:
+ RETURN_IF(mContext->setVolumeMute(vol.get<Volume::mute>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setMuteFailed");
+ return ndk::ScopedAStatus::ok();
+ default:
+ LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "volTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+ auto tag = id.getTag();
+
+ switch (tag) {
+ case Parameter::Id::equalizerTag:
+ return getParameterEqualizer(id.get<Parameter::Id::equalizerTag>(), specific);
+ case Parameter::Id::bassBoostTag:
+ return getParameterBassBoost(id.get<Parameter::Id::bassBoostTag>(), specific);
+ case Parameter::Id::virtualizerTag:
+ return getParameterVirtualizer(id.get<Parameter::Id::virtualizerTag>(), specific);
+ case Parameter::Id::volumeTag:
+ return getParameterVolume(id.get<Parameter::Id::volumeTag>(), specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "wrongIdTag");
+ }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterEqualizer(const Equalizer::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != Equalizer::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "EqualizerTagNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ Equalizer eqParam;
+
+ auto tag = id.get<Equalizer::Id::commonTag>();
+ switch (tag) {
+ case Equalizer::bandLevels: {
+ eqParam.set<Equalizer::bandLevels>(mContext->getEqualizerBandLevels());
+ break;
+ }
+ case Equalizer::preset: {
+ eqParam.set<Equalizer::preset>(mContext->getEqualizerPreset());
+ break;
+ }
+ case Equalizer::bandFrequencies: {
+ eqParam.set<Equalizer::bandFrequencies>(lvm::kEqBandFrequency);
+ break;
+ }
+ case Equalizer::presets: {
+ eqParam.set<Equalizer::presets>(lvm::kEqPresets);
+ break;
+ }
+ case Equalizer::centerFreqMh: {
+ eqParam.set<Equalizer::centerFreqMh>(mContext->getEqualizerCenterFreqs());
+ break;
+ }
+ case Equalizer::vendor: {
+ LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "unsupportedTag");
+ }
+ }
+
+ specific->set<Parameter::Specific::equalizer>(eqParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterBassBoost(const BassBoost::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != BassBoost::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "BassBoostTagNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ BassBoost bbParam;
+
+ auto tag = id.get<BassBoost::Id::commonTag>();
+ switch (tag) {
+ case BassBoost::strengthPm: {
+ bbParam.set<BassBoost::strengthPm>(mContext->getBassBoostStrength());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "BassBoostTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::bassBoost>(bbParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterVolume(const Volume::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != Volume::Id::commonTag, EX_ILLEGAL_ARGUMENT, "VolumeTagNotSupported");
+
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ Volume volParam;
+
+ auto tag = id.get<Volume::Id::commonTag>();
+ switch (tag) {
+ case Volume::levelDb: {
+ volParam.set<Volume::levelDb>(mContext->getVolumeLevel());
+ break;
+ }
+ case Volume::mute: {
+ volParam.set<Volume::mute>(mContext->getVolumeMute());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VolumeTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::volume>(volParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterVirtualizer(const Virtualizer::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF((id.getTag() != Virtualizer::Id::commonTag) &&
+ (id.getTag() != Virtualizer::Id::speakerAnglesPayload),
+ EX_ILLEGAL_ARGUMENT, "VirtualizerTagNotSupported");
+
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ Virtualizer vrParam;
+
+ if (id.getTag() == Virtualizer::Id::speakerAnglesPayload) {
+ auto angles = mContext->getSpeakerAngles(id.get<Virtualizer::Id::speakerAnglesPayload>());
+ Virtualizer param = Virtualizer::make<Virtualizer::speakerAngles>(angles);
+ specific->set<Parameter::Specific::virtualizer>(param);
+ return ndk::ScopedAStatus::ok();
+ }
+
+ auto tag = id.get<Virtualizer::Id::commonTag>();
+ switch (tag) {
+ case Virtualizer::strengthPm: {
+ vrParam.set<Virtualizer::strengthPm>(mContext->getVirtualizerStrength());
+ break;
+ }
+ case Virtualizer::device: {
+ vrParam.set<Virtualizer::device>(mContext->getForcedDevice());
+ break;
+ }
+ case Virtualizer::speakerAngles:
+ FALLTHROUGH_INTENDED;
+ case Virtualizer::vendor: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VirtualizerTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::virtualizer>(vrParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> EffectBundleAidl::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ } else {
+ // GlobalSession is a singleton
+ mContext = GlobalSession::getGlobalSession().createSession(mType, 1 /* statusFmqDepth */,
+ common);
+ }
+
+ return mContext;
+}
+
+std::shared_ptr<EffectContext> EffectBundleAidl::getContext() {
+ return mContext;
+}
+
+RetCode EffectBundleAidl::releaseContext() {
+ if (mContext) {
+ GlobalSession::getGlobalSession().releaseSession(mType, mContext->getSessionId());
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+ndk::ScopedAStatus EffectBundleAidl::commandImpl(CommandId command) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (command) {
+ case CommandId::START:
+ mContext->enable();
+ break;
+ case CommandId::STOP:
+ mContext->disable();
+ break;
+ case CommandId::RESET:
+ mContext->disable();
+ mContext->resetBuffer();
+ break;
+ default:
+ LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commandIdNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status EffectBundleAidl::effectProcessImpl(float* in, float* out, int sampleToProcess) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!mContext, status, "nullContext");
+ return mContext->lvmProcess(in, out, sampleToProcess);
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
new file mode 100644
index 0000000..ec1abe8
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 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 <functional>
+#include <map>
+#include <memory>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <android-base/logging.h>
+
+#include "effect-impl/EffectImpl.h"
+
+#include "BundleContext.h"
+#include "BundleTypes.h"
+#include "GlobalSession.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectBundleAidl final : public EffectImpl {
+ public:
+ explicit EffectBundleAidl(const AudioUuid& uuid);
+ ~EffectBundleAidl() override;
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterCommon(const Parameter& param) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ std::shared_ptr<EffectContext> getContext() override;
+ RetCode releaseContext() override;
+
+ IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+
+ std::string getEffectName() override { return *mEffectName; }
+
+ private:
+ std::shared_ptr<BundleContext> mContext;
+ const Descriptor* mDescriptor;
+ const std::string* mEffectName;
+ lvm::BundleEffectType mType = lvm::BundleEffectType::EQUALIZER;
+
+ IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
+
+ ndk::ScopedAStatus setParameterBassBoost(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterBassBoost(const BassBoost::Id& id,
+ Parameter::Specific* specific);
+
+ ndk::ScopedAStatus setParameterEqualizer(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Id& id,
+ Parameter::Specific* specific);
+ ndk::ScopedAStatus setParameterVolume(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterVolume(const Volume::Id& id, Parameter::Specific* specific);
+ ndk::ScopedAStatus setParameterVirtualizer(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterVirtualizer(const Virtualizer::Id& id,
+ Parameter::Specific* specific);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/GlobalSession.h b/media/libeffects/lvm/wrapper/Aidl/GlobalSession.h
new file mode 100644
index 0000000..d31763b
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/GlobalSession.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2022 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 <algorithm>
+#include <memory>
+#include <unordered_map>
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+
+#include "BundleContext.h"
+#include "BundleTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+/**
+ * @brief Maintain all effect bundle sessions.
+ *
+ * Sessions are identified with the session ID, maximum of MAX_BUNDLE_SESSIONS is supported by the
+ * bundle implementation.
+ */
+class GlobalSession {
+ public:
+ static GlobalSession& getGlobalSession() {
+ static GlobalSession instance;
+ return instance;
+ }
+
+ bool isSessionIdExist(int sessionId) {
+ std::lock_guard lg(mMutex);
+ return mSessionMap.count(sessionId);
+ }
+
+ static bool findBundleTypeInList(std::vector<std::shared_ptr<BundleContext>>& list,
+ const lvm::BundleEffectType& type, bool remove = false) {
+ auto itor = std::find_if(list.begin(), list.end(),
+ [type](const std::shared_ptr<BundleContext>& bundle) {
+ return bundle ? bundle->getBundleType() == type : false;
+ });
+ if (itor == list.end()) {
+ return false;
+ }
+ if (remove && *itor) {
+ (*itor)->deInit();
+ list.erase(itor);
+ }
+ return true;
+ }
+
+ /**
+ * Create a certain type of BundleContext in shared_ptr container, each session must not have
+ * more than one session for each type.
+ */
+ std::shared_ptr<BundleContext> createSession(const lvm::BundleEffectType& type, int statusDepth,
+ const Parameter::Common& common) {
+ int sessionId = common.session;
+ LOG(DEBUG) << __func__ << type << " with sessionId " << sessionId;
+ std::lock_guard lg(mMutex);
+ if (mSessionMap.count(sessionId) == 0 && mSessionMap.size() >= MAX_BUNDLE_SESSIONS) {
+ LOG(ERROR) << __func__ << " exceed max bundle session";
+ return nullptr;
+ }
+
+ if (mSessionMap.count(sessionId)) {
+ if (findBundleTypeInList(mSessionMap[sessionId], type)) {
+ LOG(ERROR) << __func__ << type << " already exist in session " << sessionId;
+ return nullptr;
+ }
+ }
+
+ auto& list = mSessionMap[sessionId];
+ auto context = std::make_shared<BundleContext>(statusDepth, common, type);
+ RETURN_VALUE_IF(!context, nullptr, "failedToCreateContext");
+
+ RetCode ret = context->init();
+ if (RetCode::SUCCESS != ret) {
+ LOG(ERROR) << __func__ << " context init ret " << ret;
+ return nullptr;
+ }
+ list.push_back(context);
+ return context;
+ }
+
+ void releaseSession(const lvm::BundleEffectType& type, int sessionId) {
+ LOG(DEBUG) << __func__ << type << " sessionId " << sessionId;
+ std::lock_guard lg(mMutex);
+ if (mSessionMap.count(sessionId)) {
+ auto& list = mSessionMap[sessionId];
+ if (!findBundleTypeInList(list, type, true /* remove */)) {
+ LOG(ERROR) << __func__ << " can't find " << type << "in session " << sessionId;
+ return;
+ }
+ if (list.size() == 0) {
+ mSessionMap.erase(sessionId);
+ }
+ }
+ }
+
+ private:
+ // Lock for mSessionMap access.
+ std::mutex mMutex;
+ // Max session number supported.
+ static constexpr int MAX_BUNDLE_SESSIONS = 32;
+ std::unordered_map<int /* session ID */, std::vector<std::shared_ptr<BundleContext>>>
+ mSessionMap GUARDED_BY(mMutex);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Android.bp b/media/libeffects/lvm/wrapper/Android.bp
index 1287514..fa300d2 100644
--- a/media/libeffects/lvm/wrapper/Android.bp
+++ b/media/libeffects/lvm/wrapper/Android.bp
@@ -100,3 +100,66 @@
integer_overflow: true,
},
}
+
+cc_library_shared {
+ name: "libbundleaidl",
+ srcs: [
+ "Aidl/BundleContext.cpp",
+ "Aidl/EffectBundleAidl.cpp",
+ ":effectCommonFile",
+ ],
+ static_libs: ["libmusicbundle"],
+ defaults: [
+ "aidlaudioservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ local_include_dirs: ["Aidl"],
+ header_libs: [
+ "libaudioeffects",
+ "libhardware_headers",
+ ],
+ shared_libs: [
+ "liblog",
+ ],
+ cflags: [
+ "-Wthread-safety",
+ ],
+ relative_install_path: "soundfx",
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
+
+cc_library_shared {
+ name: "libreverbaidl",
+ srcs: [
+ "Reverb/aidl/ReverbContext.cpp",
+ "Reverb/aidl/EffectReverb.cpp",
+ ":effectCommonFile",
+ ],
+ static_libs: ["libreverb"],
+ defaults: [
+ "aidlaudioservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ local_include_dirs: ["Reverb/aidl"],
+ header_libs: [
+ "libaudioeffects",
+ "libhardware_headers",
+ ],
+ shared_libs: [
+ "libbase",
+ "libaudioutils",
+ "libcutils",
+ "liblog",
+ ],
+ cflags: [
+ "-Wthread-safety",
+ ],
+ relative_install_path: "soundfx",
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
new file mode 100644
index 0000000..73141b6
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
@@ -0,0 +1,399 @@
+/*
+ * Copyright (C) 2023 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 "ReverbTypes.h"
+#define LOG_TAG "EffectReverb"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+#include <audio_effects/effect_bassboost.h>
+#include <audio_effects/effect_equalizer.h>
+#include <audio_effects/effect_virtualizer.h>
+
+#include "EffectReverb.h"
+#include <limits.h>
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectReverb;
+using aidl::android::hardware::audio::effect::getEffectImplUuidAuxEnvReverb;
+using aidl::android::hardware::audio::effect::getEffectImplUuidAuxPresetReverb;
+using aidl::android::hardware::audio::effect::getEffectImplUuidInsertEnvReverb;
+using aidl::android::hardware::audio::effect::getEffectImplUuidInsertPresetReverb;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+bool isReverbUuidSupported(const AudioUuid* uuid) {
+ return (*uuid == getEffectImplUuidAuxEnvReverb() ||
+ *uuid == getEffectImplUuidAuxPresetReverb() ||
+ *uuid == getEffectImplUuidInsertEnvReverb() ||
+ *uuid == getEffectImplUuidInsertPresetReverb());
+}
+
+extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (uuid == nullptr || !isReverbUuidSupported(uuid)) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<EffectReverb>(*uuid);
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (*in_impl_uuid == getEffectImplUuidAuxEnvReverb()) {
+ *_aidl_return = aidl::android::hardware::audio::effect::lvm::kAuxEnvReverbDesc;
+ } else if (*in_impl_uuid == getEffectImplUuidInsertEnvReverb()) {
+ *_aidl_return = aidl::android::hardware::audio::effect::lvm::kInsertEnvReverbDesc;
+ } else if (*in_impl_uuid == getEffectImplUuidAuxPresetReverb()) {
+ *_aidl_return = aidl::android::hardware::audio::effect::lvm::kAuxPresetReverbDesc;
+ } else if (*in_impl_uuid == getEffectImplUuidInsertPresetReverb()) {
+ *_aidl_return = aidl::android::hardware::audio::effect::lvm::kInsertPresetReverbDesc;
+ } else {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+EffectReverb::EffectReverb(const AudioUuid& uuid) {
+ LOG(DEBUG) << __func__ << uuid.toString();
+ if (uuid == getEffectImplUuidAuxEnvReverb()) {
+ mType = lvm::ReverbEffectType::AUX_ENV;
+ mDescriptor = &lvm::kAuxEnvReverbDesc;
+ mEffectName = &lvm::kAuxEnvReverbEffectName;
+ } else if (uuid == getEffectImplUuidInsertEnvReverb()) {
+ mType = lvm::ReverbEffectType::INSERT_ENV;
+ mDescriptor = &lvm::kInsertEnvReverbDesc;
+ mEffectName = &lvm::kInsertEnvReverbEffectName;
+ } else if (uuid == getEffectImplUuidAuxPresetReverb()) {
+ mType = lvm::ReverbEffectType::AUX_PRESET;
+ mDescriptor = &lvm::kAuxPresetReverbDesc;
+ mEffectName = &lvm::kAuxPresetReverbEffectName;
+ } else if (uuid == getEffectImplUuidInsertPresetReverb()) {
+ mType = lvm::ReverbEffectType::INSERT_PRESET;
+ mDescriptor = &lvm::kInsertPresetReverbDesc;
+ mEffectName = &lvm::kInsertPresetReverbEffectName;
+ } else {
+ LOG(ERROR) << __func__ << uuid.toString() << " not supported!";
+ }
+}
+
+EffectReverb::~EffectReverb() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+}
+
+ndk::ScopedAStatus EffectReverb::getDescriptor(Descriptor* _aidl_return) {
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ LOG(DEBUG) << _aidl_return->toString();
+ *_aidl_return = *mDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectReverb::setParameterSpecific(const Parameter::Specific& specific) {
+ LOG(DEBUG) << __func__ << " specific " << specific.toString();
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto tag = specific.getTag();
+ switch (tag) {
+ case Parameter::Specific::presetReverb:
+ return setParameterPresetReverb(specific);
+ case Parameter::Specific::environmentalReverb:
+ return setParameterEnvironmentalReverb(specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "specificParamNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EffectReverb::setParameterPresetReverb(const Parameter::Specific& specific) {
+ auto& prParam = specific.get<Parameter::Specific::presetReverb>();
+ RETURN_IF(!inRange(prParam, lvm::kPresetReverbRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+ auto tag = prParam.getTag();
+
+ switch (tag) {
+ case PresetReverb::preset: {
+ RETURN_IF(mContext->setPresetReverbPreset(prParam.get<PresetReverb::preset>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setPresetFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "PresetReverbTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus EffectReverb::setParameterEnvironmentalReverb(
+ const Parameter::Specific& specific) {
+ auto& erParam = specific.get<Parameter::Specific::environmentalReverb>();
+ RETURN_IF(!inRange(erParam, lvm::kEnvReverbRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+ auto tag = erParam.getTag();
+
+ switch (tag) {
+ case EnvironmentalReverb::roomLevelMb: {
+ RETURN_IF(mContext->setEnvironmentalReverbRoomLevel(
+ erParam.get<EnvironmentalReverb::roomLevelMb>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setRoomLevelFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::roomHfLevelMb: {
+ RETURN_IF(
+ mContext->setEnvironmentalReverbRoomHfLevel(
+ erParam.get<EnvironmentalReverb::roomHfLevelMb>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setRoomHfLevelFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::decayTimeMs: {
+ RETURN_IF(mContext->setEnvironmentalReverbDecayTime(
+ erParam.get<EnvironmentalReverb::decayTimeMs>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDecayTimeFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::decayHfRatioPm: {
+ RETURN_IF(
+ mContext->setEnvironmentalReverbDecayHfRatio(
+ erParam.get<EnvironmentalReverb::decayHfRatioPm>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDecayHfRatioFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::reflectionsLevelMb: {
+ RETURN_IF(mContext->setReflectionsLevel(
+ erParam.get<EnvironmentalReverb::reflectionsLevelMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setReflectionsLevelFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::reflectionsDelayMs: {
+ RETURN_IF(mContext->setReflectionsDelay(
+ erParam.get<EnvironmentalReverb::reflectionsDelayMs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setReflectionsDelayFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::levelMb: {
+ RETURN_IF(mContext->setEnvironmentalReverbLevel(
+ erParam.get<EnvironmentalReverb::levelMb>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setLevelFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::delayMs: {
+ RETURN_IF(mContext->setEnvironmentalReverbDelay(
+ erParam.get<EnvironmentalReverb::delayMs>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDelayFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::diffusionPm: {
+ RETURN_IF(mContext->setEnvironmentalReverbDiffusion(
+ erParam.get<EnvironmentalReverb::diffusionPm>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDiffusionFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::densityPm: {
+ RETURN_IF(mContext->setEnvironmentalReverbDensity(
+ erParam.get<EnvironmentalReverb::densityPm>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDensityFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::bypass: {
+ RETURN_IF(mContext->setEnvironmentalReverbBypass(
+ erParam.get<EnvironmentalReverb::bypass>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setBypassFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus EffectReverb::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+ auto tag = id.getTag();
+
+ switch (tag) {
+ case Parameter::Id::presetReverbTag:
+ return getParameterPresetReverb(id.get<Parameter::Id::presetReverbTag>(), specific);
+ case Parameter::Id::environmentalReverbTag:
+ return getParameterEnvironmentalReverb(id.get<Parameter::Id::environmentalReverbTag>(),
+ specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "wrongIdTag");
+ }
+}
+
+ndk::ScopedAStatus EffectReverb::getParameterPresetReverb(const PresetReverb::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != PresetReverb::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "PresetReverbTagNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ PresetReverb prParam;
+ auto tag = id.get<PresetReverb::Id::commonTag>();
+ switch (tag) {
+ case PresetReverb::preset: {
+ prParam.set<PresetReverb::preset>(mContext->getPresetReverbPreset());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "PresetReverbTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::presetReverb>(prParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectReverb::getParameterEnvironmentalReverb(const EnvironmentalReverb::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != EnvironmentalReverb::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "EnvironmentalReverbTagNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ EnvironmentalReverb erParam;
+
+ auto tag = id.get<EnvironmentalReverb::Id::commonTag>();
+ switch (tag) {
+ case EnvironmentalReverb::roomLevelMb: {
+ erParam.set<EnvironmentalReverb::roomLevelMb>(
+ mContext->getEnvironmentalReverbRoomLevel());
+ break;
+ }
+ case EnvironmentalReverb::roomHfLevelMb: {
+ erParam.set<EnvironmentalReverb::roomHfLevelMb>(
+ mContext->getEnvironmentalReverbRoomHfLevel());
+ break;
+ }
+ case EnvironmentalReverb::decayTimeMs: {
+ erParam.set<EnvironmentalReverb::decayTimeMs>(
+ mContext->getEnvironmentalReverbDecayTime());
+ break;
+ }
+ case EnvironmentalReverb::decayHfRatioPm: {
+ erParam.set<EnvironmentalReverb::decayHfRatioPm>(
+ mContext->getEnvironmentalReverbDecayHfRatio());
+ break;
+ }
+ case EnvironmentalReverb::reflectionsLevelMb: {
+ erParam.set<EnvironmentalReverb::reflectionsLevelMb>(mContext->getReflectionsLevel());
+ break;
+ }
+ case EnvironmentalReverb::reflectionsDelayMs: {
+ erParam.set<EnvironmentalReverb::reflectionsDelayMs>(mContext->getReflectionsDelay());
+ break;
+ }
+ case EnvironmentalReverb::levelMb: {
+ erParam.set<EnvironmentalReverb::levelMb>(mContext->getEnvironmentalReverbLevel());
+ break;
+ }
+ case EnvironmentalReverb::delayMs: {
+ erParam.set<EnvironmentalReverb::delayMs>(mContext->getEnvironmentalReverbDelay());
+ break;
+ }
+ case EnvironmentalReverb::diffusionPm: {
+ erParam.set<EnvironmentalReverb::diffusionPm>(
+ mContext->getEnvironmentalReverbDiffusion());
+ break;
+ }
+ case EnvironmentalReverb::densityPm: {
+ erParam.set<EnvironmentalReverb::densityPm>(mContext->getEnvironmentalReverbDensity());
+ break;
+ }
+ case EnvironmentalReverb::bypass: {
+ erParam.set<EnvironmentalReverb::bypass>(mContext->getEnvironmentalReverbBypass());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::environmentalReverb>(erParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> EffectReverb::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ } else {
+ mContext = std::make_shared<ReverbContext>(1 /* statusFmqDepth */, common, mType);
+ }
+
+ return mContext;
+}
+
+std::shared_ptr<EffectContext> EffectReverb::getContext() {
+ return mContext;
+}
+
+RetCode EffectReverb::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+ndk::ScopedAStatus EffectReverb::commandImpl(CommandId command) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (command) {
+ case CommandId::START:
+ mContext->enable();
+ break;
+ case CommandId::STOP:
+ mContext->disable();
+ break;
+ case CommandId::RESET:
+ mContext->disable();
+ mContext->resetBuffer();
+ break;
+ default:
+ LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commandIdNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status EffectReverb::effectProcessImpl(float* in, float* out, int sampleToProcess) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!mContext, status, "nullContext");
+ return mContext->lvmProcess(in, out, sampleToProcess);
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h
new file mode 100644
index 0000000..d7d2bbd
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "effect-impl/EffectImpl.h"
+#include "ReverbContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectReverb final : public EffectImpl {
+ public:
+ explicit EffectReverb(const AudioUuid& uuid);
+ ~EffectReverb() override;
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ std::shared_ptr<EffectContext> getContext() override;
+ RetCode releaseContext() override;
+
+ IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+
+ std::string getEffectName() override { return *mEffectName; }
+
+ private:
+ std::shared_ptr<ReverbContext> mContext;
+ const Descriptor* mDescriptor;
+ const std::string* mEffectName;
+ lvm::ReverbEffectType mType;
+
+ IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
+
+ ndk::ScopedAStatus setParameterPresetReverb(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterPresetReverb(const PresetReverb::Id& id,
+ Parameter::Specific* specific);
+
+ ndk::ScopedAStatus setParameterEnvironmentalReverb(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterEnvironmentalReverb(const EnvironmentalReverb::Id& id,
+ Parameter::Specific* specific);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp
new file mode 100644
index 0000000..79e67f2
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp
@@ -0,0 +1,521 @@
+/*
+ * Copyright (C) 2023 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 <cstddef>
+
+#define LOG_TAG "ReverbContext"
+#include <android-base/logging.h>
+#include <Utils.h>
+
+#include "ReverbContext.h"
+#include "VectorArithmetic.h"
+#include "math.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+
+#define GOTO_IF_LVREV_ERROR(status, tag, log) \
+ do { \
+ LVREV_ReturnStatus_en temp = (status); \
+ if (temp != LVREV_SUCCESS) { \
+ LOG(ERROR) << __func__ << " return status: " << temp << " " << (log); \
+ goto tag; \
+ } \
+ } while (0)
+
+RetCode ReverbContext::init() {
+ if (isPreset()) {
+ // force reloading preset at first call to process()
+ mPreset = PresetReverb::Presets::NONE;
+ mNextPreset = PresetReverb::Presets::NONE;
+ }
+
+ mVolume.left = kUnitVolume;
+ mVolume.right = kUnitVolume;
+ mPrevVolume.left = kUnitVolume;
+ mPrevVolume.right = kUnitVolume;
+ volumeMode = VOLUME_FLAT;
+
+ mSamplesToExitCount = kDefaultDecayTime * mCommon.input.base.sampleRate / 1000;
+
+ /* Saved strength is used to return the exact strength that was used in the set to the get
+ * because we map the original strength range of 0:1000 to 1:15, and this will avoid
+ * quantisation like effect when returning
+ */
+ mRoomLevel = lvm::kMinLevel;
+ mRoomHfLevel = 0;
+ mEnabled = LVM_FALSE;
+ mDecayTime = kDefaultDecayTime;
+ mDecayHfRatio = kDefaultDamping * 20;
+ mDensity = kDefaultRoomSize * 10;
+ mDiffusion = kDefaultDensity * 10;
+ mLevel = lvm::kMinLevel;
+
+ // allocate lvm reverb instance
+ LVREV_ReturnStatus_en status = LVREV_SUCCESS;
+ {
+ std::lock_guard lg(mMutex);
+ LVREV_InstanceParams_st params = {
+ .MaxBlockSize = lvm::kMaxCallSize,
+ // Max format, could be mono during process
+ .SourceFormat = LVM_STEREO,
+ .NumDelays = LVREV_DELAYLINES_4,
+ };
+ /* Init sets the instance handle */
+ status = LVREV_GetInstanceHandle(&mInstance, ¶ms);
+ GOTO_IF_LVREV_ERROR(status, deinit, "LVREV_GetInstanceHandleFailed");
+
+ // set control
+ LVREV_ControlParams_st controlParams;
+ initControlParameter(controlParams);
+ status = LVREV_SetControlParameters(mInstance, &controlParams);
+ GOTO_IF_LVREV_ERROR(status, deinit, "LVREV_SetControlParametersFailed");
+ }
+
+ return RetCode::SUCCESS;
+
+deinit:
+ deInit();
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+}
+
+void ReverbContext::deInit() {
+ std::lock_guard lg(mMutex);
+ if (mInstance) {
+ LVREV_FreeInstance(mInstance);
+ mInstance = nullptr;
+ }
+}
+
+RetCode ReverbContext::enable() {
+ if (mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
+ mEnabled = true;
+ mSamplesToExitCount = (mDecayTime * mCommon.input.base.sampleRate) / 1000;
+ // force no volume ramp for first buffer processed after enabling the effect
+ volumeMode = VOLUME_FLAT;
+ return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::disable() {
+ if (!mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
+ mEnabled = false;
+ return RetCode::SUCCESS;
+}
+
+bool ReverbContext::isAuxiliary() {
+ return (mType == lvm::ReverbEffectType::AUX_ENV || mType == lvm::ReverbEffectType::AUX_PRESET);
+}
+
+bool ReverbContext::isPreset() {
+ return (mType == lvm::ReverbEffectType::AUX_PRESET ||
+ mType == lvm::ReverbEffectType::INSERT_PRESET);
+}
+
+RetCode ReverbContext::setVolumeStereo(const Parameter::VolumeStereo& volume) {
+ if (volumeMode == VOLUME_OFF) {
+ // force no volume ramp for first buffer processed after getting volume control
+ volumeMode = VOLUME_FLAT;
+ }
+ mVolumeStereo = volume;
+ return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setPresetReverbPreset(const PresetReverb::Presets& preset) {
+ mNextPreset = preset;
+ return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbRoomLevel(int roomLevel) {
+ // Update Control Parameter
+ LVREV_ControlParams_st params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ // Sum of room and reverb level controls
+ // needs to subtract max levels for both room level and reverb level
+ int combinedLevel = (roomLevel + mLevel) - lvm::kMaxReverbLevel;
+ params.Level = convertLevel(combinedLevel);
+
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ }
+ mRoomLevel = roomLevel;
+ return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbRoomHfLevel(int roomHfLevel) {
+ // Update Control Parameter
+ LVREV_ControlParams_st params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ params.LPF = convertHfLevel(roomHfLevel);
+
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ }
+ mRoomHfLevel = roomHfLevel;
+ return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbDecayTime(int decayTime) {
+ int time = decayTime;
+ if (time > lvm::kMaxT60) {
+ time = lvm::kMaxT60;
+ }
+
+ // Update Control Parameter
+ LVREV_ControlParams_st params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ params.T60 = (LVM_UINT16)time;
+ mSamplesToExitCount = (params.T60 * mCommon.input.base.sampleRate) / 1000;
+
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ }
+ mDecayTime = time;
+ return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbDecayHfRatio(int decayHfRatio) {
+ // Update Control Parameter
+ LVREV_ControlParams_st params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ params.Damping = (LVM_INT16)(decayHfRatio / 20);
+
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ }
+ mDecayHfRatio = decayHfRatio;
+ return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbLevel(int level) {
+ // Update Control Parameter
+ LVREV_ControlParams_st params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ // Sum of room and reverb level controls
+ // needs to subtract max levels for both room level and level
+ int combinedLevel = (level + mRoomLevel) - lvm::kMaxReverbLevel;
+ params.Level = convertLevel(combinedLevel);
+
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ }
+ mLevel = level;
+ return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbDelay(int delay) {
+ mDelay = delay;
+ return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbDiffusion(int diffusion) {
+ // Update Control Parameter
+ LVREV_ControlParams_st params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ params.Density = (LVM_INT16)(diffusion / 10);
+
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ }
+ mDiffusion = diffusion;
+ return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbDensity(int density) {
+ // Update Control Parameter
+ LVREV_ControlParams_st params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ params.RoomSize = (LVM_INT16)(((density * 99) / 1000) + 1);
+
+ RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ }
+ mDensity = density;
+ return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbBypass(bool bypass) {
+ mBypass = bypass;
+ return RetCode::SUCCESS;
+}
+
+void ReverbContext::loadPreset() {
+ // TODO: add delay when early reflections are implemented
+ mPreset = mNextPreset;
+
+ if (mPreset != PresetReverb::Presets::NONE) {
+ const t_reverb_settings preset = mReverbPresets[mPreset];
+ setEnvironmentalReverbRoomLevel(preset.roomLevel);
+ setEnvironmentalReverbRoomHfLevel(preset.roomHFLevel);
+ setEnvironmentalReverbDecayTime(preset.decayTime);
+ setEnvironmentalReverbDecayHfRatio(preset.decayHFRatio);
+ setEnvironmentalReverbLevel(preset.reverbLevel);
+ // reverbDelay
+ setEnvironmentalReverbDiffusion(preset.diffusion);
+ setEnvironmentalReverbDensity(preset.density);
+ }
+}
+
+void ReverbContext::initControlParameter(LVREV_ControlParams_st& params) {
+ /* Set the initial process parameters */
+ /* General parameters */
+ params.OperatingMode = LVM_MODE_ON;
+ params.SampleRate = LVM_FS_44100;
+ params.SourceFormat = (::aidl::android::hardware::audio::common::getChannelCount(
+ mCommon.input.base.channelMask) == 1
+ ? LVM_MONO
+ : LVM_STEREO);
+
+ if (!isAuxiliary() && params.SourceFormat == LVM_MONO) {
+ params.SourceFormat = LVM_STEREO;
+ }
+
+ /* Reverb parameters */
+ params.Level = kDefaultLevel;
+ params.LPF = kDefaultLPF;
+ params.HPF = kDefaultHPF;
+ params.T60 = kDefaultDecayTime;
+ params.Density = kDefaultDensity;
+ params.Damping = kDefaultDamping;
+ params.RoomSize = kDefaultRoomSize;
+}
+
+/*
+ * Convert level from OpenSL ES format to LVM format
+ *
+ * @param level : level to be applied
+ */
+
+int ReverbContext::convertLevel(int level) {
+ for (int i = 0; i < kLevelMapping.size(); i++) {
+ if (level <= kLevelMapping[i]) {
+ return i;
+ }
+ }
+ return kDefaultLevel;
+}
+
+/*
+ * Convert level HF from OpenSL ES format to LVM format
+ *
+ * @param hfLevel : level to be applied
+ */
+
+int16_t ReverbContext::convertHfLevel(int hfLevel) {
+ for (auto lpfPair : kLPFMapping) {
+ if (hfLevel <= lpfPair.roomHf) {
+ return lpfPair.lpf;
+ }
+ }
+ return kDefaultLPF;
+}
+
+IEffect::Status ReverbContext::lvmProcess(float* in, float* out, int samples) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!in, status, "nullInput");
+ RETURN_VALUE_IF(!out, status, "nullOutput");
+ status = {EX_ILLEGAL_STATE, 0, 0};
+ int64_t inputFrameCount = getCommon().input.frameCount;
+ int64_t outputFrameCount = getCommon().output.frameCount;
+ RETURN_VALUE_IF(inputFrameCount != outputFrameCount, status, "FrameCountMismatch");
+ RETURN_VALUE_IF(0 == getInputFrameSize(), status, "zeroFrameSize");
+
+ LOG(DEBUG) << __func__ << " start processing";
+ std::lock_guard lg(mMutex);
+
+ int channels = ::aidl::android::hardware::audio::common::getChannelCount(
+ mCommon.input.base.channelMask);
+ int outChannels = ::aidl::android::hardware::audio::common::getChannelCount(
+ mCommon.output.base.channelMask);
+ int frameCount = mCommon.input.frameCount;
+
+ // Reverb only effects the stereo channels in multichannel source.
+ if (channels < 1 || channels > LVM_MAX_CHANNELS) {
+ LOG(ERROR) << __func__ << " process invalid PCM channels " << channels;
+ return status;
+ }
+
+ std::vector<float> inFrames(samples);
+ std::vector<float> outFrames(frameCount * FCC_2);
+
+ if (isPreset() && mNextPreset != mPreset) {
+ loadPreset();
+ }
+
+ if (isAuxiliary()) {
+ inFrames.assign(in, in + samples);
+ } else {
+ // mono input is duplicated
+ if (channels >= FCC_2) {
+ for (int i = 0; i < frameCount; i++) {
+ inFrames[FCC_2 * i] = in[channels * i] * kSendLevel;
+ inFrames[FCC_2 * i + 1] = in[channels * i + 1] * kSendLevel;
+ }
+ } else {
+ for (int i = 0; i < frameCount; i++) {
+ inFrames[FCC_2 * i] = inFrames[FCC_2 * i + 1] = in[i] * kSendLevel;
+ }
+ }
+ }
+
+ if (isPreset() && mPreset == PresetReverb::Presets::NONE) {
+ std::fill(outFrames.begin(), outFrames.end(), 0); // always stereo here
+ } else {
+ if (!mEnabled && mSamplesToExitCount > 0) {
+ std::fill(outFrames.begin(), outFrames.end(), 0);
+ LOG(VERBOSE) << "Zeroing " << channels << " samples per frame at the end of call ";
+ }
+
+ /* Process the samples, producing a stereo output */
+ LVREV_ReturnStatus_en lvrevStatus =
+ LVREV_Process(mInstance, /* Instance handle */
+ inFrames.data(), /* Input buffer */
+ outFrames.data(), /* Output buffer */
+ frameCount); /* Number of samples to read */
+ if (lvrevStatus != LVREV_SUCCESS) {
+ LOG(ERROR) << __func__ << lvrevStatus;
+ return {EX_UNSUPPORTED_OPERATION, 0, 0};
+ }
+ }
+ // Convert to 16 bits
+ if (isAuxiliary()) {
+ // nothing to do here
+ } else {
+ if (channels >= FCC_2) {
+ for (int i = 0; i < frameCount; i++) {
+ // Mix with dry input
+ outFrames[FCC_2 * i] += in[channels * i];
+ outFrames[FCC_2 * i + 1] += in[channels * i + 1];
+ }
+ } else {
+ for (int i = 0; i < frameCount; i++) {
+ // Mix with dry input
+ outFrames[FCC_2 * i] += in[i];
+ outFrames[FCC_2 * i + 1] += in[i];
+ }
+ }
+
+ // apply volume with ramp if needed
+ if (mVolume != mPrevVolume && volumeMode == VOLUME_RAMP) {
+ float vl = mPrevVolume.left;
+ float incl = (mVolume.left - vl) / frameCount;
+ float vr = mPrevVolume.right;
+ float incr = (mVolume.right - vr) / frameCount;
+
+ for (int i = 0; i < frameCount; i++) {
+ outFrames[FCC_2 * i] *= vl;
+ outFrames[FCC_2 * i + 1] *= vr;
+
+ vl += incl;
+ vr += incr;
+ }
+ mPrevVolume = mVolume;
+ } else if (volumeMode != VOLUME_OFF) {
+ if (mVolume.left != kUnitVolume || mVolume.right != kUnitVolume) {
+ for (int i = 0; i < frameCount; i++) {
+ outFrames[FCC_2 * i] *= mVolume.left;
+ outFrames[FCC_2 * i + 1] *= mVolume.right;
+ }
+ }
+ mPrevVolume = mVolume;
+ volumeMode = VOLUME_RAMP;
+ }
+ }
+
+ bool accumulate = false;
+ if (outChannels > 2) {
+ // Accumulate if required
+ if (accumulate) {
+ for (int i = 0; i < frameCount; i++) {
+ out[outChannels * i] += outFrames[FCC_2 * i];
+ out[outChannels * i + 1] += outFrames[FCC_2 * i + 1];
+ }
+ } else {
+ for (int i = 0; i < frameCount; i++) {
+ out[outChannels * i] = outFrames[FCC_2 * i];
+ out[outChannels * i + 1] = outFrames[FCC_2 * i + 1];
+ }
+ }
+ if (!isAuxiliary()) {
+ for (int i = 0; i < frameCount; i++) {
+ // channels and outChannels are expected to be same.
+ for (int j = FCC_2; j < outChannels; j++) {
+ out[outChannels * i + j] = in[outChannels * i + j];
+ }
+ }
+ }
+ } else {
+ if (accumulate) {
+ if (outChannels == FCC_1) {
+ for (int i = 0; i < frameCount; i++) {
+ out[i] += ((outFrames[i * FCC_2] + outFrames[i * FCC_2 + 1]) * 0.5f);
+ }
+ } else {
+ for (int i = 0; i < frameCount * FCC_2; i++) {
+ out[i] += outFrames[i];
+ }
+ }
+ } else {
+ if (outChannels == FCC_1) {
+ From2iToMono_Float(outFrames.data(), out, frameCount);
+ } else {
+ for (int i = 0; i < frameCount * FCC_2; i++) {
+ out[i] = outFrames[i];
+ }
+ }
+ }
+ }
+
+ LOG(DEBUG) << __func__ << " done processing";
+
+ if (!mEnabled && mSamplesToExitCount > 0) {
+ // signed - unsigned will trigger integer overflow if result becomes negative.
+ mSamplesToExitCount -= samples;
+ }
+
+ return {STATUS_OK, samples, outChannels * frameCount};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
new file mode 100644
index 0000000..9bb0b1a
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2023 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 <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+#include <unordered_map>
+
+#include "ReverbTypes.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+enum VolumeMode {
+ VOLUME_OFF,
+ VOLUME_FLAT,
+ VOLUME_RAMP,
+};
+
+struct LPFPair {
+ int roomHf;
+ int lpf;
+};
+
+class ReverbContext final : public EffectContext {
+ public:
+ ReverbContext(int statusDepth, const Parameter::Common& common,
+ const lvm::ReverbEffectType& type)
+ : EffectContext(statusDepth, common), mType(type) {
+ LOG(DEBUG) << __func__ << type;
+ init();
+ }
+ ~ReverbContext() override {
+ LOG(DEBUG) << __func__;
+ deInit();
+ }
+
+ RetCode init();
+ void deInit();
+
+ RetCode enable();
+ RetCode disable();
+
+ bool isAuxiliary();
+ bool isPreset();
+
+ RetCode setPresetReverbPreset(const PresetReverb::Presets& preset);
+ PresetReverb::Presets getPresetReverbPreset() const { return mNextPreset; }
+
+ RetCode setEnvironmentalReverbRoomLevel(int roomLevel);
+ int getEnvironmentalReverbRoomLevel() const { return mRoomLevel; }
+ RetCode setEnvironmentalReverbRoomHfLevel(int roomHfLevel);
+ int getEnvironmentalReverbRoomHfLevel() const { return mRoomHfLevel; }
+ RetCode setEnvironmentalReverbDecayTime(int decayTime);
+ int getEnvironmentalReverbDecayTime() const { return mDecayTime; }
+ RetCode setEnvironmentalReverbDecayHfRatio(int decayHfRatio);
+ int getEnvironmentalReverbDecayHfRatio() const { return mDecayHfRatio; }
+ RetCode setEnvironmentalReverbLevel(int level);
+ int getEnvironmentalReverbLevel() const { return mLevel; }
+ RetCode setEnvironmentalReverbDelay(int delay);
+ int getEnvironmentalReverbDelay() const { return mDelay; }
+ RetCode setEnvironmentalReverbDiffusion(int diffusion);
+ int getEnvironmentalReverbDiffusion() const { return mDiffusion; }
+ RetCode setEnvironmentalReverbDensity(int density);
+ int getEnvironmentalReverbDensity() const { return mDensity; }
+ RetCode setEnvironmentalReverbBypass(bool bypass);
+ bool getEnvironmentalReverbBypass() const { return mBypass; }
+
+ RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
+ Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
+
+ RetCode setReflectionsDelay(int delay) {
+ mReflectionsDelayMs = delay;
+ return RetCode::SUCCESS;
+ }
+ bool getReflectionsDelay() const { return mReflectionsDelayMs; }
+
+ RetCode setReflectionsLevel(int level) {
+ mReflectionsLevelMb = level;
+ return RetCode::SUCCESS;
+ }
+ bool getReflectionsLevel() const { return mReflectionsLevelMb; }
+
+ IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+ private:
+ static constexpr inline float kUnitVolume = 1;
+ static constexpr inline float kSendLevel = 0.75f;
+ static constexpr inline int kDefaultLevel = 0;
+ static constexpr inline int kDefaultLPF = 23999; /* Default low pass filter, in Hz */
+ static constexpr inline int kDefaultHPF = 50; /* Default high pass filter, in Hz */
+ static constexpr inline int kDefaultDecayTime = 1490; /* Default Decay time, in ms */
+ static constexpr inline int kDefaultDensity = 100; /* Default Echo density */
+ static constexpr inline int kDefaultDamping = 21;
+ static constexpr inline int kDefaultRoomSize = 100;
+
+ static inline const std::vector<LPFPair> kLPFMapping = {
+ // Limit range to 50 for LVREV parameter range
+ {-10000, 50}, {-5000, 50}, {-4000, 50}, {-3000, 158}, {-2000, 502}, {-1000, 1666},
+ {-900, 1897}, {-800, 2169}, {-700, 2496}, {-600, 2895}, {-500, 3400}, {-400, 4066},
+ {-300, 5011}, {-200, 6537}, {-100, 9826}, {-99, 9881}, {-98, 9937}, {-97, 9994},
+ {-96, 10052}, {-95, 10111}, {-94, 10171}, {-93, 10231}, {-92, 10293}, {-91, 10356},
+ {-90, 10419}, {-89, 10484}, {-88, 10549}, {-87, 10616}, {-86, 10684}, {-85, 10753},
+ {-84, 10823}, {-83, 10895}, {-82, 10968}, {-81, 11042}, {-80, 11117}, {-79, 11194},
+ {-78, 11272}, {-77, 11352}, {-76, 11433}, {-75, 11516}, {-74, 11600}, {-73, 11686},
+ {-72, 11774}, {-71, 11864}, {-70, 11955}, {-69, 12049}, {-68, 12144}, {-67, 12242},
+ {-66, 12341}, {-65, 12443}, {-64, 12548}, {-63, 12654}, {-62, 12763}, {-61, 12875},
+ {-60, 12990}, {-59, 13107}, {-58, 13227}, {-57, 13351}, {-56, 13477}, {-55, 13607},
+ {-54, 13741}, {-53, 13878}, {-52, 14019}, {-51, 14164}, {-50, 14313}, {-49, 14467},
+ {-48, 14626}, {-47, 14789}, {-46, 14958}, {-45, 15132}, {-44, 15312}, {-43, 15498},
+ {-42, 15691}, {-41, 15890}, {-40, 16097}, {-39, 16311}, {-38, 16534}, {-37, 16766},
+ {-36, 17007}, {-35, 17259}, {-34, 17521}, {-33, 17795}, {-32, 18081}, {-31, 18381},
+ {-30, 18696}, {-29, 19027}, {-28, 19375}, {-27, 19742}, {-26, 20129}, {-25, 20540},
+ {-24, 20976}, {-23, 21439}, {-22, 21934}, {-21, 22463}, {-20, 23031}, {-19, 23643},
+ {-18, 23999}};
+
+ static inline const std::vector<int> kLevelMapping = {
+ -12000, -4000, -3398, -3046, -2796, -2603, -2444, -2310, -2194, -2092, -2000, -1918,
+ -1842, -1773, -1708, -1648, -1592, -1540, -1490, -1443, -1398, -1356, -1316, -1277,
+ -1240, -1205, -1171, -1138, -1106, -1076, -1046, -1018, -990, -963, -938, -912,
+ -888, -864, -841, -818, -796, -775, -754, -734, -714, -694, -675, -656,
+ -638, -620, -603, -585, -568, -552, -536, -520, -504, -489, -474, -459,
+ -444, -430, -416, -402, -388, -375, -361, -348, -335, -323, -310, -298,
+ -286, -274, -262, -250, -239, -228, -216, -205, -194, -184, -173, -162,
+ -152, -142, -132, -121, -112, -102, -92, -82, -73, -64, -54, -45,
+ -36, -27, -18, -9, 0};
+
+ static inline std::unordered_map<PresetReverb::Presets, t_reverb_settings> mReverbPresets = {
+ {PresetReverb::Presets::NONE, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+ {PresetReverb::Presets::SMALLROOM,
+ {-400, -600, 1100, 830, -400, 5, 500, 10, 1000, 1000}},
+ {PresetReverb::Presets::MEDIUMROOM,
+ {-400, -600, 1300, 830, -1000, 20, -200, 20, 1000, 1000}},
+ {PresetReverb::Presets::LARGEROOM,
+ {-400, -600, 1500, 830, -1600, 5, -1000, 40, 1000, 1000}},
+ {PresetReverb::Presets::MEDIUMHALL,
+ {-400, -600, 1800, 700, -1300, 15, -800, 30, 1000, 1000}},
+ {PresetReverb::Presets::LARGEHALL,
+ {-400, -600, 1800, 700, -2000, 30, -1400, 60, 1000, 1000}},
+ {PresetReverb::Presets::PLATE, {-400, -200, 1300, 900, 0, 2, 0, 10, 1000, 750}}};
+
+ std::mutex mMutex;
+ const lvm::ReverbEffectType mType;
+ bool mEnabled = false;
+ LVREV_Handle_t mInstance GUARDED_BY(mMutex);
+
+ int mRoomLevel = 0;
+ int mRoomHfLevel = 0;
+ int mDecayTime = 0;
+ int mDecayHfRatio = 0;
+ int mLevel = 0;
+ int mDelay = 0;
+ int mDiffusion = 0;
+ int mDensity = 0;
+ bool mBypass = 0;
+ int mReflectionsLevelMb = 0;
+ int mReflectionsDelayMs = 0;
+
+ PresetReverb::Presets mPreset;
+ PresetReverb::Presets mNextPreset;
+
+ int mSamplesToExitCount;
+
+ Parameter::VolumeStereo mVolume;
+ Parameter::VolumeStereo mPrevVolume;
+ VolumeMode volumeMode;
+
+ void initControlParameter(LVREV_ControlParams_st& params);
+ int16_t convertHfLevel(int hfLevel);
+ int convertLevel(int level);
+ void loadPreset();
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h
new file mode 100644
index 0000000..37f9287
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <android/binder_enums.h>
+#include <audio_effects/effect_environmentalreverb.h>
+#include <audio_effects/effect_presetreverb.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "effect-impl/EffectTypes.h"
+// from Reverb/lib
+#include "LVREV.h"
+
+namespace aidl::android::hardware::audio::effect {
+namespace lvm {
+
+constexpr inline int kMaxCallSize = 256;
+constexpr inline int kMinLevel = -6000;
+constexpr inline int kMaxT60 = 7000; /* Maximum decay time */
+constexpr inline int kMaxReverbLevel = 2000;
+constexpr inline int kMaxFrameSize = 2560;
+constexpr inline int kCpuLoadARM9E = 470; // Expressed in 0.1 MIPS
+constexpr inline int kMemUsage = (71 + (kMaxFrameSize >> 7)); // Expressed in kB
+
+static const std::vector<Range::EnvironmentalReverbRange> kEnvReverbRanges = {
+ MAKE_RANGE(EnvironmentalReverb, roomLevelMb, lvm::kMinLevel, 0),
+ MAKE_RANGE(EnvironmentalReverb, roomHfLevelMb, -4000, 0),
+ MAKE_RANGE(EnvironmentalReverb, decayTimeMs, 0, lvm::kMaxT60),
+ MAKE_RANGE(EnvironmentalReverb, decayHfRatioPm, 100, 2000),
+ MAKE_RANGE(EnvironmentalReverb, levelMb, lvm::kMinLevel, 0),
+ MAKE_RANGE(EnvironmentalReverb, delayMs, 0, 65),
+ MAKE_RANGE(EnvironmentalReverb, diffusionPm, 0, 1000),
+ MAKE_RANGE(EnvironmentalReverb, densityPm, 0, 1000)};
+static const Capability kEnvReverbCap = {
+ .range = Range::make<Range::environmentalReverb>(kEnvReverbRanges)};
+
+// NXP SW auxiliary environmental reverb
+static const std::string kAuxEnvReverbEffectName = "Auxiliary Environmental Reverb";
+static const Descriptor kAuxEnvReverbDesc = {
+ .common = {.id = {.type = getEffectTypeUuidEnvReverb(),
+ .uuid = getEffectImplUuidAuxEnvReverb(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::AUXILIARY},
+ .cpuLoad = kCpuLoadARM9E,
+ .memoryUsage = kMemUsage,
+ .name = kAuxEnvReverbEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = kEnvReverbCap};
+
+// NXP SW insert environmental reverb
+static const std::string kInsertEnvReverbEffectName = "Insert Environmental Reverb";
+static const Descriptor kInsertEnvReverbDesc = {
+ .common = {.id = {.type = getEffectTypeUuidEnvReverb(),
+ .uuid = getEffectImplUuidInsertEnvReverb(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .cpuLoad = kCpuLoadARM9E,
+ .memoryUsage = kMemUsage,
+ .name = kInsertEnvReverbEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = kEnvReverbCap};
+
+static const std::vector<PresetReverb::Presets> kSupportedPresets{
+ ndk::enum_range<PresetReverb::Presets>().begin(),
+ ndk::enum_range<PresetReverb::Presets>().end()};
+static const std::vector<Range::PresetReverbRange> kPresetReverbRanges = {
+ MAKE_RANGE(PresetReverb, supportedPresets, kSupportedPresets, kSupportedPresets)};
+static const Capability kPresetReverbCap = {
+ .range = Range::make<Range::presetReverb>(kPresetReverbRanges)};
+
+// NXP SW auxiliary preset reverb
+static const std::string kAuxPresetReverbEffectName = "Auxiliary Preset Reverb";
+static const Descriptor kAuxPresetReverbDesc = {
+ .common = {.id = {.type = getEffectTypeUuidPresetReverb(),
+ .uuid = getEffectImplUuidAuxPresetReverb(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::AUXILIARY},
+ .cpuLoad = kCpuLoadARM9E,
+ .memoryUsage = kMemUsage,
+ .name = kAuxPresetReverbEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = kPresetReverbCap};
+
+// NXP SW insert preset reverb
+static const std::string kInsertPresetReverbEffectName = "Insert Preset Reverb";
+static const Descriptor kInsertPresetReverbDesc = {
+ .common = {.id = {.type = getEffectTypeUuidPresetReverb(),
+ .uuid = getEffectImplUuidInsertPresetReverb(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .cpuLoad = kCpuLoadARM9E,
+ .memoryUsage = kMemUsage,
+ .name = kInsertPresetReverbEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = kPresetReverbCap};
+
+enum class ReverbEffectType {
+ AUX_ENV,
+ INSERT_ENV,
+ AUX_PRESET,
+ INSERT_PRESET,
+};
+
+inline std::ostream& operator<<(std::ostream& out, const ReverbEffectType& type) {
+ switch (type) {
+ case ReverbEffectType::AUX_ENV:
+ return out << kAuxEnvReverbEffectName;
+ case ReverbEffectType::INSERT_ENV:
+ return out << kInsertEnvReverbEffectName;
+ case ReverbEffectType::AUX_PRESET:
+ return out << kAuxPresetReverbEffectName;
+ case ReverbEffectType::INSERT_PRESET:
+ return out << kInsertPresetReverbEffectName;
+ }
+ return out << "EnumReverbEffectTypeError";
+}
+
+inline std::ostream& operator<<(std::ostream& out, const LVREV_ReturnStatus_en& status) {
+ switch (status) {
+ case LVREV_SUCCESS:
+ return out << "LVREV_SUCCESS";
+ case LVREV_NULLADDRESS:
+ return out << "LVREV_NULLADDRESS";
+ case LVREV_OUTOFRANGE:
+ return out << "LVREV_OUTOFRANGE";
+ case LVREV_INVALIDNUMSAMPLES:
+ return out << "LVREV_INVALIDNUMSAMPLES";
+ case LVREV_RETURNSTATUS_DUMMY:
+ return out << "LVREV_RETURNSTATUS_DUMMY";
+ }
+ return out << "EnumLvrevRetStatusError";
+}
+
+} // namespace lvm
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/Android.bp b/media/libeffects/preprocessing/Android.bp
index c6e036a..d018c47 100644
--- a/media/libeffects/preprocessing/Android.bp
+++ b/media/libeffects/preprocessing/Android.bp
@@ -58,3 +58,39 @@
"libwebrtc_absl_headers",
],
}
+
+cc_library_shared {
+ name: "libpreprocessingaidl",
+ srcs: [
+ "aidl/PreProcessingContext.cpp",
+ "aidl/EffectPreProcessing.cpp",
+ ":effectCommonFile",
+ ],
+ defaults: [
+ "aidlaudioservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ local_include_dirs: ["aidl"],
+ shared_libs: [
+ "liblog",
+ "libutils",
+ "libaudioutils",
+ ],
+ static_libs: [
+ "webrtc_audio_processing",
+ ],
+ header_libs: [
+ "libwebrtc_absl_headers",
+ "libaudioeffects",
+ "libhardware_headers",
+ ],
+ cflags: [
+ "-Wthread-safety",
+ "-Wno-unused-parameter",
+ ],
+ relative_install_path: "soundfx",
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 61a2bf5..59f1fc3 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -102,7 +102,8 @@
uint32_t state; // current state (enum preproc_session_state)
int id; // audio session ID
int io; // handle of input stream this session is on
- webrtc::AudioProcessing* apm; // handle on webRTC audio processing module (APM)
+ rtc::scoped_refptr<webrtc::AudioProcessing>
+ apm; // handle on webRTC audio processing module (APM)
// Audio Processing module builder
webrtc::AudioProcessingBuilder ap_builder;
// frameCount represents the size of the buffers used for processing, and must represent 10ms.
@@ -260,9 +261,6 @@
ALOGV("Agc2Init");
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller2.fixed_digital.gain_db = 0.f;
- effect->session->config.gain_controller2.adaptive_digital.level_estimator =
- effect->session->config.gain_controller2.kRms;
- effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db = 2.f;
effect->session->apm->ApplyConfig(effect->session->config);
return 0;
}
@@ -332,24 +330,19 @@
ALOGV("Agc2GetParameter() target level %f dB", *(float*)pValue);
break;
case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
- *(uint32_t*)pValue = (uint32_t)(
- effect->session->config.gain_controller2.adaptive_digital.level_estimator);
- ALOGV("Agc2GetParameter() level estimator %d",
- *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
+ // WebRTC only supports RMS level estimator now
+ *(uint32_t*)pValue = (uint32_t)(0);
+ ALOGV("Agc2GetParameter() level estimator RMS");
break;
case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
- *(float*)pValue = (float)(effect->session->config.gain_controller2.adaptive_digital
- .extra_saturation_margin_db);
+ *(float*)pValue = (float)(2.0);
ALOGV("Agc2GetParameter() extra saturation margin %f dB", *(float*)pValue);
break;
case AGC2_PARAM_PROPERTIES:
pProperties->fixedDigitalGain =
(float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
- pProperties->level_estimator = (uint32_t)(
- effect->session->config.gain_controller2.adaptive_digital.level_estimator);
- pProperties->extraSaturationMargin =
- (float)(effect->session->config.gain_controller2.adaptive_digital
- .extra_saturation_margin_db);
+ pProperties->level_estimator = 0;
+ pProperties->extraSaturationMargin = 2.0;
break;
default:
ALOGW("Agc2GetParameter() unknown param %d", param);
@@ -438,16 +431,19 @@
effect->session->config.gain_controller2.fixed_digital.gain_db = valueFloat;
break;
case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
- ALOGV("Agc2SetParameter() level estimator %d",
- *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
- effect->session->config.gain_controller2.adaptive_digital.level_estimator =
- (*(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
+ ALOGV("Agc2SetParameter() level estimator %d", *(uint32_t*)pValue);
+ if (*(uint32_t*)pValue != 0) {
+ // only RMS is supported
+ status = -EINVAL;
+ }
break;
case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
valueFloat = (float)(*(int32_t*)pValue);
ALOGV("Agc2SetParameter() extra saturation margin %f dB", valueFloat);
- effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
- valueFloat;
+ if (valueFloat != 2.0) {
+ // extra_staturation_margin_db is no longer configurable in webrtc
+ status = -EINVAL;
+ }
break;
case AGC2_PARAM_PROPERTIES:
ALOGV("Agc2SetParameter() properties gain %f, level %d margin %f",
@@ -455,11 +451,9 @@
pProperties->extraSaturationMargin);
effect->session->config.gain_controller2.fixed_digital.gain_db =
pProperties->fixedDigitalGain;
- effect->session->config.gain_controller2.adaptive_digital.level_estimator =
- (webrtc::AudioProcessing::Config::GainController2::LevelEstimator)
- pProperties->level_estimator;
- effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
- pProperties->extraSaturationMargin;
+ if (pProperties->level_estimator != 0 || pProperties->extraSaturationMargin != 2.0) {
+ status = -EINVAL;
+ }
break;
default:
ALOGW("Agc2SetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
@@ -879,8 +873,8 @@
error:
if (session->createdMsk == 0) {
- delete session->apm;
- session->apm = NULL;
+ // Scoped_refptr will handle reference counting here
+ session->apm = nullptr;
}
return status;
}
@@ -889,8 +883,8 @@
ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
session->createdMsk &= ~(1 << fx->procId);
if (session->createdMsk == 0) {
- delete session->apm;
- session->apm = NULL;
+ // Scoped_refptr will handle reference counting here
+ session->apm = nullptr;
session->id = 0;
}
diff --git a/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp b/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp
new file mode 100644
index 0000000..e8ae8b3
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectPreProcessing"
+#include <algorithm>
+#include <unordered_set>
+
+#include <Utils.h>
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "EffectPreProcessing.h"
+
+using aidl::android::hardware::audio::effect::getEffectImplUuidAcousticEchoCancelerSw;
+using aidl::android::hardware::audio::effect::getEffectImplUuidAutomaticGainControlV1Sw;
+using aidl::android::hardware::audio::effect::getEffectImplUuidAutomaticGainControlV2Sw;
+using aidl::android::hardware::audio::effect::getEffectImplUuidNoiseSuppressionSw;
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectPreProcessing;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+bool isPreProcessingUuidSupported(const AudioUuid& uuid) {
+ return uuid == getEffectImplUuidAcousticEchoCancelerSw() ||
+ uuid == getEffectImplUuidAutomaticGainControlV1Sw() ||
+ uuid == getEffectImplUuidAutomaticGainControlV2Sw() ||
+ uuid == getEffectImplUuidNoiseSuppressionSw();
+}
+
+extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!uuid || !isPreProcessingUuidSupported(*uuid)) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<EffectPreProcessing>(*uuid);
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || !isPreProcessingUuidSupported(*in_impl_uuid)) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (*in_impl_uuid == getEffectImplUuidAcousticEchoCancelerSw()) {
+ *_aidl_return = aidl::android::hardware::audio::effect::kAcousticEchoCancelerDesc;
+ } else if (*in_impl_uuid == getEffectImplUuidAutomaticGainControlV1Sw()) {
+ *_aidl_return = aidl::android::hardware::audio::effect::kAutomaticGainControlV1Desc;
+ } else if (*in_impl_uuid == getEffectImplUuidAutomaticGainControlV2Sw()) {
+ *_aidl_return = aidl::android::hardware::audio::effect::kAutomaticGainControlV2Desc;
+ } else if (*in_impl_uuid == getEffectImplUuidNoiseSuppressionSw()) {
+ *_aidl_return = aidl::android::hardware::audio::effect::kNoiseSuppressionDesc;
+ }
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+EffectPreProcessing::EffectPreProcessing(const AudioUuid& uuid) {
+ LOG(DEBUG) << __func__ << uuid.toString();
+ if (uuid == getEffectImplUuidAcousticEchoCancelerSw()) {
+ mType = PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION;
+ mDescriptor = &kAcousticEchoCancelerDesc;
+ mEffectName = &kAcousticEchoCancelerEffectName;
+ } else if (uuid == getEffectImplUuidAutomaticGainControlV1Sw()) {
+ mType = PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1;
+ mDescriptor = &kAutomaticGainControlV1Desc;
+ mEffectName = &kAutomaticGainControlV1EffectName;
+ } else if (uuid == getEffectImplUuidAutomaticGainControlV2Sw()) {
+ mType = PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2;
+ mDescriptor = &kAutomaticGainControlV2Desc;
+ mEffectName = &kAutomaticGainControlV2EffectName;
+ } else if (uuid == getEffectImplUuidNoiseSuppressionSw()) {
+ mType = PreProcessingEffectType::NOISE_SUPPRESSION;
+ mDescriptor = &kNoiseSuppressionDesc;
+ mEffectName = &kNoiseSuppressionEffectName;
+ } else {
+ LOG(ERROR) << __func__ << uuid.toString() << " not supported!";
+ }
+}
+
+EffectPreProcessing::~EffectPreProcessing() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getDescriptor(Descriptor* _aidl_return) {
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ LOG(DEBUG) << _aidl_return->toString();
+ *_aidl_return = *mDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterSpecific(const Parameter::Specific& specific) {
+ LOG(DEBUG) << __func__ << " specific " << specific.toString();
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto tag = specific.getTag();
+ switch (tag) {
+ case Parameter::Specific::acousticEchoCanceler:
+ return setParameterAcousticEchoCanceler(specific);
+ case Parameter::Specific::automaticGainControlV1:
+ return setParameterAutomaticGainControlV1(specific);
+ case Parameter::Specific::automaticGainControlV2:
+ return setParameterAutomaticGainControlV2(specific);
+ case Parameter::Specific::noiseSuppression:
+ return setParameterNoiseSuppression(specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "specificParamNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterAcousticEchoCanceler(
+ const Parameter::Specific& specific) {
+ auto& param = specific.get<Parameter::Specific::acousticEchoCanceler>();
+ RETURN_IF(!inRange(param, kAcousticEchoCancelerRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+ auto tag = param.getTag();
+
+ switch (tag) {
+ case AcousticEchoCanceler::echoDelayUs: {
+ RETURN_IF(mContext->setAcousticEchoCancelerEchoDelay(
+ param.get<AcousticEchoCanceler::echoDelayUs>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "echoDelayNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case AcousticEchoCanceler::mobileMode: {
+ RETURN_IF(mContext->setAcousticEchoCancelerMobileMode(
+ param.get<AcousticEchoCanceler::mobileMode>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "SettingMobileModeNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterAutomaticGainControlV1(
+ const Parameter::Specific& specific) {
+ auto& param = specific.get<Parameter::Specific::automaticGainControlV1>();
+ RETURN_IF(!inRange(param, kAutomaticGainControlV1Ranges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+ auto tag = param.getTag();
+
+ switch (tag) {
+ case AutomaticGainControlV1::targetPeakLevelDbFs: {
+ RETURN_IF(mContext->setAutomaticGainControlV1TargetPeakLevel(
+ param.get<AutomaticGainControlV1::targetPeakLevelDbFs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "targetPeakLevelNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case AutomaticGainControlV1::maxCompressionGainDb: {
+ RETURN_IF(mContext->setAutomaticGainControlV1MaxCompressionGain(
+ param.get<AutomaticGainControlV1::maxCompressionGainDb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "maxCompressionGainNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case AutomaticGainControlV1::enableLimiter: {
+ RETURN_IF(
+ mContext->setAutomaticGainControlV1EnableLimiter(
+ param.get<AutomaticGainControlV1::enableLimiter>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "enableLimiterNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV1TagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterAutomaticGainControlV2(
+ const Parameter::Specific& specific) {
+ auto& param = specific.get<Parameter::Specific::automaticGainControlV2>();
+ RETURN_IF(!inRange(param, kAutomaticGainControlV2Ranges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+ auto tag = param.getTag();
+
+ switch (tag) {
+ case AutomaticGainControlV2::fixedDigitalGainMb: {
+ RETURN_IF(mContext->setAutomaticGainControlV2DigitalGain(
+ param.get<AutomaticGainControlV2::fixedDigitalGainMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "digitalGainNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case AutomaticGainControlV2::levelEstimator: {
+ RETURN_IF(mContext->setAutomaticGainControlV2LevelEstimator(
+ param.get<AutomaticGainControlV2::levelEstimator>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "levelEstimatorNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case AutomaticGainControlV2::saturationMarginMb: {
+ RETURN_IF(mContext->setAutomaticGainControlV2SaturationMargin(
+ param.get<AutomaticGainControlV2::saturationMarginMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "saturationMarginNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV2TagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterNoiseSuppression(
+ const Parameter::Specific& specific) {
+ auto& param = specific.get<Parameter::Specific::noiseSuppression>();
+ auto tag = param.getTag();
+
+ switch (tag) {
+ case NoiseSuppression::level: {
+ RETURN_IF(mContext->setNoiseSuppressionLevel(param.get<NoiseSuppression::level>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "levelNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+ auto tag = id.getTag();
+
+ switch (tag) {
+ case Parameter::Id::acousticEchoCancelerTag:
+ return getParameterAcousticEchoCanceler(
+ id.get<Parameter::Id::acousticEchoCancelerTag>(), specific);
+ case Parameter::Id::automaticGainControlV1Tag:
+ return getParameterAutomaticGainControlV1(
+ id.get<Parameter::Id::automaticGainControlV1Tag>(), specific);
+ case Parameter::Id::automaticGainControlV2Tag:
+ return getParameterAutomaticGainControlV2(
+ id.get<Parameter::Id::automaticGainControlV2Tag>(), specific);
+ case Parameter::Id::noiseSuppressionTag:
+ return getParameterNoiseSuppression(id.get<Parameter::Id::noiseSuppressionTag>(),
+ specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "wrongIdTag");
+ }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterAcousticEchoCanceler(
+ const AcousticEchoCanceler::Id& id, Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != AcousticEchoCanceler::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "AcousticEchoCancelerTagNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ AcousticEchoCanceler param;
+ auto tag = id.get<AcousticEchoCanceler::Id::commonTag>();
+ switch (tag) {
+ case AcousticEchoCanceler::echoDelayUs: {
+ param.set<AcousticEchoCanceler::echoDelayUs>(
+ mContext->getAcousticEchoCancelerEchoDelay());
+ break;
+ }
+ case AcousticEchoCanceler::mobileMode: {
+ param.set<AcousticEchoCanceler::mobileMode>(
+ mContext->getAcousticEchoCancelerMobileMode());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::acousticEchoCanceler>(param);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterAutomaticGainControlV1(
+ const AutomaticGainControlV1::Id& id, Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != AutomaticGainControlV1::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "AutomaticGainControlV1TagNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ AutomaticGainControlV1 param;
+
+ auto tag = id.get<AutomaticGainControlV1::Id::commonTag>();
+ switch (tag) {
+ case AutomaticGainControlV1::targetPeakLevelDbFs: {
+ param.set<AutomaticGainControlV1::targetPeakLevelDbFs>(
+ mContext->getAutomaticGainControlV1TargetPeakLevel());
+ break;
+ }
+ case AutomaticGainControlV1::maxCompressionGainDb: {
+ param.set<AutomaticGainControlV1::maxCompressionGainDb>(
+ mContext->getAutomaticGainControlV1MaxCompressionGain());
+ break;
+ }
+ case AutomaticGainControlV1::enableLimiter: {
+ param.set<AutomaticGainControlV1::enableLimiter>(
+ mContext->getAutomaticGainControlV1EnableLimiter());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV1TagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::automaticGainControlV1>(param);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterAutomaticGainControlV2(
+ const AutomaticGainControlV2::Id& id, Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != AutomaticGainControlV2::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "AutomaticGainControlV2TagNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ AutomaticGainControlV2 param;
+
+ auto tag = id.get<AutomaticGainControlV2::Id::commonTag>();
+ switch (tag) {
+ case AutomaticGainControlV2::fixedDigitalGainMb: {
+ param.set<AutomaticGainControlV2::fixedDigitalGainMb>(
+ mContext->getAutomaticGainControlV2DigitalGain());
+ break;
+ }
+ case AutomaticGainControlV2::levelEstimator: {
+ param.set<AutomaticGainControlV2::levelEstimator>(
+ mContext->getAutomaticGainControlV2LevelEstimator());
+ break;
+ }
+ case AutomaticGainControlV2::saturationMarginMb: {
+ param.set<AutomaticGainControlV2::saturationMarginMb>(
+ mContext->getAutomaticGainControlV2SaturationMargin());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV2TagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::automaticGainControlV2>(param);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterNoiseSuppression(
+ const NoiseSuppression::Id& id, Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != NoiseSuppression::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "NoiseSuppressionTagNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ NoiseSuppression param;
+
+ auto tag = id.get<NoiseSuppression::Id::commonTag>();
+ switch (tag) {
+ case NoiseSuppression::level: {
+ param.set<NoiseSuppression::level>(mContext->getNoiseSuppressionLevel());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::noiseSuppression>(param);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> EffectPreProcessing::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ } else {
+ // PreProcessingSession is a singleton
+ mContext = PreProcessingSession::getPreProcessingSession().createSession(
+ mType, 1 /* statusFmqDepth */, common);
+ }
+
+ return mContext;
+}
+
+std::shared_ptr<EffectContext> EffectPreProcessing::getContext() {
+ return mContext;
+}
+
+RetCode EffectPreProcessing::releaseContext() {
+ if (mContext) {
+ PreProcessingSession::getPreProcessingSession().releaseSession(mType,
+ mContext->getSessionId());
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+ndk::ScopedAStatus EffectPreProcessing::commandImpl(CommandId command) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (command) {
+ case CommandId::START:
+ mContext->enable();
+ break;
+ case CommandId::STOP:
+ mContext->disable();
+ break;
+ case CommandId::RESET:
+ mContext->disable();
+ mContext->resetBuffer();
+ break;
+ default:
+ LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commandIdNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status EffectPreProcessing::effectProcessImpl(float* in, float* out, int sampleToProcess) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!mContext, status, "nullContext");
+ return mContext->lvmProcess(in, out, sampleToProcess);
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/EffectPreProcessing.h b/media/libeffects/preprocessing/aidl/EffectPreProcessing.h
new file mode 100644
index 0000000..fad848a
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/EffectPreProcessing.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "PreProcessingContext.h"
+#include "PreProcessingSession.h"
+#include "effect-impl/EffectImpl.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectPreProcessing final : public EffectImpl {
+ public:
+ explicit EffectPreProcessing(const AudioUuid& uuid);
+ ~EffectPreProcessing() override;
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ std::shared_ptr<EffectContext> getContext() override;
+ RetCode releaseContext() override;
+
+ IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+
+ std::string getEffectName() override { return *mEffectName; }
+
+ private:
+ std::shared_ptr<PreProcessingContext> mContext;
+ const Descriptor* mDescriptor;
+ const std::string* mEffectName;
+ PreProcessingEffectType mType;
+
+ ndk::ScopedAStatus setParameterAcousticEchoCanceler(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterAcousticEchoCanceler(const AcousticEchoCanceler::Id& id,
+ Parameter::Specific* specific);
+
+ ndk::ScopedAStatus setParameterAutomaticGainControlV1(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterAutomaticGainControlV1(const AutomaticGainControlV1::Id& id,
+ Parameter::Specific* specific);
+
+ ndk::ScopedAStatus setParameterAutomaticGainControlV2(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterAutomaticGainControlV2(const AutomaticGainControlV2::Id& id,
+ Parameter::Specific* specific);
+
+ ndk::ScopedAStatus setParameterNoiseSuppression(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterNoiseSuppression(const NoiseSuppression::Id& id,
+ Parameter::Specific* specific);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp b/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp
new file mode 100644
index 0000000..c1e4eda
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2023 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 <cstddef>
+#define LOG_TAG "PreProcessingContext"
+#include <Utils.h>
+
+#include "PreProcessingContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+
+RetCode PreProcessingContext::init(const Parameter::Common& common) {
+ std::lock_guard lg(mMutex);
+ webrtc::AudioProcessingBuilder apBuilder;
+ mAudioProcessingModule = apBuilder.Create();
+ if (mAudioProcessingModule == nullptr) {
+ LOG(ERROR) << "init could not get apm engine";
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+
+ updateConfigs(common);
+
+ mEnabledMsk = 0;
+ mProcessedMsk = 0;
+ mRevEnabledMsk = 0;
+ mRevProcessedMsk = 0;
+
+ auto config = mAudioProcessingModule->GetConfig();
+ switch (mType) {
+ case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+ config.echo_canceller.mobile_mode = true;
+ break;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+ config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
+ config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
+ config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
+ break;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+ config.gain_controller2.fixed_digital.gain_db = 0.f;
+ break;
+ case PreProcessingEffectType::NOISE_SUPPRESSION:
+ config.noise_suppression.level = kNsDefaultLevel;
+ break;
+ }
+ mAudioProcessingModule->ApplyConfig(config);
+ mState = PRE_PROC_STATE_INITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::deInit() {
+ std::lock_guard lg(mMutex);
+ mAudioProcessingModule = nullptr;
+ mState = PRE_PROC_STATE_UNINITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::enable() {
+ if (mState != PRE_PROC_STATE_INITIALIZED) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ int typeMsk = (1 << int(mType));
+ std::lock_guard lg(mMutex);
+ // Check if effect is already enabled.
+ if ((mEnabledMsk & typeMsk) == typeMsk) {
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ mEnabledMsk |= typeMsk;
+ auto config = mAudioProcessingModule->GetConfig();
+ switch (mType) {
+ case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+ config.echo_canceller.enabled = true;
+ // AEC has reverse stream
+ mRevEnabledMsk |= typeMsk;
+ mRevProcessedMsk = 0;
+ break;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+ config.gain_controller1.enabled = true;
+ break;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+ config.gain_controller2.enabled = true;
+ break;
+ case PreProcessingEffectType::NOISE_SUPPRESSION:
+ config.noise_suppression.enabled = true;
+ break;
+ }
+ mProcessedMsk = 0;
+ mAudioProcessingModule->ApplyConfig(config);
+ mState = PRE_PROC_STATE_ACTIVE;
+ return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::disable() {
+ if (mState != PRE_PROC_STATE_ACTIVE) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ int typeMsk = (1 << int(mType));
+ std::lock_guard lg(mMutex);
+ // Check if effect is already disabled.
+ if ((mEnabledMsk & typeMsk) != typeMsk) {
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ mEnabledMsk &= ~typeMsk;
+ auto config = mAudioProcessingModule->GetConfig();
+ switch (mType) {
+ case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+ config.echo_canceller.enabled = false;
+ // AEC has reverse stream
+ mRevEnabledMsk &= ~typeMsk;
+ mRevProcessedMsk = 0;
+ break;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+ config.gain_controller1.enabled = false;
+ break;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+ config.gain_controller2.enabled = false;
+ break;
+ case PreProcessingEffectType::NOISE_SUPPRESSION:
+ config.noise_suppression.enabled = false;
+ break;
+ }
+ mProcessedMsk = 0;
+ mAudioProcessingModule->ApplyConfig(config);
+ mState = PRE_PROC_STATE_INITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::setCommon(const Parameter::Common& common) {
+ mCommon = common;
+ updateConfigs(common);
+ return RetCode::SUCCESS;
+}
+
+void PreProcessingContext::updateConfigs(const Parameter::Common& common) {
+ mInputConfig.set_sample_rate_hz(common.input.base.sampleRate);
+ mInputConfig.set_num_channels(::aidl::android::hardware::audio::common::getChannelCount(
+ common.input.base.channelMask));
+ mOutputConfig.set_sample_rate_hz(common.input.base.sampleRate);
+ mOutputConfig.set_num_channels(::aidl::android::hardware::audio::common::getChannelCount(
+ common.output.base.channelMask));
+}
+
+RetCode PreProcessingContext::setAcousticEchoCancelerEchoDelay(int echoDelayUs) {
+ mEchoDelayUs = echoDelayUs;
+ std::lock_guard lg(mMutex);
+ mAudioProcessingModule->set_stream_delay_ms(mEchoDelayUs / 1000);
+ return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAcousticEchoCancelerEchoDelay() const {
+ return mEchoDelayUs;
+}
+
+RetCode PreProcessingContext::setAcousticEchoCancelerMobileMode(bool mobileMode) {
+ mMobileMode = mobileMode;
+ std::lock_guard lg(mMutex);
+ auto config = mAudioProcessingModule->GetConfig();
+ config.echo_canceller.mobile_mode = mobileMode;
+ mAudioProcessingModule->ApplyConfig(config);
+ return RetCode::SUCCESS;
+}
+
+bool PreProcessingContext::getAcousticEchoCancelerMobileMode() const {
+ return mMobileMode;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV1TargetPeakLevel(int targetPeakLevel) {
+ mTargetPeakLevel = targetPeakLevel;
+ std::lock_guard lg(mMutex);
+ auto config = mAudioProcessingModule->GetConfig();
+ config.gain_controller1.target_level_dbfs = -(mTargetPeakLevel / 100);
+ mAudioProcessingModule->ApplyConfig(config);
+ return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV1TargetPeakLevel() const {
+ return mTargetPeakLevel;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV1MaxCompressionGain(int maxCompressionGain) {
+ mMaxCompressionGain = maxCompressionGain;
+ std::lock_guard lg(mMutex);
+ auto config = mAudioProcessingModule->GetConfig();
+ config.gain_controller1.compression_gain_db = mMaxCompressionGain / 100;
+ mAudioProcessingModule->ApplyConfig(config);
+ return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV1MaxCompressionGain() const {
+ return mMaxCompressionGain;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV1EnableLimiter(bool enableLimiter) {
+ mEnableLimiter = enableLimiter;
+ std::lock_guard lg(mMutex);
+ auto config = mAudioProcessingModule->GetConfig();
+ config.gain_controller1.enable_limiter = mEnableLimiter;
+ mAudioProcessingModule->ApplyConfig(config);
+ return RetCode::SUCCESS;
+}
+
+bool PreProcessingContext::getAutomaticGainControlV1EnableLimiter() const {
+ return mEnableLimiter;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV2DigitalGain(int gain) {
+ mDigitalGain = gain;
+ std::lock_guard lg(mMutex);
+ auto config = mAudioProcessingModule->GetConfig();
+ config.gain_controller2.fixed_digital.gain_db = mDigitalGain;
+ mAudioProcessingModule->ApplyConfig(config);
+ return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV2DigitalGain() const {
+ return mDigitalGain;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV2LevelEstimator(
+ AutomaticGainControlV2::LevelEstimator levelEstimator) {
+ mLevelEstimator = levelEstimator;
+ return RetCode::SUCCESS;
+}
+
+AutomaticGainControlV2::LevelEstimator
+PreProcessingContext::getAutomaticGainControlV2LevelEstimator() const {
+ return mLevelEstimator;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV2SaturationMargin(int saturationMargin) {
+ mSaturationMargin = saturationMargin;
+ return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV2SaturationMargin() const {
+ return mSaturationMargin;
+}
+
+RetCode PreProcessingContext::setNoiseSuppressionLevel(NoiseSuppression::Level level) {
+ mLevel = level;
+ std::lock_guard lg(mMutex);
+ auto config = mAudioProcessingModule->GetConfig();
+ config.noise_suppression.level =
+ (webrtc::AudioProcessing::Config::NoiseSuppression::Level)level;
+ mAudioProcessingModule->ApplyConfig(config);
+ return RetCode::SUCCESS;
+}
+
+NoiseSuppression::Level PreProcessingContext::getNoiseSuppressionLevel() const {
+ return mLevel;
+}
+
+IEffect::Status PreProcessingContext::lvmProcess(float* in, float* out, int samples) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!in, status, "nullInput");
+ RETURN_VALUE_IF(!out, status, "nullOutput");
+ status = {EX_ILLEGAL_STATE, 0, 0};
+ int64_t inputFrameCount = getCommon().input.frameCount;
+ int64_t outputFrameCount = getCommon().output.frameCount;
+ RETURN_VALUE_IF(inputFrameCount != outputFrameCount, status, "FrameCountMismatch");
+ RETURN_VALUE_IF(0 == getInputFrameSize(), status, "zeroFrameSize");
+
+ LOG(DEBUG) << __func__ << " start processing";
+ std::lock_guard lg(mMutex);
+
+ mProcessedMsk |= (1 << int(mType));
+
+ // webrtc implementation clear out was_stream_delay_set every time after ProcessStream() call
+ mAudioProcessingModule->set_stream_delay_ms(mEchoDelayUs / 1000);
+
+ if ((mProcessedMsk & mEnabledMsk) == mEnabledMsk) {
+ mProcessedMsk = 0;
+ int processStatus = mAudioProcessingModule->ProcessStream(
+ (const int16_t* const)in, mInputConfig, mOutputConfig, (int16_t* const)out);
+ if (processStatus != 0) {
+ LOG(ERROR) << "Process stream failed with error " << processStatus;
+ return status;
+ }
+ }
+
+ mRevProcessedMsk |= (1 << int(mType));
+
+ if ((mRevProcessedMsk & mRevEnabledMsk) == mRevEnabledMsk) {
+ mRevProcessedMsk = 0;
+ int revProcessStatus = mAudioProcessingModule->ProcessReverseStream(
+ (const int16_t* const)in, mInputConfig, mInputConfig, (int16_t* const)out);
+ if (revProcessStatus != 0) {
+ LOG(ERROR) << "Process reverse stream failed with error " << revProcessStatus;
+ return status;
+ }
+ }
+
+ return {STATUS_OK, samples, samples};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingContext.h b/media/libeffects/preprocessing/aidl/PreProcessingContext.h
new file mode 100644
index 0000000..9ba1bbe
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/PreProcessingContext.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2023 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 <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+#include <audio_processing.h>
+#include <unordered_map>
+
+#include "PreProcessingTypes.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+enum PreProcEffectState {
+ PRE_PROC_STATE_UNINITIALIZED,
+ PRE_PROC_STATE_INITIALIZED,
+ PRE_PROC_STATE_ACTIVE,
+};
+
+class PreProcessingContext final : public EffectContext {
+ public:
+ PreProcessingContext(int statusDepth, const Parameter::Common& common,
+ const PreProcessingEffectType& type)
+ : EffectContext(statusDepth, common), mType(type) {
+ LOG(DEBUG) << __func__ << type;
+ mState = PRE_PROC_STATE_UNINITIALIZED;
+ }
+ ~PreProcessingContext() override { LOG(DEBUG) << __func__; }
+
+ RetCode init(const Parameter::Common& common);
+ RetCode deInit();
+
+ PreProcessingEffectType getPreProcessingType() const { return mType; }
+
+ RetCode enable();
+ RetCode disable();
+
+ RetCode setCommon(const Parameter::Common& common) override;
+ void updateConfigs(const Parameter::Common& common);
+
+ RetCode setAcousticEchoCancelerEchoDelay(int echoDelayUs);
+ int getAcousticEchoCancelerEchoDelay() const;
+ RetCode setAcousticEchoCancelerMobileMode(bool mobileMode);
+ bool getAcousticEchoCancelerMobileMode() const;
+
+ RetCode setAutomaticGainControlV1TargetPeakLevel(int targetPeakLevel);
+ int getAutomaticGainControlV1TargetPeakLevel() const;
+ RetCode setAutomaticGainControlV1MaxCompressionGain(int maxCompressionGain);
+ int getAutomaticGainControlV1MaxCompressionGain() const;
+ RetCode setAutomaticGainControlV1EnableLimiter(bool enableLimiter);
+ bool getAutomaticGainControlV1EnableLimiter() const;
+
+ RetCode setAutomaticGainControlV2DigitalGain(int gain);
+ int getAutomaticGainControlV2DigitalGain() const;
+ RetCode setAutomaticGainControlV2LevelEstimator(
+ AutomaticGainControlV2::LevelEstimator levelEstimator);
+ AutomaticGainControlV2::LevelEstimator getAutomaticGainControlV2LevelEstimator() const;
+ RetCode setAutomaticGainControlV2SaturationMargin(int saturationMargin);
+ int getAutomaticGainControlV2SaturationMargin() const;
+
+ RetCode setNoiseSuppressionLevel(NoiseSuppression::Level level);
+ NoiseSuppression::Level getNoiseSuppressionLevel() const;
+
+ IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+ private:
+ static constexpr inline int kAgcDefaultTargetLevel = 3;
+ static constexpr inline int kAgcDefaultCompGain = 9;
+ static constexpr inline bool kAgcDefaultLimiter = true;
+ static constexpr inline webrtc::AudioProcessing::Config::NoiseSuppression::Level
+ kNsDefaultLevel = webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
+
+ std::mutex mMutex;
+ const PreProcessingEffectType mType;
+ PreProcEffectState mState; // current state
+
+ // handle on webRTC audio processing module (APM)
+ rtc::scoped_refptr<webrtc::AudioProcessing> mAudioProcessingModule GUARDED_BY(mMutex);
+
+ int mEnabledMsk GUARDED_BY(mMutex); // bit field containing IDs of enabled pre processors
+ int mProcessedMsk GUARDED_BY(mMutex); // bit field containing IDs of pre processors already
+ // processed in current round
+ int mRevEnabledMsk GUARDED_BY(mMutex); // bit field containing IDs of enabled pre processors
+ // with reverse channel
+ int mRevProcessedMsk GUARDED_BY(mMutex); // bit field containing IDs of pre processors with
+ // reverse channel already processed in current round
+
+ webrtc::StreamConfig mInputConfig; // input stream configuration
+ webrtc::StreamConfig mOutputConfig; // output stream configuration
+
+ // Acoustic Echo Canceler
+ int mEchoDelayUs = 0;
+ bool mMobileMode = false;
+
+ // Automatic Gain Control V1
+ int mTargetPeakLevel = 0;
+ int mMaxCompressionGain = 0;
+ bool mEnableLimiter = false;
+
+ // Automatic Gain Control V2
+ int mDigitalGain = 0;
+ AutomaticGainControlV2::LevelEstimator mLevelEstimator =
+ AutomaticGainControlV2::LevelEstimator::RMS;
+ int mSaturationMargin = 2;
+
+ // NoiseSuppression
+ NoiseSuppression::Level mLevel = NoiseSuppression::Level::LOW;
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingSession.h b/media/libeffects/preprocessing/aidl/PreProcessingSession.h
new file mode 100644
index 0000000..877292f
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/PreProcessingSession.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2023 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 <algorithm>
+#include <memory>
+#include <unordered_map>
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+
+#include "PreProcessingContext.h"
+#include "PreProcessingTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+/**
+ * @brief Maintain all effect pre-processing sessions.
+ *
+ * Sessions are identified with the session ID, maximum of MAX_BUNDLE_SESSIONS is supported by the
+ * pre-processing implementation.
+ */
+class PreProcessingSession {
+ public:
+ static PreProcessingSession& getPreProcessingSession() {
+ static PreProcessingSession instance;
+ return instance;
+ }
+
+ static bool findPreProcessingTypeInList(
+ std::vector<std::shared_ptr<PreProcessingContext>>& list,
+ const PreProcessingEffectType& type, bool remove = false) {
+ auto itor = std::find_if(list.begin(), list.end(),
+ [type](const std::shared_ptr<PreProcessingContext>& bundle) {
+ return bundle->getPreProcessingType() == type;
+ });
+ if (itor == list.end()) {
+ return false;
+ }
+ if (remove) {
+ (*itor)->deInit();
+ list.erase(itor);
+ }
+ return true;
+ }
+
+ /**
+ * Create a certain type of PreProcessingContext in shared_ptr container, each session must not
+ * have more than one session for each type.
+ */
+ std::shared_ptr<PreProcessingContext> createSession(const PreProcessingEffectType& type,
+ int statusDepth,
+ const Parameter::Common& common) {
+ int sessionId = common.session;
+ LOG(DEBUG) << __func__ << type << " with sessionId " << sessionId;
+ std::lock_guard lg(mMutex);
+ if (mSessionMap.count(sessionId) == 0 && mSessionMap.size() >= MAX_PRE_PROC_SESSIONS) {
+ LOG(ERROR) << __func__ << " exceed max bundle session";
+ return nullptr;
+ }
+
+ if (mSessionMap.count(sessionId)) {
+ if (findPreProcessingTypeInList(mSessionMap[sessionId], type)) {
+ LOG(ERROR) << __func__ << type << " already exist in session " << sessionId;
+ return nullptr;
+ }
+ }
+
+ auto& list = mSessionMap[sessionId];
+ auto context = std::make_shared<PreProcessingContext>(statusDepth, common, type);
+ RETURN_VALUE_IF(!context, nullptr, "failedToCreateContext");
+
+ RetCode ret = context->init(common);
+ if (RetCode::SUCCESS != ret) {
+ LOG(ERROR) << __func__ << " context init ret " << ret;
+ return nullptr;
+ }
+ list.push_back(context);
+ return context;
+ }
+
+ void releaseSession(const PreProcessingEffectType& type, int sessionId) {
+ LOG(DEBUG) << __func__ << type << " sessionId " << sessionId;
+ std::lock_guard lg(mMutex);
+ if (mSessionMap.count(sessionId)) {
+ auto& list = mSessionMap[sessionId];
+ if (!findPreProcessingTypeInList(list, type, true /* remove */)) {
+ LOG(ERROR) << __func__ << " can't find " << type << "in session " << sessionId;
+ return;
+ }
+ if (list.empty()) {
+ mSessionMap.erase(sessionId);
+ }
+ }
+ }
+
+ private:
+ // Lock for mSessionMap access.
+ std::mutex mMutex;
+ // Max session number supported.
+ static constexpr int MAX_PRE_PROC_SESSIONS = 8;
+ std::unordered_map<int /* session ID */, std::vector<std::shared_ptr<PreProcessingContext>>>
+ mSessionMap GUARDED_BY(mMutex);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingTypes.h b/media/libeffects/preprocessing/aidl/PreProcessingTypes.h
new file mode 100644
index 0000000..4c2b8ba
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/PreProcessingTypes.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2023 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 <optional>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include <audio_effects/effect_aec.h>
+#include <audio_effects/effect_agc.h>
+#include <audio_effects/effect_agc2.h>
+#include <audio_effects/effect_ns.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "effect-impl/EffectTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+// Acoustic Echo Cancellation
+static const std::string kAcousticEchoCancelerEffectName = "Acoustic Echo Canceler";
+static const std::vector<Range::AcousticEchoCancelerRange> kAcousticEchoCancelerRanges = {
+ MAKE_RANGE(AcousticEchoCanceler, AcousticEchoCanceler::echoDelayUs, 0, 500)};
+static const Capability kAcousticEchoCancelerCap = {.range = kAcousticEchoCancelerRanges};
+static const Descriptor kAcousticEchoCancelerDesc = {
+ .common = {.id = {.type = getEffectTypeUuidAcousticEchoCanceler(),
+ .uuid = getEffectImplUuidAcousticEchoCancelerSw(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::PRE_PROC, .deviceIndication = true},
+ .name = kAcousticEchoCancelerEffectName,
+ .implementor = "The Android Open Source Project"},
+ .capability = kAcousticEchoCancelerCap};
+
+// Automatic Gain Control 1
+static const std::string kAutomaticGainControlV1EffectName = "Automatic Gain Control V1";
+static const std::vector<Range::AutomaticGainControlV1Range> kAutomaticGainControlV1Ranges = {
+ MAKE_RANGE(AutomaticGainControlV1, AutomaticGainControlV1::targetPeakLevelDbFs, -3100, 0),
+ MAKE_RANGE(AutomaticGainControlV1, AutomaticGainControlV1::maxCompressionGainDb, 0, 9000)};
+static const Capability kAutomaticGainControlV1Cap = {.range = kAutomaticGainControlV1Ranges};
+static const Descriptor kAutomaticGainControlV1Desc = {
+ .common = {.id = {.type = getEffectTypeUuidAutomaticGainControlV1(),
+ .uuid = getEffectImplUuidAutomaticGainControlV1Sw(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::PRE_PROC, .deviceIndication = true},
+ .name = kAutomaticGainControlV1EffectName,
+ .implementor = "The Android Open Source Project"},
+ .capability = kAutomaticGainControlV1Cap};
+
+// Automatic Gain Control 2
+static const std::string kAutomaticGainControlV2EffectName = "Automatic Gain Control V2";
+const std::vector<Range::AutomaticGainControlV2Range> kAutomaticGainControlV2Ranges = {
+ MAKE_RANGE(AutomaticGainControlV2, AutomaticGainControlV2::fixedDigitalGainMb, 0, 90),
+ // extra_staturation_margin_db is no longer configurable in webrtc
+ MAKE_RANGE(AutomaticGainControlV2, AutomaticGainControlV2::saturationMarginMb, 2, 2),
+ // WebRTC only supports RMS level estimator now
+ MAKE_RANGE(AutomaticGainControlV2, AutomaticGainControlV2::levelEstimator,
+ AutomaticGainControlV2::LevelEstimator::RMS,
+ AutomaticGainControlV2::LevelEstimator::RMS)};
+static const Capability kAutomaticGainControlV2Cap = {.range = kAutomaticGainControlV2Ranges};
+static const Descriptor kAutomaticGainControlV2Desc = {
+ .common = {.id = {.type = getEffectTypeUuidAutomaticGainControlV2(),
+ .uuid = getEffectImplUuidAutomaticGainControlV2Sw(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::PRE_PROC, .deviceIndication = true},
+ .name = kAutomaticGainControlV2EffectName,
+ .implementor = "The Android Open Source Project"},
+ .capability = kAutomaticGainControlV2Cap};
+
+// Noise suppression
+static const std::string kNoiseSuppressionEffectName = "Noise Suppression";
+static const Descriptor kNoiseSuppressionDesc = {
+ .common = {.id = {.type = getEffectTypeUuidNoiseSuppression(),
+ .uuid = getEffectImplUuidNoiseSuppressionSw(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::PRE_PROC, .deviceIndication = true},
+ .name = kNoiseSuppressionEffectName,
+ .implementor = "The Android Open Source Project"}};
+
+enum class PreProcessingEffectType {
+ ACOUSTIC_ECHO_CANCELLATION,
+ AUTOMATIC_GAIN_CONTROL_V1,
+ AUTOMATIC_GAIN_CONTROL_V2,
+ NOISE_SUPPRESSION,
+};
+
+inline std::ostream& operator<<(std::ostream& out, const PreProcessingEffectType& type) {
+ switch (type) {
+ case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+ return out << kAcousticEchoCancelerEffectName;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+ return out << kAutomaticGainControlV1EffectName;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+ return out << kAutomaticGainControlV2EffectName;
+ case PreProcessingEffectType::NOISE_SUPPRESSION:
+ return out << kNoiseSuppressionEffectName;
+ }
+ return out << "EnumPreProcessingEffectTypeError";
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp b/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
index 07006a1..8fdb864 100644
--- a/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
+++ b/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
@@ -143,10 +143,6 @@
const AGC2Params* agc2Params = ¶ms->agc2Params;
ASSERT_NO_FATAL_FAILURE(
effect.setParam(AGC2_PARAM_FIXED_DIGITAL_GAIN, agc2Params->fixedDigitalGain));
- ASSERT_NO_FATAL_FAILURE(effect.setParam(AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR,
- agc2Params->adaptDigiLevelEstimator));
- ASSERT_NO_FATAL_FAILURE(effect.setParam(AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN,
- agc2Params->extraSaturationMargin));
} else if (isAECEffect(uuid)) {
const AECParams* aecParams = ¶ms->aecParams;
ASSERT_NO_FATAL_FAILURE(effect.setParam(AEC_PARAM_ECHO_DELAY, aecParams->echoDelay));
diff --git a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
index 3bd93f8..03400d7 100644
--- a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
+++ b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
@@ -400,20 +400,6 @@
ALOGE("Invalid AGC2 Fixed Digital Gain. Error %d\n", status);
return EXIT_FAILURE;
}
- if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR,
- (uint32_t)preProcCfgParams.agc2Level,
- effectHandle[PREPROC_AGC2]);
- status != 0) {
- ALOGE("Invalid AGC2 Level Estimator. Error %d\n", status);
- return EXIT_FAILURE;
- }
- if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN,
- (float)preProcCfgParams.agc2SaturationMargin,
- effectHandle[PREPROC_AGC2]);
- status != 0) {
- ALOGE("Invalid AGC2 Saturation Margin. Error %d\n", status);
- return EXIT_FAILURE;
- }
}
if (effectEn[PREPROC_NS]) {
if (int status = preProcSetConfigParam(NS_PARAM_LEVEL, (uint32_t)preProcCfgParams.nsLevel,
diff --git a/media/libeffects/spatializer/benchmarks/Android.bp b/media/libeffects/spatializer/benchmarks/Android.bp
new file mode 100644
index 0000000..ab7e468
--- /dev/null
+++ b/media/libeffects/spatializer/benchmarks/Android.bp
@@ -0,0 +1,21 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_benchmark {
+ name: "spatializer_benchmark",
+ vendor: true,
+ srcs: ["spatializer_benchmark.cpp"],
+ shared_libs: [
+ "libaudioutils",
+ "liblog",
+ ],
+ header_libs: [
+ "libhardware_headers",
+ ],
+}
diff --git a/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp b/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp
new file mode 100644
index 0000000..e8ac480
--- /dev/null
+++ b/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2022 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 <array>
+#include <dlfcn.h>
+#include <random>
+#include <vector>
+
+#include <benchmark/benchmark.h>
+#include <hardware/audio_effect.h>
+#include <log/log.h>
+
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = [] {
+ audio_effect_library_t symbol{};
+ void* effectLib = dlopen("libspatialaudio.so", RTLD_NOW);
+ if (effectLib) {
+ audio_effect_library_t* effectInterface =
+ (audio_effect_library_t*)dlsym(effectLib, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
+ if (effectInterface == nullptr) {
+ ALOGE("dlsym failed: %s", dlerror());
+ exit(-1);
+ }
+ symbol = (audio_effect_library_t)(*effectInterface);
+ } else {
+ ALOGE("dlopen failed: %s", dlerror());
+ exit(-1);
+ }
+ return symbol;
+}();
+
+// channel masks
+constexpr int kInputChMask = AUDIO_CHANNEL_OUT_5POINT1;
+
+// sampleRates
+constexpr size_t kSampleRates[] = {
+ 44100,
+ 48000,
+ 96000,
+};
+constexpr size_t kNumSampleRates = std::size(kSampleRates);
+
+// duration in ms
+constexpr size_t kDurations[] = {2, 5, 10};
+constexpr size_t kNumDurations = std::size(kDurations);
+
+// effect uuids
+constexpr effect_uuid_t kEffectUuid = {
+ 0xcc4677de, 0xff72, 0x11eb, 0x9a03, {0x02, 0x42, 0xac, 0x13, 0x00, 0x03}};
+
+constexpr float kMinAmplitude = -1.0f;
+constexpr float kMaxAmplitude = 1.0f;
+
+/*******************************************************************
+ * A test result running on Pixel 5 for comparison.
+ * The first parameter indicates the sample rate.
+ * 0: 44100, 1: 48000, 2: 96000
+ * The second parameter indicates the duration in ms.
+ * 0: 2, 1: 5, 2: 10
+ * -------------------------------------------------------------
+ * Benchmark Time CPU Iterations
+ * -------------------------------------------------------------
+ * BM_SPATIALIZER/0/0 739848 ns 738497 ns 934
+ * BM_SPATIALIZER/0/1 1250503 ns 1248337 ns 480
+ * BM_SPATIALIZER/0/2 2094092 ns 2090092 ns 310
+ * BM_SPATIALIZER/1/0 783114 ns 781626 ns 683
+ * BM_SPATIALIZER/1/1 1332951 ns 1330473 ns 452
+ * BM_SPATIALIZER/1/2 2258313 ns 2254022 ns 289
+ * BM_SPATIALIZER/2/0 1210332 ns 1207957 ns 477
+ * BM_SPATIALIZER/2/1 2356259 ns 2351764 ns 269
+ * BM_SPATIALIZER/2/2 4267814 ns 4259567 ns 155
+ *******************************************************************/
+
+static void BM_SPATIALIZER(benchmark::State& state) {
+ const size_t sampleRate = kSampleRates[state.range(0)];
+ const size_t durationMs = kDurations[state.range(1)];
+ const size_t frameCount = durationMs * sampleRate / 1000;
+ const size_t inputChannelCount = audio_channel_count_from_out_mask(kInputChMask);
+ const size_t outputChannelCount = audio_channel_count_from_out_mask(AUDIO_CHANNEL_OUT_STEREO);
+
+ // Initialize input buffer with deterministic pseudo-random values
+ std::minstd_rand gen(kInputChMask);
+ std::uniform_real_distribution<> dis(kMinAmplitude, kMaxAmplitude);
+ std::vector<float> input(frameCount * inputChannelCount);
+ for (auto& in : input) {
+ in = dis(gen);
+ }
+
+ effect_handle_t effectHandle = nullptr;
+ if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&kEffectUuid, 1 /* sessionId */,
+ 1 /* ioId */, &effectHandle);
+ status != 0) {
+ ALOGE("create_effect returned an error = %d\n", status);
+ return;
+ }
+
+ effect_config_t config{};
+ config.inputCfg.samplingRate = config.outputCfg.samplingRate = sampleRate;
+ config.inputCfg.channels = kInputChMask;
+ config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
+
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ if (int status = (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t),
+ &config, &replySize, &reply);
+ status != 0) {
+ ALOGE("command returned an error = %d\n", status);
+ return;
+ }
+
+ if (int status = (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_ENABLE, sizeof(effect_config_t),
+ &config, &replySize, &reply);
+ status != 0) {
+ ALOGE("command returned an error = %d\n", status);
+ return;
+ }
+
+ // Run the test
+ std::vector<float> output(frameCount * outputChannelCount);
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(input.data());
+ benchmark::DoNotOptimize(output.data());
+
+ audio_buffer_t inBuffer = {.frameCount = frameCount, .f32 = input.data()};
+ audio_buffer_t outBuffer = {.frameCount = frameCount, .f32 = output.data()};
+ (*effectHandle)->process(effectHandle, &inBuffer, &outBuffer);
+
+ benchmark::ClobberMemory();
+ }
+
+ state.SetComplexityN(frameCount);
+
+ if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle); status != 0) {
+ ALOGE("release_effect returned an error = %d\n", status);
+ return;
+ }
+}
+
+static void SPATIALIZERArgs(benchmark::internal::Benchmark* b) {
+ for (int i = 0; i < kNumSampleRates; i++) {
+ for (int j = 0; j < kNumDurations; ++j) {
+ b->Args({i, j});
+ }
+ }
+}
+
+BENCHMARK(BM_SPATIALIZER)->Apply(SPATIALIZERArgs);
+
+BENCHMARK_MAIN();
diff --git a/media/libeffects/spatializer/tests/Android.bp b/media/libeffects/spatializer/tests/Android.bp
new file mode 100644
index 0000000..704e873
--- /dev/null
+++ b/media/libeffects/spatializer/tests/Android.bp
@@ -0,0 +1,21 @@
+// Build the unit tests for spatializer effect
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_test {
+ name: "SpatializerTest",
+ defaults: [
+ "libeffects-test-defaults",
+ ],
+ host_supported: false,
+ srcs: [
+ "SpatializerTest.cpp",
+ ],
+}
diff --git a/media/libeffects/spatializer/tests/SpatializerTest.cpp b/media/libeffects/spatializer/tests/SpatializerTest.cpp
new file mode 100644
index 0000000..110fbb1
--- /dev/null
+++ b/media/libeffects/spatializer/tests/SpatializerTest.cpp
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SpatializerTest"
+
+#include <system/audio_effects/effect_spatializer.h>
+#include "EffectTestHelper.h"
+
+using namespace android;
+
+// relying on dlsym to fill the interface context
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = [] {
+ audio_effect_library_t symbol{};
+ void* effectLib = dlopen("libspatialaudio.so", RTLD_NOW);
+ if (effectLib) {
+ audio_effect_library_t* effectInterface =
+ (audio_effect_library_t*)dlsym(effectLib, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
+ if (effectInterface == nullptr) {
+ ALOGE("dlsym failed: %s", dlerror());
+ exit(-1);
+ }
+ symbol = (audio_effect_library_t)(*effectInterface);
+ } else {
+ ALOGE("dlopen failed: %s", dlerror());
+ exit(-1);
+ }
+ return symbol;
+}();
+
+// channel masks
+constexpr audio_channel_mask_t kSpatializerChMasks[] = {
+ AUDIO_CHANNEL_OUT_5POINT1,
+};
+constexpr size_t kNumSpatializerChMasks = std::size(kSpatializerChMasks);
+
+// sampleRates
+// TODO(b/234170025): Add all sampling rates once they are handled by spatializer
+constexpr int kSpatializerSampleRates[] = {44100, 48000, 96000};
+constexpr size_t kNumSpatializerSampleRates = std::size(kSpatializerSampleRates);
+
+// frame counts
+// TODO(b/234620538): Add sizes smaller than 80 once they are handled by spatializer
+constexpr size_t kSpatializerFrameCounts[] = {4800, 1920, 480, 80};
+constexpr size_t kNumSpatializerFrameCounts = std::size(kSpatializerFrameCounts);
+
+// effect uuids
+constexpr effect_uuid_t kSpatializerEffectUuids[] = {
+ {0xcc4677de, 0xff72, 0x11eb, 0x9a03, {0x02, 0x42, 0xac, 0x13, 0x00, 0x03}},
+};
+const size_t kNumSpatializerEffectUuids = std::size(kSpatializerEffectUuids);
+
+constexpr float kMinAmplitude = -1.0f;
+constexpr float kMaxAmplitude = 1.0f;
+constexpr float kSNRThreshold = 100.0f;
+constexpr size_t kNumBufferSplits = 2;
+
+using SingleEffectTestParam = std::tuple<int, int, int, int, int>;
+
+class SingleEffectTest : public ::testing::TestWithParam<SingleEffectTestParam> {
+ public:
+ SingleEffectTest()
+ : mInputChMask(kSpatializerChMasks[std::get<0>(GetParam())]),
+ mInputChannelCount(audio_channel_count_from_out_mask(mInputChMask)),
+ mOutputChMask(AUDIO_CHANNEL_OUT_STEREO),
+ mOutputChannelCount(audio_channel_count_from_out_mask(mOutputChMask)),
+ mSampleRate(kSpatializerSampleRates[std::get<1>(GetParam())]),
+ mFrameCount(kSpatializerFrameCounts[std::get<2>(GetParam())]),
+ mLoopCount(EffectTestHelper::kLoopCounts[std::get<3>(GetParam())]),
+ mTotalFrameCount(mFrameCount * mLoopCount),
+ mUuid(&kSpatializerEffectUuids[std::get<4>(GetParam())]) {}
+ void SetUp() override {
+ ASSERT_EQ(AUDIO_EFFECT_LIBRARY_TAG, AUDIO_EFFECT_LIBRARY_INFO_SYM.tag)
+ << "Invalid effect tag";
+ }
+ const size_t mInputChMask;
+ const size_t mInputChannelCount;
+ const size_t mOutputChMask;
+ const size_t mOutputChannelCount;
+ const size_t mSampleRate;
+ const size_t mFrameCount;
+ const size_t mLoopCount;
+ const size_t mTotalFrameCount;
+ const effect_uuid_t* mUuid;
+};
+
+// Test basic spatializer functionality (does not crash) for various combinations of sampling
+// rates, channel masks and frame counts.
+TEST_P(SingleEffectTest, SimpleProcess) {
+ SCOPED_TRACE(testing::Message()
+ << "chMask: " << mInputChMask << " sampleRate: " << mSampleRate);
+
+ EffectTestHelper effect(mUuid, mInputChMask, mOutputChMask, mSampleRate, mFrameCount,
+ mLoopCount);
+ ASSERT_NO_FATAL_FAILURE(effect.createEffect());
+ ASSERT_NO_FATAL_FAILURE(effect.setConfig());
+
+ // Initialize input buffer with deterministic pseudo-random values
+ std::vector<float> input(mTotalFrameCount * mInputChannelCount);
+ std::vector<float> output(mTotalFrameCount * mOutputChannelCount);
+ std::minstd_rand gen(mInputChMask);
+ std::uniform_real_distribution<> dis(kMinAmplitude, kMaxAmplitude);
+ for (auto& in : input) {
+ in = dis(gen);
+ }
+ ASSERT_NO_FATAL_FAILURE(effect.process(input.data(), output.data()));
+ ASSERT_NO_FATAL_FAILURE(effect.releaseEffect());
+}
+
+INSTANTIATE_TEST_SUITE_P(SpatializerTest, SingleEffectTest,
+ ::testing::Combine(::testing::Range(0, (int)kNumSpatializerChMasks),
+ ::testing::Range(0, (int)kNumSpatializerSampleRates),
+ ::testing::Range(0, (int)kNumSpatializerFrameCounts),
+ ::testing::Range(0,
+ (int)EffectTestHelper::kNumLoopCounts),
+ ::testing::Range(0, (int)kNumSpatializerEffectUuids)));
+
+using SingleEffectComparisonTestParam = std::tuple<int, int, int>;
+
+class SingleEffectComparisonTest
+ : public ::testing::TestWithParam<SingleEffectComparisonTestParam> {
+ public:
+ SingleEffectComparisonTest()
+ : mInputChMask(kSpatializerChMasks[std::get<0>(GetParam())]),
+ mInputChannelCount(audio_channel_count_from_out_mask(mInputChMask)),
+ mOutputChMask(AUDIO_CHANNEL_OUT_STEREO),
+ mOutputChannelCount(audio_channel_count_from_out_mask(mOutputChMask)),
+ mSampleRate(kSpatializerSampleRates[std::get<1>(GetParam())]),
+ mUuid(&kSpatializerEffectUuids[std::get<2>(GetParam())]) {}
+
+ const size_t mInputChMask;
+ const size_t mInputChannelCount;
+ const size_t mOutputChMask;
+ const size_t mOutputChannelCount;
+ const size_t mSampleRate;
+ const effect_uuid_t* mUuid;
+};
+
+// Ensure that effect produces similar output when an input is fed in a single call
+// or called multiples times with buffer split into smaller parts
+
+// TODO(b/234619903): This is currently disabled as output from the spatializer has
+// an algorithm delay that varies with frame count and hence makes it tricky to
+// compare output from two cases with different frame counts.
+// Feed valid input to spatializer and dump the output to verify spatializer is being
+// correctly initialized and once that is verified, enable the following
+TEST_P(SingleEffectComparisonTest, DISABLED_SimpleProcess) {
+ SCOPED_TRACE(testing::Message()
+ << "chMask: " << mInputChMask << " sampleRate: " << mSampleRate);
+ int testDurationMs = 20; // 20 ms
+ int testFrameCount = (mSampleRate * testDurationMs) / 1000;
+ int totalFrameCount = testFrameCount * kNumBufferSplits;
+ size_t totalInSamples = totalFrameCount * mInputChannelCount;
+ size_t totalOutSamples = totalFrameCount * mOutputChannelCount;
+ std::vector<float> input(totalInSamples);
+ std::vector<float> outRef(totalOutSamples);
+ std::vector<float> outTest(totalOutSamples);
+
+ // Initialize input buffer with deterministic pseudo-random values
+ std::minstd_rand gen(mInputChMask);
+ std::uniform_real_distribution<> dis(kMinAmplitude, kMaxAmplitude);
+ for (auto& in : input) {
+ in = dis(gen);
+ }
+
+ EffectTestHelper refEffect(mUuid, mInputChMask, mOutputChMask, mSampleRate, totalFrameCount, 1);
+ ASSERT_NO_FATAL_FAILURE(refEffect.createEffect());
+ ASSERT_NO_FATAL_FAILURE(refEffect.setConfig());
+ ASSERT_NO_FATAL_FAILURE(refEffect.process(input.data(), outRef.data()));
+ ASSERT_NO_FATAL_FAILURE(refEffect.releaseEffect());
+
+ EffectTestHelper testEffect(mUuid, mInputChMask, mOutputChMask, mSampleRate,
+ totalFrameCount / kNumBufferSplits, kNumBufferSplits);
+ ASSERT_NO_FATAL_FAILURE(testEffect.createEffect());
+ ASSERT_NO_FATAL_FAILURE(testEffect.setConfig());
+ ASSERT_NO_FATAL_FAILURE(testEffect.process(input.data(), outTest.data()));
+ ASSERT_NO_FATAL_FAILURE(testEffect.releaseEffect());
+
+ float snr = computeSnr(outTest.data(), outRef.data(), totalOutSamples);
+ ASSERT_GT(snr, kSNRThreshold) << "SNR between reference and test output " << snr
+ << " is lower than required " << kSNRThreshold;
+}
+
+INSTANTIATE_TEST_SUITE_P(SpatializerTest, SingleEffectComparisonTest,
+ ::testing::Combine(::testing::Range(0, (int)kNumSpatializerChMasks),
+ ::testing::Range(0, (int)kNumSpatializerSampleRates),
+ ::testing::Range(0, (int)kNumSpatializerEffectUuids)));
+
+// This test checks if get/set Spatializer effect params are in accordance with documentation. The
+// test doesn't validate the functionality of the params configured. It only checks the return
+// status of API calls.
+TEST(ParameterTests, CheckParameterSupport) {
+ EffectTestHelper effect(&kSpatializerEffectUuids[0], kSpatializerChMasks[0],
+ AUDIO_CHANNEL_OUT_STEREO, kSpatializerSampleRates[0],
+ kSpatializerFrameCounts[0], EffectTestHelper::kLoopCounts[0]);
+ ASSERT_NO_FATAL_FAILURE(effect.createEffect());
+
+ // capture list of channel masks supported
+ std::vector<audio_channel_mask_t> channelMasks;
+ int status = effect.getParam<true>(SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS, channelMasks);
+ EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+ if (!status) {
+ EXPECT_EQ(1, channelMasks.size());
+ EXPECT_EQ(AUDIO_CHANNEL_OUT_5POINT1, channelMasks[0]);
+ }
+
+ // capture list of spatialization levels supported
+ std::vector<int8_t> spatializationLevels;
+ status = effect.getParam<true>(SPATIALIZER_PARAM_SUPPORTED_LEVELS, spatializationLevels);
+ EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+ if (!status) {
+ EXPECT_EQ(1, spatializationLevels.size());
+ EXPECT_EQ(SPATIALIZATION_LEVEL_MULTICHANNEL, spatializationLevels[0]);
+ }
+
+ // capture list of spatialization modes supported
+ std::vector<int8_t> spatializationModes;
+ status = effect.getParam<true>(SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
+ spatializationModes);
+ EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+ if (!status) {
+ EXPECT_EQ(1, spatializationModes.size());
+ EXPECT_EQ(SPATIALIZATION_MODE_BINAURAL, spatializationModes[0]);
+ }
+
+ // check if head tracking is supported
+ std::vector<int8_t> headTracking;
+ status = effect.getParam<false>(SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED, headTracking);
+ EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+ if (!status) {
+ EXPECT_EQ(1, headTracking.size());
+ EXPECT_EQ(true, headTracking[0]);
+ }
+
+ // verify spatialization level setting
+ std::vector<int8_t> level;
+ status = effect.getParam<false>(SPATIALIZER_PARAM_LEVEL, level);
+ EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+ if (!status) {
+ EXPECT_EQ(1, level.size());
+ EXPECT_EQ(SPATIALIZATION_LEVEL_NONE, level[0]);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(effect.setConfig());
+
+ status = effect.getParam<false>(SPATIALIZER_PARAM_LEVEL, level);
+ EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+ if (!status) {
+ EXPECT_EQ(1, level.size());
+ EXPECT_EQ(SPATIALIZATION_LEVEL_MULTICHANNEL, level[0]);
+ }
+
+ // try setting unsupported parameters
+ level.clear();
+ level.push_back(SPATIALIZATION_LEVEL_MCHAN_BED_PLUS_OBJECTS);
+ ASSERT_EQ(1, level.size());
+ EXPECT_NE(0, effect.setParam(SPATIALIZER_PARAM_LEVEL, level));
+
+ // Ensure that unsupported level isn't set by above setParam
+ status = effect.getParam<false>(SPATIALIZER_PARAM_LEVEL, level);
+ EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+ if (!status) {
+ EXPECT_EQ(1, level.size());
+ EXPECT_EQ(SPATIALIZATION_LEVEL_MULTICHANNEL, level[0]);
+ }
+
+ std::vector<float> hingeAngle = {3.1415f};
+ ASSERT_EQ(1, hingeAngle.size());
+ EXPECT_NE(0, effect.setParam(SPATIALIZER_PARAM_HINGE_ANGLE, hingeAngle));
+
+ std::vector<int8_t> headTrackingMode = {2}; // RELATIVE_WORLD
+ ASSERT_EQ(1, headTrackingMode.size());
+ EXPECT_NE(0, effect.setParam(SPATIALIZER_PARAM_HEADTRACKING_MODE, headTrackingMode));
+
+ // try setting supported parameters
+ std::vector<float> vectorFloat = {0.1, 0.2, 0.15, 0.04, 2.23, 3.14};
+ ASSERT_EQ(6, vectorFloat.size());
+ EXPECT_EQ(0, effect.setParam(SPATIALIZER_PARAM_HEAD_TO_STAGE, vectorFloat));
+
+ ASSERT_NO_FATAL_FAILURE(effect.releaseEffect());
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ ALOGD("Test result = %d\n", status);
+ return status;
+}
diff --git a/media/libeffects/tests/common/Android.bp b/media/libeffects/tests/common/Android.bp
new file mode 100644
index 0000000..73179fb
--- /dev/null
+++ b/media/libeffects/tests/common/Android.bp
@@ -0,0 +1,45 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+filegroup {
+ name: "libeffects-test-helper-srcs",
+ srcs: [
+ "EffectTestHelper.cpp",
+ ],
+}
+
+cc_library_headers {
+ name: "libeffects-test-helper-headers",
+ vendor: true,
+ host_supported: true,
+ export_include_dirs: [
+ ".",
+ ],
+}
+
+cc_defaults {
+ name: "libeffects-test-defaults",
+ vendor: true,
+ gtest: true,
+ host_supported: true,
+ test_suites: ["device-tests"],
+ static_libs: [
+ "libaudioutils",
+ ],
+ srcs: [
+ ":libeffects-test-helper-srcs",
+ ],
+ header_libs: [
+ "libeffects-test-helper-headers",
+ "libhardware_headers",
+ ],
+ shared_libs: [
+ "liblog",
+ ],
+}
diff --git a/media/libeffects/lvm/tests/EffectTestHelper.cpp b/media/libeffects/tests/common/EffectTestHelper.cpp
similarity index 97%
rename from media/libeffects/lvm/tests/EffectTestHelper.cpp
rename to media/libeffects/tests/common/EffectTestHelper.cpp
index ec727c7..db085ba 100644
--- a/media/libeffects/lvm/tests/EffectTestHelper.cpp
+++ b/media/libeffects/tests/common/EffectTestHelper.cpp
@@ -15,7 +15,6 @@
*/
#include "EffectTestHelper.h"
-extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
namespace android {
diff --git a/media/libeffects/lvm/tests/EffectTestHelper.h b/media/libeffects/tests/common/EffectTestHelper.h
similarity index 69%
rename from media/libeffects/lvm/tests/EffectTestHelper.h
rename to media/libeffects/tests/common/EffectTestHelper.h
index bcee84e..c99e27a 100644
--- a/media/libeffects/lvm/tests/EffectTestHelper.h
+++ b/media/libeffects/tests/common/EffectTestHelper.h
@@ -21,6 +21,7 @@
#include <audio_utils/primitives.h>
#include <climits>
#include <cstdlib>
+#include <dlfcn.h>
#include <gtest/gtest.h>
#include <hardware/audio_effect.h>
#include <log/log.h>
@@ -29,7 +30,9 @@
#include <system/audio.h>
#include <vector>
+extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
namespace android {
+
template <typename T>
static float computeSnr(const T* ref, const T* tst, size_t count) {
double signal{};
@@ -82,6 +85,7 @@
void createEffect();
void releaseEffect();
void setConfig();
+
template <typename VALUE_DTYPE>
void setParam(uint32_t type, VALUE_DTYPE const value) {
int reply = 0;
@@ -101,6 +105,76 @@
ASSERT_EQ(status, 0) << "set_param returned an error " << status;
ASSERT_EQ(reply, 0) << "set_param reply non zero " << reply;
};
+
+ template <bool MULTI_VALUES, typename T>
+ int32_t getParam(uint32_t type, std::vector<T>& values) {
+ const int kMaxEffectParamValues = 10;
+ uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1];
+ uint32_t reply[sizeof(effect_param_t) / sizeof(uint32_t) + 1 + 1 + kMaxEffectParamValues];
+
+ effect_param_t* p = (effect_param_t*)cmd;
+ p->psize = sizeof(uint32_t);
+ if (MULTI_VALUES) {
+ p->vsize = (kMaxEffectParamValues + 1) * sizeof(T);
+ } else {
+ p->vsize = sizeof(T);
+ }
+ *(uint32_t*)p->data = type;
+ uint32_t replySize = sizeof(effect_param_t) + p->psize + p->vsize;
+
+ int32_t status = (*mEffectHandle)
+ ->command(mEffectHandle, EFFECT_CMD_GET_PARAM,
+ sizeof(effect_param_t) + sizeof(uint32_t), cmd,
+ &replySize, reply);
+ if (status) {
+ return status;
+ }
+ if (p->status) {
+ return p->status;
+ }
+ if (replySize <
+ sizeof(effect_param_t) + sizeof(uint32_t) + (MULTI_VALUES ? 2 : 1) * sizeof(T)) {
+ return -EINVAL;
+ }
+
+ T* params = (T*)((uint8_t*)reply + sizeof(effect_param_t) + sizeof(uint32_t));
+ int numParams = 1;
+ if (MULTI_VALUES) {
+ numParams = (int)*params++;
+ }
+ if (numParams > kMaxEffectParamValues) {
+ return -EINVAL;
+ }
+ values.clear();
+ std::copy(¶ms[0], ¶ms[numParams], back_inserter(values));
+ return 0;
+ }
+
+ template <typename T>
+ int setParam(uint32_t type, const std::vector<T>& values) {
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+
+ uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1 + values.size()];
+ effect_param_t* p = (effect_param_t*)cmd;
+ p->psize = sizeof(uint32_t);
+ p->vsize = sizeof(T) * values.size();
+ *(uint32_t*)p->data = type;
+ memcpy((uint32_t*)p->data + 1, values.data(), sizeof(T) * values.size());
+
+ int status = (*mEffectHandle)
+ ->command(mEffectHandle, EFFECT_CMD_SET_PARAM,
+ sizeof(effect_param_t) + p->psize + p->vsize, p, &replySize,
+ &reply);
+ if (status) {
+ return status;
+ }
+ if (reply) {
+ return reply;
+ }
+ return 0;
+ }
+
void process(float* input, float* output);
// Corresponds to SNR for 1 bit difference between two int16_t signals
diff --git a/media/libeffects/visualizer/Android.bp b/media/libeffects/visualizer/Android.bp
index 8dd6789..cf782f7 100644
--- a/media/libeffects/visualizer/Android.bp
+++ b/media/libeffects/visualizer/Android.bp
@@ -18,34 +18,60 @@
],
}
-cc_library_shared {
- name: "libvisualizer",
-
+cc_defaults {
+ name: "visualizer_defaults",
vendor: true,
-
- srcs: [
- "EffectVisualizer.cpp",
- ],
-
cflags: [
- "-O2",
- "-fvisibility=hidden",
-
- "-DBUILD_FLOAT",
+ "-DBUILD_FLOAT", // TODO: remove BUILD_FLOAT and SUPPORT_MC in lvm libs
"-DSUPPORT_MC",
-
"-Wall",
"-Werror",
],
-
shared_libs: [
"liblog",
],
-
- relative_install_path: "soundfx",
-
header_libs: [
"libaudioeffects",
"libaudioutils_headers",
],
}
+
+cc_library_shared {
+ name: "libvisualizer",
+ defaults: [
+ "visualizer_defaults",
+ ],
+ srcs: [
+ "EffectVisualizer.cpp",
+ ],
+ relative_install_path: "soundfx",
+ cflags: [
+ "-O2",
+ "-fvisibility=hidden",
+ ],
+}
+
+cc_library_shared {
+ name: "libvisualizeraidl",
+ srcs: [
+ "aidl/Visualizer.cpp",
+ "aidl/VisualizerContext.cpp",
+ ":effectCommonFile",
+ ],
+ defaults: [
+ "aidlaudioeffectservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "visualizer_defaults",
+ ],
+ cflags: [
+ "-Wthread-safety",
+ ],
+ shared_libs: [
+ "libcutils",
+ ],
+ relative_install_path: "soundfx",
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/media/libeffects/visualizer/aidl/Visualizer.cpp b/media/libeffects/visualizer/aidl/Visualizer.cpp
new file mode 100644
index 0000000..53bfb41
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/Visualizer.cpp
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_VisualizerLibEffects"
+
+#include <android-base/logging.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "Visualizer.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::getEffectImplUuidVisualizer;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::hardware::audio::effect::VisualizerImpl;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidVisualizer()) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<VisualizerImpl>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidVisualizer()) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ *_aidl_return = VisualizerImpl::kDescriptor;
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string VisualizerImpl::kEffectName = "Visualizer";
+const std::vector<Range::VisualizerRange> VisualizerImpl::kRanges = {
+ MAKE_RANGE(Visualizer, latencyMs, 0, VisualizerContext::kMaxLatencyMs),
+ MAKE_RANGE(Visualizer, captureSamples, 0, VisualizerContext::kMaxCaptureBufSize),
+ /* get only parameters, set invalid range (min > max) to indicate not support set */
+ MAKE_RANGE(Visualizer, measurement, Visualizer::Measurement({.peak = 1, .rms = 1}),
+ Visualizer::Measurement({.peak = 0, .rms = 0})),
+ MAKE_RANGE(Visualizer, captureSampleBuffer, std::vector<uint8_t>({1}),
+ std::vector<uint8_t>({0}))};
+const Capability VisualizerImpl::kCapability = {
+ .range = Range::make<Range::visualizer>(VisualizerImpl::kRanges)};
+const Descriptor VisualizerImpl::kDescriptor = {
+ .common = {.id = {.type = getEffectTypeUuidVisualizer(),
+ .uuid = getEffectImplUuidVisualizer(),
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::LAST,
+ .volume = Flags::Volume::CTRL},
+ .name = VisualizerImpl::kEffectName,
+ .implementor = "The Android Open Source Project"},
+ .capability = VisualizerImpl::kCapability};
+
+ndk::ScopedAStatus VisualizerImpl::getDescriptor(Descriptor* _aidl_return) {
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::commandImpl(CommandId command) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (command) {
+ case CommandId::START:
+ mContext->enable();
+ break;
+ case CommandId::STOP:
+ mContext->disable();
+ break;
+ case CommandId::RESET:
+ mContext->disable();
+ mContext->resetBuffer();
+ break;
+ default:
+ LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commandIdNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& param = specific.get<Parameter::Specific::visualizer>();
+ RETURN_IF(!inRange(param, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+ const auto tag = param.getTag();
+ switch (tag) {
+ case Visualizer::captureSamples: {
+ RETURN_IF(mContext->setCaptureSamples(param.get<Visualizer::captureSamples>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setCaptureSizeFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::scalingMode: {
+ RETURN_IF(mContext->setScalingMode(param.get<Visualizer::scalingMode>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setScalingModeFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::measurementMode: {
+ RETURN_IF(mContext->setMeasurementMode(param.get<Visualizer::measurementMode>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setMeasurementModeFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::latencyMs: {
+ RETURN_IF(mContext->setDownstreamLatency(param.get<Visualizer::latencyMs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setLatencyFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "VisualizerTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus VisualizerImpl::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto specificId = id.get<Parameter::Id::visualizerTag>();
+ auto specificTag = specificId.getTag();
+ switch (specificTag) {
+ case Visualizer::Id::commonTag: {
+ return getParameterVisualizer(specificId.get<Visualizer::Id::commonTag>(), specific);
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(specificTag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VisualizerTagNotSupported");
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::getParameterVisualizer(const Visualizer::Tag& tag,
+ Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ Visualizer param;
+ switch (tag) {
+ case Visualizer::captureSamples: {
+ param.set<Visualizer::captureSamples>(mContext->getCaptureSamples());
+ break;
+ }
+ case Visualizer::scalingMode: {
+ param.set<Visualizer::scalingMode>(mContext->getScalingMode());
+ break;
+ }
+ case Visualizer::measurementMode: {
+ param.set<Visualizer::measurementMode>(mContext->getMeasurementMode());
+ break;
+ }
+ case Visualizer::measurement: {
+ param.set<Visualizer::measurement>(mContext->getMeasure());
+ break;
+ }
+ case Visualizer::captureSampleBuffer: {
+ param.set<Visualizer::captureSampleBuffer>(mContext->capture());
+ break;
+ }
+ case Visualizer::latencyMs: {
+ param.set<Visualizer::latencyMs>(mContext->getDownstreamLatency());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "VisualizerTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::visualizer>(param);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> VisualizerImpl::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+
+ mContext = std::make_shared<VisualizerContext>(1 /* statusFmqDepth */, common);
+ mContext->initParams(common);
+ return mContext;
+}
+
+RetCode VisualizerImpl::releaseContext() {
+ if (mContext) {
+ mContext->disable();
+ mContext->resetBuffer();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status VisualizerImpl::effectProcessImpl(float* in, float* out, int samples) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!mContext, status, "nullContext");
+ return mContext->process(in, out, samples);
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/Visualizer.h b/media/libeffects/visualizer/aidl/Visualizer.h
new file mode 100644
index 0000000..ec725db
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/Visualizer.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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 <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "effect-impl/EffectImpl.h"
+
+#include "VisualizerContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class VisualizerImpl final : public EffectImpl {
+ public:
+ static const std::string kEffectName;
+ static const Capability kCapability;
+ static const Descriptor kDescriptor;
+ VisualizerImpl() { LOG(DEBUG) << __func__; }
+ ~VisualizerImpl() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ std::shared_ptr<EffectContext> getContext() override { return mContext; }
+ std::string getEffectName() override { return kEffectName; }
+
+ private:
+ static const std::vector<Range::VisualizerRange> kRanges;
+ std::shared_ptr<VisualizerContext> mContext;
+ ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag,
+ Parameter::Specific* specific);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.cpp b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
new file mode 100644
index 0000000..5d0d08d
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2022 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 "VisualizerContext.h"
+
+#include <algorithm>
+#include <math.h>
+#include <time.h>
+
+#include <android/binder_status.h>
+#include <audio_utils/primitives.h>
+#include <system/audio.h>
+#include <Utils.h>
+
+#ifndef BUILD_FLOAT
+ #error AIDL Visualizer only support float 32bits, make sure add cflags -DBUILD_FLOAT,
+#endif
+
+using aidl::android::hardware::audio::common::getChannelCount;
+
+namespace aidl::android::hardware::audio::effect {
+
+VisualizerContext::VisualizerContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+}
+
+VisualizerContext::~VisualizerContext() {
+ std::lock_guard lg(mMutex);
+ LOG(DEBUG) << __func__;
+ mState = State::UNINITIALIZED;
+}
+
+RetCode VisualizerContext::initParams(const Parameter::Common& common) {
+ std::lock_guard lg(mMutex);
+ LOG(DEBUG) << __func__;
+ if (common.input != common.output) {
+ LOG(ERROR) << __func__ << " mismatch input: " << common.input.toString()
+ << " and output: " << common.output.toString();
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+
+ mState = State::INITIALIZED;
+ auto channelCount = getChannelCount(common.input.base.channelMask);
+#ifdef SUPPORT_MC
+ if (channelCount < 1 || channelCount > FCC_LIMIT) return RetCode::ERROR_ILLEGAL_PARAMETER;
+#else
+ if (channelCount != FCC_2) return RetCode::ERROR_ILLEGAL_PARAMETER;
+#endif
+ mChannelCount = channelCount;
+ mCommon = common;
+ return RetCode::SUCCESS;
+}
+
+RetCode VisualizerContext::enable() {
+ std::lock_guard lg(mMutex);
+ if (mState != State::INITIALIZED) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = State::ACTIVE;
+ return RetCode::SUCCESS;
+}
+
+RetCode VisualizerContext::disable() {
+ std::lock_guard lg(mMutex);
+ if (mState != State::ACTIVE) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = State::INITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+void VisualizerContext::reset() {
+ std::lock_guard lg(mMutex);
+ std::fill_n(mCaptureBuf.begin(), kMaxCaptureBufSize, 0x80);
+}
+
+RetCode VisualizerContext::setCaptureSamples(int samples) {
+ std::lock_guard lg(mMutex);
+ mCaptureSamples = samples;
+ return RetCode::SUCCESS;
+}
+int VisualizerContext::getCaptureSamples() {
+ std::lock_guard lg(mMutex);
+ return mCaptureSamples;
+}
+
+RetCode VisualizerContext::setMeasurementMode(Visualizer::MeasurementMode mode) {
+ std::lock_guard lg(mMutex);
+ mMeasurementMode = mode;
+ return RetCode::SUCCESS;
+}
+Visualizer::MeasurementMode VisualizerContext::getMeasurementMode() {
+ std::lock_guard lg(mMutex);
+ return mMeasurementMode;
+}
+
+RetCode VisualizerContext::setScalingMode(Visualizer::ScalingMode mode) {
+ std::lock_guard lg(mMutex);
+ mScalingMode = mode;
+ return RetCode::SUCCESS;
+}
+Visualizer::ScalingMode VisualizerContext::getScalingMode() {
+ std::lock_guard lg(mMutex);
+ return mScalingMode;
+}
+
+RetCode VisualizerContext::setDownstreamLatency(int latency) {
+ std::lock_guard lg(mMutex);
+ mDownstreamLatency = latency;
+ return RetCode::SUCCESS;
+}
+
+int VisualizerContext::getDownstreamLatency() {
+ std::lock_guard lg(mMutex);
+ return mDownstreamLatency;
+}
+
+uint32_t VisualizerContext::getDeltaTimeMsFromUpdatedTime_l() {
+ uint32_t deltaMs = 0;
+ if (mBufferUpdateTime.tv_sec != 0) {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
+ time_t secs = ts.tv_sec - mBufferUpdateTime.tv_sec;
+ long nsec = ts.tv_nsec - mBufferUpdateTime.tv_nsec;
+ if (nsec < 0) {
+ --secs;
+ nsec += 1000000000;
+ }
+ deltaMs = secs * 1000 + nsec / 1000000;
+ }
+ }
+ return deltaMs;
+}
+
+Visualizer::Measurement VisualizerContext::getMeasure() {
+ uint16_t peakU16 = 0;
+ float sumRmsSquared = 0.0f;
+ uint8_t nbValidMeasurements = 0;
+
+ {
+ std::lock_guard lg(mMutex);
+ // reset measurements if last measurement was too long ago (which implies stored
+ // measurements aren't relevant anymore and shouldn't bias the new one)
+ const uint32_t delayMs = getDeltaTimeMsFromUpdatedTime_l();
+ if (delayMs > kDiscardMeasurementsTimeMs) {
+ LOG(INFO) << __func__ << " Discarding " << delayMs << " ms old measurements";
+ for (uint32_t i = 0; i < mMeasurementWindowSizeInBuffers; i++) {
+ mPastMeasurements[i].mIsValid = false;
+ mPastMeasurements[i].mPeakU16 = 0;
+ mPastMeasurements[i].mRmsSquared = 0;
+ }
+ mMeasurementBufferIdx = 0;
+ } else {
+ // only use actual measurements, otherwise the first RMS measure happening before
+ // MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS have been played will always be artificially
+ // low
+ for (uint32_t i = 0; i < mMeasurementWindowSizeInBuffers; i++) {
+ if (mPastMeasurements[i].mIsValid) {
+ if (mPastMeasurements[i].mPeakU16 > peakU16) {
+ peakU16 = mPastMeasurements[i].mPeakU16;
+ }
+ sumRmsSquared += mPastMeasurements[i].mRmsSquared;
+ nbValidMeasurements++;
+ }
+ }
+ }
+ }
+
+ float rms = nbValidMeasurements == 0 ? 0.0f : sqrtf(sumRmsSquared / nbValidMeasurements);
+ Visualizer::Measurement measure;
+ // convert from I16 sample values to mB and write results
+ measure.rms = (rms < 0.000016f) ? -9600 : (int32_t)(2000 * log10(rms / 32767.0f));
+ measure.peak = (peakU16 == 0) ? -9600 : (int32_t)(2000 * log10(peakU16 / 32767.0f));
+ LOG(INFO) << __func__ << " peak " << peakU16 << " (" << measure.peak << "mB), rms " << rms
+ << " (" << measure.rms << "mB)";
+ return measure;
+}
+
+std::vector<uint8_t> VisualizerContext::capture() {
+ std::vector<uint8_t> result;
+ std::lock_guard lg(mMutex);
+ // cts android.media.audio.cts.VisualizerTest expecting silence data when effect not running
+ // RETURN_VALUE_IF(mState != State::ACTIVE, result, "illegalState");
+ if (mState != State::ACTIVE) {
+ result.resize(mCaptureSamples);
+ memset(result.data(), 0x80, mCaptureSamples);
+ return result;
+ }
+
+ const uint32_t deltaMs = getDeltaTimeMsFromUpdatedTime_l();
+ // if audio framework has stopped playing audio although the effect is still active we must
+ // clear the capture buffer to return silence
+ if ((mLastCaptureIdx == mCaptureIdx) && (mBufferUpdateTime.tv_sec != 0) &&
+ (deltaMs > kMaxStallTimeMs)) {
+ LOG(INFO) << __func__ << " capture going to idle";
+ mBufferUpdateTime.tv_sec = 0;
+ return result;
+ }
+ int32_t latencyMs = mDownstreamLatency;
+ latencyMs -= deltaMs;
+ if (latencyMs < 0) {
+ latencyMs = 0;
+ }
+ uint32_t deltaSamples = mCaptureSamples + mCommon.input.base.sampleRate * latencyMs / 1000;
+
+ // large sample rate, latency, or capture size, could cause overflow.
+ // do not offset more than the size of buffer.
+ if (deltaSamples > kMaxCaptureBufSize) {
+ android_errorWriteLog(0x534e4554, "31781965");
+ deltaSamples = kMaxCaptureBufSize;
+ }
+
+ int32_t capturePoint;
+ //capturePoint = (int32_t)mCaptureIdx - deltaSamples;
+ __builtin_sub_overflow((int32_t) mCaptureIdx, deltaSamples, &capturePoint);
+ // a negative capturePoint means we wrap the buffer.
+ if (capturePoint < 0) {
+ uint32_t size = -capturePoint;
+ if (size > mCaptureSamples) {
+ size = mCaptureSamples;
+ }
+ result.insert(result.end(), &mCaptureBuf[kMaxCaptureBufSize + capturePoint],
+ &mCaptureBuf[kMaxCaptureBufSize + capturePoint + size]);
+ mCaptureSamples -= size;
+ capturePoint = 0;
+ }
+ result.insert(result.end(), &mCaptureBuf[capturePoint],
+ &mCaptureBuf[capturePoint + mCaptureSamples]);
+ mLastCaptureIdx = mCaptureIdx;
+ return result;
+}
+
+IEffect::Status VisualizerContext::process(float* in, float* out, int samples) {
+ IEffect::Status result = {STATUS_NOT_ENOUGH_DATA, 0, 0};
+ RETURN_VALUE_IF(in == nullptr || out == nullptr || samples == 0, result, "dataBufferError");
+
+ std::lock_guard lg(mMutex);
+ result.status = STATUS_INVALID_OPERATION;
+ RETURN_VALUE_IF(mState != State::ACTIVE, result, "stateNotActive");
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+ // perform measurements if needed
+ if (mMeasurementMode == Visualizer::MeasurementMode::PEAK_RMS) {
+ // find the peak and RMS squared for the new buffer
+ float rmsSqAcc = 0;
+ float maxSample = 0.f;
+ for (size_t inIdx = 0; inIdx < (unsigned)samples; ++inIdx) {
+ maxSample = fmax(maxSample, fabs(in[inIdx]));
+ rmsSqAcc += in[inIdx] * in[inIdx];
+ }
+ maxSample *= 1 << 15; // scale to int16_t, with exactly 1 << 15 representing positive num.
+ rmsSqAcc *= 1 << 30; // scale to int16_t * 2
+ mPastMeasurements[mMeasurementBufferIdx] = {
+ .mPeakU16 = (uint16_t)maxSample,
+ .mRmsSquared = rmsSqAcc / samples,
+ .mIsValid = true };
+ if (++mMeasurementBufferIdx >= mMeasurementWindowSizeInBuffers) {
+ mMeasurementBufferIdx = 0;
+ }
+ }
+
+ float fscale; // multiplicative scale
+ if (mScalingMode == Visualizer::ScalingMode::NORMALIZED) {
+ // derive capture scaling factor from peak value in current buffer
+ // this gives more interesting captures for display.
+ float maxSample = 0.f;
+ for (size_t inIdx = 0; inIdx < (unsigned)samples; ) {
+ // we reconstruct the actual summed value to ensure proper normalization
+ // for multichannel outputs (channels > 2 may often be 0).
+ float smp = 0.f;
+ for (int i = 0; i < mChannelCount; ++i) {
+ smp += in[inIdx++];
+ }
+ maxSample = fmax(maxSample, fabs(smp));
+ }
+ if (maxSample > 0.f) {
+ fscale = 0.99f / maxSample;
+ int exp; // unused
+ const float significand = frexp(fscale, &exp);
+ if (significand == 0.5f) {
+ fscale *= 255.f / 256.f; // avoid returning unaltered PCM signal
+ }
+ } else {
+ // scale doesn't matter, the values are all 0.
+ fscale = 1.f;
+ }
+ } else {
+ assert(mScalingMode == Visualizer::ScalingMode::AS_PLAYED);
+ // Note: if channels are uncorrelated, 1/sqrt(N) could be used at the risk of clipping.
+ fscale = 1.f / mChannelCount; // account for summing all the channels together.
+ }
+
+ uint32_t captIdx;
+ uint32_t inIdx;
+ for (inIdx = 0, captIdx = mCaptureIdx; inIdx < (unsigned)samples; captIdx++) {
+ // wrap
+ if (captIdx >= kMaxCaptureBufSize) {
+ captIdx = 0;
+ }
+
+ float smp = 0.f;
+ for (uint32_t i = 0; i < mChannelCount; ++i) {
+ smp += in[inIdx++];
+ }
+ mCaptureBuf[captIdx] = clamp8_from_float(smp * fscale);
+ }
+
+ // the following two should really be atomic, though it probably doesn't
+ // matter much for visualization purposes
+ mCaptureIdx = captIdx;
+ // update last buffer update time stamp
+ if (clock_gettime(CLOCK_MONOTONIC, &mBufferUpdateTime) < 0) {
+ mBufferUpdateTime.tv_sec = 0;
+ }
+
+ // TODO: handle access_mode
+ memcpy(out, in, samples * sizeof(float));
+ return {STATUS_OK, samples, samples};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.h b/media/libeffects/visualizer/aidl/VisualizerContext.h
new file mode 100644
index 0000000..958035f
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 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 <android-base/thread_annotations.h>
+#include <audio_effects/effect_dynamicsprocessing.h>
+
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class VisualizerContext final : public EffectContext {
+ public:
+ static const uint32_t kMaxCaptureBufSize = 65536;
+ static const uint32_t kMaxLatencyMs = 3000; // 3 seconds of latency for audio pipeline
+
+ VisualizerContext(int statusDepth, const Parameter::Common& common);
+ ~VisualizerContext();
+
+ RetCode initParams(const Parameter::Common& common);
+
+ RetCode enable();
+ RetCode disable();
+ // keep all parameters and reset buffer.
+ void reset();
+
+ RetCode setCaptureSamples(int captureSize);
+ int getCaptureSamples();
+ RetCode setMeasurementMode(Visualizer::MeasurementMode mode);
+ Visualizer::MeasurementMode getMeasurementMode();
+ RetCode setScalingMode(Visualizer::ScalingMode mode);
+ Visualizer::ScalingMode getScalingMode();
+ RetCode setDownstreamLatency(int latency);
+ int getDownstreamLatency();
+
+ IEffect::Status process(float* in, float* out, int samples);
+ // Gets the current measurements, measured by process() and consumed by getParameter()
+ Visualizer::Measurement getMeasure();
+ // Gets the latest PCM capture, data captured by process() and consumed by getParameter()
+ std::vector<uint8_t> capture();
+
+ struct BufferStats {
+ bool mIsValid;
+ uint16_t mPeakU16; // the positive peak of the absolute value of the samples in a buffer
+ float mRmsSquared; // the average square of the samples in a buffer
+ };
+
+ enum State {
+ UNINITIALIZED,
+ INITIALIZED,
+ ACTIVE,
+ };
+
+ private:
+ // maximum time since last capture buffer update before resetting capture buffer. This means
+ // that the framework has stopped playing audio and we must start returning silence
+ static const uint32_t kMaxStallTimeMs = 1000;
+ // discard measurements older than this number of ms
+ static const uint32_t kDiscardMeasurementsTimeMs = 2000;
+ // maximum number of buffers for which we keep track of the measurements
+ // note: buffer index is stored in uint8_t
+ static const uint32_t kMeasurementWindowMaxSizeInBuffers = 25;
+
+ // serialize process() and parameter setting
+ std::mutex mMutex;
+ Parameter::Common mCommon GUARDED_BY(mMutex);
+ State mState GUARDED_BY(mMutex) = State::UNINITIALIZED;
+ uint32_t mCaptureIdx GUARDED_BY(mMutex) = 0;
+ uint32_t mLastCaptureIdx GUARDED_BY(mMutex) = 0;
+ Visualizer::ScalingMode mScalingMode GUARDED_BY(mMutex) = Visualizer::ScalingMode::NORMALIZED;
+ struct timespec mBufferUpdateTime GUARDED_BY(mMutex);
+ // capture buf with 8 bits mono PCM samples
+ std::array<uint8_t, kMaxCaptureBufSize> mCaptureBuf GUARDED_BY(mMutex);
+ uint32_t mDownstreamLatency GUARDED_BY(mMutex) = 0;
+ uint32_t mCaptureSamples GUARDED_BY(mMutex) = kMaxCaptureBufSize;
+
+ // to avoid recomputing it every time a buffer is processed
+ uint8_t mChannelCount GUARDED_BY(mMutex) = 0;
+ Visualizer::MeasurementMode mMeasurementMode GUARDED_BY(mMutex) =
+ Visualizer::MeasurementMode::NONE;
+ uint8_t mMeasurementWindowSizeInBuffers = kMeasurementWindowMaxSizeInBuffers;
+ uint8_t mMeasurementBufferIdx GUARDED_BY(mMutex) = 0;
+ std::array<BufferStats, kMeasurementWindowMaxSizeInBuffers> mPastMeasurements;
+ void init_params();
+
+ uint32_t getDeltaTimeMsFromUpdatedTime_l() REQUIRES(mMutex);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/liberror/Android.bp b/media/liberror/Android.bp
index f54d354..5e94b0a 100644
--- a/media/liberror/Android.bp
+++ b/media/liberror/Android.bp
@@ -25,7 +25,7 @@
],
apex_available: [
"//apex_available:platform",
- "com.android.bluetooth",
+ "com.android.btservices",
"com.android.media",
"com.android.media.swcodec",
],
@@ -51,7 +51,7 @@
min_sdk_version: "29",
apex_available: [
"//apex_available:platform",
- "com.android.bluetooth",
+ "com.android.btservices",
"com.android.media",
"com.android.media.swcodec",
],
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 2dd5784..590a7b7 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -304,6 +304,10 @@
cc_library {
name: "libmedia",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+
srcs: [
":mediaextractorservice_aidl",
"IDataSource.cpp",
@@ -356,7 +360,6 @@
shared_libs: [
"android.hidl.token@1.0-utils",
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
"av-types-aidl-cpp",
"liblog",
@@ -381,7 +384,6 @@
export_shared_lib_headers: [
"libaudioclient",
"libbinder",
- "libandroidicu",
//"libsonivox",
"libmedia_omx",
"framework-permission-aidl-cpp",
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 154988d..e191999 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -428,7 +428,7 @@
return reply.readInt32();
}
- status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
+ status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones)
{
ALOGV("getActiveMicrophones");
Parcel data, reply;
@@ -756,7 +756,7 @@
case GET_ACTIVE_MICROPHONES: {
ALOGV("GET_ACTIVE_MICROPHONES");
CHECK_INTERFACE(IMediaRecorder, data, reply);
- std::vector<media::MicrophoneInfo> activeMicrophones;
+ std::vector<media::MicrophoneInfoFw> activeMicrophones;
status_t status = getActiveMicrophones(&activeMicrophones);
reply->writeInt32(status);
if (status != NO_ERROR) {
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 85768bd..5aa9adc 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -898,10 +898,9 @@
}
}
- for (size_t cameraId = 0; cameraId < mCameraIds.size(); ++cameraId) {
+ for (size_t refIndex = 0; refIndex < mCameraIds.size(); ++refIndex) {
+ const int cameraId = mCameraIds[refIndex];
for (size_t j = 0; j < kNumRequiredProfiles; ++j) {
- int refIndex = getRequiredProfileRefIndex(cameraId);
- CHECK(refIndex != -1);
RequiredProfileRefInfo *info =
&mRequiredProfileRefs[refIndex].mRefs[j];
@@ -931,14 +930,14 @@
int index = getCamcorderProfileIndex(cameraId, profile->mQuality);
if (index != -1) {
- ALOGV("Profile quality %d for camera %zu already exists",
+ ALOGV("Profile quality %d for camera %d already exists",
profile->mQuality, cameraId);
CHECK(index == refIndex);
continue;
}
// Insert the new profile
- ALOGV("Add a profile: quality %d=>%d for camera %zu",
+ ALOGV("Add a profile: quality %d=>%d for camera %d",
mCamcorderProfiles[info->mRefProfileIndex]->mQuality,
profile->mQuality, cameraId);
diff --git a/media/libmedia/include/media/CharacterEncodingDetector.h b/media/libmedia/include/media/CharacterEncodingDetector.h
index 62564b1..2acc868 100644
--- a/media/libmedia/include/media/CharacterEncodingDetector.h
+++ b/media/libmedia/include/media/CharacterEncodingDetector.h
@@ -21,9 +21,12 @@
#include "StringArray.h"
-#include "unicode/ucnv.h"
-#include "unicode/ucsdet.h"
-#include "unicode/ustring.h"
+/** Declare opaque structures from ICU4C. */
+struct UConverter;
+typedef struct UConverter UConverter;
+
+struct UCharsetMatch;
+typedef struct UCharsetMatch UCharsetMatch;
namespace android {
diff --git a/media/libmedia/include/media/IMediaRecorder.h b/media/libmedia/include/media/IMediaRecorder.h
index 6e69782..05da5c2 100644
--- a/media/libmedia/include/media/IMediaRecorder.h
+++ b/media/libmedia/include/media/IMediaRecorder.h
@@ -18,8 +18,8 @@
#ifndef ANDROID_IMEDIARECORDER_H
#define ANDROID_IMEDIARECORDER_H
+#include <android/media/MicrophoneInfoFw.h>
#include <binder/IInterface.h>
-#include <media/MicrophoneInfo.h>
#include <system/audio.h>
#include <vector>
@@ -74,7 +74,7 @@
virtual status_t getRoutedDeviceId(audio_port_handle_t *deviceId) = 0;
virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
virtual status_t getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones) = 0;
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) = 0;
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
virtual status_t getPortId(audio_port_handle_t *portId) = 0;
diff --git a/media/libmedia/include/media/MediaRecorderBase.h b/media/libmedia/include/media/MediaRecorderBase.h
index 2b7818d..82ec9c5 100644
--- a/media/libmedia/include/media/MediaRecorderBase.h
+++ b/media/libmedia/include/media/MediaRecorderBase.h
@@ -19,7 +19,6 @@
#define MEDIA_RECORDER_BASE_H_
#include <media/AudioSystem.h>
-#include <media/MicrophoneInfo.h>
#include <media/mediarecorder.h>
#include <android/content/AttributionSourceState.h>
@@ -74,7 +73,7 @@
virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback) = 0;
virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
virtual status_t getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones) = 0;
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) = 0;
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
virtual status_t getPortId(audio_port_handle_t *portId) const = 0;
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index dd18144..602f72e 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -24,7 +24,7 @@
#include <utils/Errors.h>
#include <media/IMediaRecorderClient.h>
#include <media/IMediaDeathNotifier.h>
-#include <media/MicrophoneInfo.h>
+#include <android/media/MicrophoneInfoFw.h>
#include <android/content/AttributionSourceState.h>
namespace android {
@@ -268,7 +268,7 @@
status_t setInputDevice(audio_port_handle_t deviceId);
status_t getRoutedDeviceId(audio_port_handle_t *deviceId);
status_t enableAudioDeviceCallback(bool enabled);
- status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones);
status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
status_t setPreferredMicrophoneFieldDimension(float zoom);
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index cf12c36..bd06fb6 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -884,7 +884,8 @@
return mMediaRecorder->enableAudioDeviceCallback(enabled);
}
-status_t MediaRecorder::getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
+status_t MediaRecorder::getActiveMicrophones(
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones)
{
ALOGV("getActiveMicrophones");
diff --git a/media/libmedia/tests/codeclist/CodecListTest.cpp b/media/libmedia/tests/codeclist/CodecListTest.cpp
index bd2adf7..75adcca 100644
--- a/media/libmedia/tests/codeclist/CodecListTest.cpp
+++ b/media/libmedia/tests/codeclist/CodecListTest.cpp
@@ -18,6 +18,8 @@
#define LOG_TAG "CodecListTest"
#include <utils/Log.h>
+#include <memory>
+
#include <gtest/gtest.h>
#include <binder/Parcel.h>
@@ -194,16 +196,15 @@
}
}
- Parcel *codecInfoParcel = new Parcel();
+ std::unique_ptr<Parcel> codecInfoParcel(new Parcel());
ASSERT_NE(codecInfoParcel, nullptr) << "Unable to create parcel";
- status_t status = info->writeToParcel(codecInfoParcel);
+ status_t status = info->writeToParcel(codecInfoParcel.get());
ASSERT_EQ(status, OK) << "Writing to parcel failed";
codecInfoParcel->setDataPosition(0);
sp<MediaCodecInfo> parcelCodecInfo = info->FromParcel(*codecInfoParcel);
ASSERT_NE(parcelCodecInfo, nullptr) << "CodecInfo from parcel is null";
- delete codecInfoParcel;
EXPECT_STREQ(info->getCodecName(), parcelCodecInfo->getCodecName())
<< "Returned codec name in info doesn't match";
diff --git a/media/libmediahelper/Android.bp b/media/libmediahelper/Android.bp
index 165a8ad..c66861b 100644
--- a/media/libmediahelper/Android.bp
+++ b/media/libmediahelper/Android.bp
@@ -20,7 +20,7 @@
},
apex_available: [
"//apex_available:platform",
- "com.android.bluetooth",
+ "com.android.btservices",
"com.android.media",
"com.android.media.swcodec",
],
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
index 382a920..9a8156e 100644
--- a/media/libmediahelper/AudioParameter.cpp
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -61,6 +61,12 @@
AUDIO_PARAMETER_DEVICE_ADDITIONAL_OUTPUT_DELAY;
const char * const AudioParameter::keyMaxAdditionalOutputDeviceDelay =
AUDIO_PARAMETER_DEVICE_MAX_ADDITIONAL_OUTPUT_DELAY;
+const char * const AudioParameter::keyOffloadCodecAverageBitRate = AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE;
+const char * const AudioParameter::keyOffloadCodecSampleRate = AUDIO_OFFLOAD_CODEC_SAMPLE_RATE;
+const char * const AudioParameter::keyOffloadCodecChannels = AUDIO_OFFLOAD_CODEC_NUM_CHANNEL;
+const char * const AudioParameter::keyOffloadCodecDelaySamples = AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES;
+const char * const AudioParameter::keyOffloadCodecPaddingSamples =
+ AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES;
AudioParameter::AudioParameter(const String8& keyValuePairs)
{
@@ -226,4 +232,9 @@
}
}
+bool AudioParameter::containsKey(const String8& key) const
+{
+ return mParameters.indexOfKey(key) >= 0;
+}
+
} // namespace android
diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h
index 9a6ca8a..41aff7c 100644
--- a/media/libmediahelper/include/media/AudioParameter.h
+++ b/media/libmediahelper/include/media/AudioParameter.h
@@ -107,6 +107,12 @@
static const char * const keyAdditionalOutputDeviceDelay;
static const char * const keyMaxAdditionalOutputDeviceDelay;
+ static const char * const keyOffloadCodecAverageBitRate;
+ static const char * const keyOffloadCodecSampleRate;
+ static const char * const keyOffloadCodecChannels;
+ static const char * const keyOffloadCodecDelaySamples;
+ static const char * const keyOffloadCodecPaddingSamples;
+
String8 toString() const { return toStringImpl(true); }
String8 keysToString() const { return toStringImpl(false); }
@@ -117,6 +123,12 @@
status_t remove(const String8& key);
+ status_t get(const String8& key, int& value) const {
+ return getInt(key, value);
+ }
+ status_t get(const String8& key, float& value) const {
+ return getFloat(key, value);
+ }
status_t get(const String8& key, String8& value) const;
status_t getInt(const String8& key, int& value) const;
status_t getFloat(const String8& key, float& value) const;
@@ -125,6 +137,7 @@
size_t size() const { return mParameters.size(); }
+ bool containsKey(const String8& key) const;
private:
String8 mKeyValuePairs;
KeyedVector <String8, String8> mParameters;
diff --git a/media/libmediametrics/libmediametrics.map.txt b/media/libmediametrics/libmediametrics.map.txt
index c46281a..f37af64 100644
--- a/media/libmediametrics/libmediametrics.map.txt
+++ b/media/libmediametrics/libmediametrics.map.txt
@@ -1,29 +1,29 @@
LIBMEDIAMETRICS_1 {
global:
- mediametrics_addDouble; # apex
- mediametrics_addInt32; # apex
- mediametrics_addInt64; # apex
- mediametrics_addRate; # apex
- mediametrics_count; # apex
- mediametrics_create; # apex
- mediametrics_delete; # apex
- mediametrics_freeCString; # apex
- mediametrics_getAttributes; # apex
- mediametrics_getCString; # apex
- mediametrics_getDouble; # apex
- mediametrics_getInt32; # apex
- mediametrics_getInt64; # apex
- mediametrics_getKey; # apex
- mediametrics_getRate; # apex
- mediametrics_isEnabled; # apex
- mediametrics_readable; # apex
- mediametrics_selfRecord; # apex
- mediametrics_setCString; # apex
- mediametrics_setDouble; # apex
- mediametrics_setInt32; # apex
- mediametrics_setInt64; # apex
- mediametrics_setRate; # apex
- mediametrics_setUid; # apex
+ mediametrics_addDouble; # systemapi
+ mediametrics_addInt32; # systemapi
+ mediametrics_addInt64; # systemapi
+ mediametrics_addRate; # systemapi
+ mediametrics_count; # systemapi
+ mediametrics_create; # systemapi
+ mediametrics_delete; # systemapi
+ mediametrics_freeCString; # systemapi
+ mediametrics_getAttributes; # systemapi
+ mediametrics_getCString; # systemapi
+ mediametrics_getDouble; # systemapi
+ mediametrics_getInt32; # systemapi
+ mediametrics_getInt64; # systemapi
+ mediametrics_getKey; # systemapi
+ mediametrics_getRate; # systemapi
+ mediametrics_isEnabled; # systemapi
+ mediametrics_readable; # systemapi
+ mediametrics_selfRecord; # systemapi
+ mediametrics_setCString; # systemapi
+ mediametrics_setDouble; # systemapi
+ mediametrics_setInt32; # systemapi
+ mediametrics_setInt64; # systemapi
+ mediametrics_setRate; # systemapi
+ mediametrics_setUid; # systemapi
local:
*;
};
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 8e19d02..fdcf246 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -2683,7 +2683,7 @@
// This is a benign busy-wait, with the next data request generated 10 ms or more later;
// nevertheless for power reasons, we don't want to see too many of these.
- ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned");
+ ALOGV_IF(actualSize == 0 && buffer.size() > 0, "callbackwrapper: empty buffer returned");
unlock();
return actualSize;
}
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 4aa80be..58fc06d 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -563,7 +563,7 @@
}
status_t MediaRecorderClient::getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones) {
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
ALOGV("getActiveMicrophones");
Mutex::Autolock lock(mLock);
if (mRecorder != NULL) {
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index dcb9f82..dec0c99 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -83,7 +83,7 @@
virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
virtual status_t enableAudioDeviceCallback(bool enabled);
virtual status_t getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones);
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones);
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
virtual status_t setPreferredMicrophoneFieldDimension(float zoom);
status_t getPortId(audio_port_handle_t *portId) override;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 6497b58..ec79b99 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -2576,7 +2576,7 @@
}
status_t StagefrightRecorder::getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones) {
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
if (mAudioSourceNode != 0) {
return mAudioSourceNode->getActiveMicrophones(activeMicrophones);
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 0801101..0b6a5bb 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -83,7 +83,7 @@
virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
virtual status_t enableAudioDeviceCallback(bool enabled);
- virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones);
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
virtual status_t setPreferredMicrophoneFieldDimension(float zoom);
status_t getPortId(audio_port_handle_t *portId) const override;
diff --git a/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp b/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
index b0040fe..43b3c37 100644
--- a/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
+++ b/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
@@ -193,7 +193,7 @@
mStfRecorder->setInputDevice(deviceId);
mStfRecorder->getRoutedDeviceId(&deviceId);
- vector<android::media::MicrophoneInfo> activeMicrophones{};
+ vector<android::media::MicrophoneInfoFw> activeMicrophones{};
mStfRecorder->getActiveMicrophones(&activeMicrophones);
int32_t portId;
diff --git a/media/libmediaplayerservice/nuplayer/Android.bp b/media/libmediaplayerservice/nuplayer/Android.bp
index 71a3168..911463b 100644
--- a/media/libmediaplayerservice/nuplayer/Android.bp
+++ b/media/libmediaplayerservice/nuplayer/Android.bp
@@ -17,6 +17,14 @@
],
}
+cc_library_headers {
+ name: "libstagefright_nuplayer_headers",
+
+ export_include_dirs: [
+ "include",
+ ],
+}
+
cc_library_static {
srcs: [
@@ -81,6 +89,7 @@
static_libs: [
"libplayerservice_datasource",
+ "libstagefright_esds",
"libstagefright_timedtext",
],
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 9b4fc8f..d205990 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -60,7 +60,7 @@
#include <gui/Surface.h>
-#include "ESDS.h"
+#include <media/esds/ESDS.h>
#include <media/stagefright/Utils.h>
namespace android {
@@ -1220,7 +1220,11 @@
notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
} else {
// Only audio track has error. Video track could be still good to play.
- notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_AUDIO_ERROR, err);
+ if (mVideoEOS) {
+ notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
+ } else {
+ notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_AUDIO_ERROR, err);
+ }
}
mAudioDecoderError = true;
} else {
@@ -1231,7 +1235,11 @@
notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
} else {
// Only video track has error. Audio track could be still good to play.
- notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_VIDEO_ERROR, err);
+ if (mAudioEOS) {
+ notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
+ } else {
+ notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_VIDEO_ERROR, err);
+ }
}
mVideoDecoderError = true;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
index 5e29b3f..a964d4f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
@@ -22,14 +22,13 @@
#include <mediadrm/DrmUtils.h>
#include <utils/Log.h>
-
namespace android {
// static helpers - internal
sp<IDrm> NuPlayerDrm::CreateDrm(status_t *pstatus)
{
- return DrmUtils::MakeDrm(pstatus);
+ return DrmUtils::MakeDrm(IDRM_NUPLAYER, pstatus);
}
sp<ICrypto> NuPlayerDrm::createCrypto(status_t *pstatus)
diff --git a/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp b/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp
index 162c187..9514021 100644
--- a/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp
+++ b/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp
@@ -286,7 +286,7 @@
// Record media for 4 secs
std::this_thread::sleep_for(std::chrono::seconds(kClipDurationInSec));
- std::vector<media::MicrophoneInfo> activeMicrophones{};
+ std::vector<media::MicrophoneInfoFw> activeMicrophones{};
status = mStfRecorder->getActiveMicrophones(&activeMicrophones);
ASSERT_EQ(status, OK) << "Failed to get Active Microphones";
ASSERT_GT(activeMicrophones.size(), 0) << "No active microphones are found";
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 52c4c0f..ccbe995 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -785,7 +785,7 @@
// we cannot change the number of output buffers while OMX is running
// set up surface to the same count
- Vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput];
+ std::vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput];
ALOGV("setting up surface for %zu buffers", buffers.size());
err = native_window_set_buffer_count(nativeWindow, buffers.size());
@@ -825,7 +825,7 @@
// cancel undequeued buffers to new surface
if (!storingMetadataInDecodedBuffers()) {
for (size_t i = 0; i < buffers.size(); ++i) {
- BufferInfo &info = buffers.editItemAt(i);
+ BufferInfo &info = buffers[i];
if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
ALOGV("canceling buffer %p", info.mGraphicBuffer->getNativeBuffer());
err = nativeWindow->cancelBuffer(
@@ -872,7 +872,7 @@
CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
CHECK(mAllocator[portIndex] == NULL);
- CHECK(mBuffers[portIndex].isEmpty());
+ CHECK(mBuffers[portIndex].empty());
status_t err;
if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
@@ -951,6 +951,7 @@
const sp<AMessage> &format =
portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
+ mBuffers[portIndex].reserve(def.nBufferCountActual);
for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
hidl_memory hidlMemToken;
sp<TMemory> hidlMem;
@@ -1039,7 +1040,7 @@
}
}
- mBuffers[portIndex].push(info);
+ mBuffers[portIndex].push_back(info);
}
}
}
@@ -1250,6 +1251,7 @@
mComponentName.c_str(), bufferCount, bufferSize);
// Dequeue buffers and send them to OMX
+ mBuffers[kPortIndexOutput].reserve(bufferCount);
for (OMX_U32 i = 0; i < bufferCount; i++) {
ANativeWindowBuffer *buf;
int fenceFd;
@@ -1275,7 +1277,7 @@
info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize));
info.mCodecData = info.mData;
- mBuffers[kPortIndexOutput].push(info);
+ mBuffers[kPortIndexOutput].push_back(info);
IOMX::buffer_id bufferId;
err = mOMXNode->useBuffer(kPortIndexOutput, graphicBuffer, &bufferId);
@@ -1285,7 +1287,7 @@
break;
}
- mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
+ mBuffers[kPortIndexOutput][i].mBufferID = bufferId;
ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)",
mComponentName.c_str(),
@@ -1307,7 +1309,7 @@
}
for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
- BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
+ BufferInfo *info = &mBuffers[kPortIndexOutput][i];
if (info->mStatus == BufferInfo::OWNED_BY_US) {
status_t error = cancelBufferToNativeWindow(info);
if (err == 0) {
@@ -1336,6 +1338,7 @@
ALOGV("[%s] Allocating %u meta buffers on output port",
mComponentName.c_str(), bufferCount);
+ mBuffers[kPortIndexOutput].reserve(bufferCount);
for (OMX_U32 i = 0; i < bufferCount; i++) {
BufferInfo info;
info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
@@ -1353,7 +1356,7 @@
info.mCodecData = info.mData;
err = mOMXNode->useBuffer(kPortIndexOutput, OMXBuffer::sPreset, &info.mBufferID);
- mBuffers[kPortIndexOutput].push(info);
+ mBuffers[kPortIndexOutput].push_back(info);
ALOGV("[%s] allocated meta buffer with ID %u",
mComponentName.c_str(), info.mBufferID);
@@ -1462,7 +1465,7 @@
it != done.cend(); ++it) {
ssize_t index = it->getIndex();
if (index >= 0 && (size_t)index < mBuffers[kPortIndexOutput].size()) {
- mBuffers[kPortIndexOutput].editItemAt(index).mRenderInfo = NULL;
+ mBuffers[kPortIndexOutput][index].mRenderInfo = NULL;
} else if (index >= 0) {
// THIS SHOULD NEVER HAPPEN
ALOGE("invalid index %zd in %zu", index, mBuffers[kPortIndexOutput].size());
@@ -1502,7 +1505,7 @@
bool stale = false;
for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
i--;
- BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
+ BufferInfo *info = &mBuffers[kPortIndexOutput][i];
if (info->mGraphicBuffer != NULL &&
info->mGraphicBuffer->handle == buf->handle) {
@@ -1550,8 +1553,7 @@
BufferInfo *oldest = NULL;
for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
i--;
- BufferInfo *info =
- &mBuffers[kPortIndexOutput].editItemAt(i);
+ BufferInfo *info = &mBuffers[kPortIndexOutput][i];
if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
(oldest == NULL ||
// avoid potential issues from counter rolling over
@@ -1608,8 +1610,7 @@
status_t err = OK;
for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
i--;
- BufferInfo *info =
- &mBuffers[kPortIndexOutput].editItemAt(i);
+ BufferInfo *info = &mBuffers[kPortIndexOutput][i];
// At this time some buffers may still be with the component
// or being drained.
@@ -1626,7 +1627,7 @@
}
status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
- BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
+ BufferInfo *info = &mBuffers[portIndex][i];
status_t err = OK;
// there should not be any fences in the metadata
@@ -1666,14 +1667,14 @@
}
// remove buffer even if mOMXNode->freeBuffer fails
- mBuffers[portIndex].removeAt(i);
+ mBuffers[portIndex].erase(mBuffers[portIndex].begin() + i);
return err;
}
ACodec::BufferInfo *ACodec::findBufferByID(
uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index) {
for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
- BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
+ BufferInfo *info = &mBuffers[portIndex][i];
if (info->mBufferID == bufferID) {
if (index != NULL) {
@@ -5102,7 +5103,7 @@
size_t n = 0;
for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
- const BufferInfo &info = mBuffers[portIndex].itemAt(i);
+ const BufferInfo &info = mBuffers[portIndex][i];
if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
++n;
@@ -5116,7 +5117,7 @@
size_t n = 0;
for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
- const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
+ const BufferInfo &info = mBuffers[kPortIndexOutput][i];
if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
++n;
@@ -5143,7 +5144,7 @@
bool ACodec::allYourBuffersAreBelongToUs(
OMX_U32 portIndex) {
for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
- BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
+ BufferInfo *info = &mBuffers[portIndex][i];
if (info->mStatus != BufferInfo::OWNED_BY_US
&& info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
@@ -5167,12 +5168,11 @@
}
void ACodec::processDeferredMessages() {
- List<sp<AMessage> > queue = mDeferredQueue;
+ std::list<sp<AMessage>> queue = mDeferredQueue;
mDeferredQueue.clear();
- List<sp<AMessage> >::iterator it = queue.begin();
- while (it != queue.end()) {
- onMessageReceived(*it++);
+ for(const sp<AMessage> &msg : queue) {
+ onMessageReceived(msg);
}
}
@@ -5928,19 +5928,17 @@
case ACodec::kWhatSetSurface:
{
+ sp<AReplyToken> replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
sp<RefBase> obj;
CHECK(msg->findObject("surface", &obj));
status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get()));
- sp<AReplyToken> replyID;
- if (msg->senderAwaitsResponse(&replyID)) {
- sp<AMessage> response = new AMessage;
- response->setInt32("err", err);
- response->postReply(replyID);
- } else if (err != OK) {
- mCodec->signalError(OMX_ErrorUndefined, err);
- }
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", err);
+ response->postReply(replyID);
break;
}
@@ -6483,7 +6481,7 @@
BufferInfo *eligible = NULL;
for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
- BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
+ BufferInfo *info = &mCodec->mBuffers[kPortIndexInput][i];
#if 0
if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
@@ -6753,6 +6751,8 @@
info->checkReadFence("onOutputBufferDrained before queueBuffer");
err = mCodec->mNativeWindow->queueBuffer(
mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
+ // TODO(b/266211548): Poll the native window for rendered buffers, since when queueing
+ // buffers, the frame event history delta is retrieved.
info->mFenceFd = -1;
if (err == OK) {
info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
@@ -7515,7 +7515,7 @@
// submit as many buffers as there are input buffers with the codec
// in case we are in port reconfiguring
for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
- BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
+ BufferInfo *info = &mCodec->mBuffers[kPortIndexInput][i];
if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
if (mCodec->submitOutputMetadataBuffer() != OK)
@@ -7533,7 +7533,7 @@
void ACodec::ExecutingState::submitRegularOutputBuffers() {
bool failed = false;
for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
- BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
+ BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput][i];
if (mCodec->mNativeWindow != NULL) {
if (info->mStatus != BufferInfo::OWNED_BY_US
@@ -7590,7 +7590,7 @@
}
for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
- BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
+ BufferInfo *info = &mCodec->mBuffers[kPortIndexInput][i];
if (info->mStatus == BufferInfo::OWNED_BY_US) {
postFillThisBuffer(info);
}
@@ -8529,17 +8529,11 @@
case kWhatSetSurface:
{
- ALOGV("[%s] Deferring setSurface", mCodec->mComponentName.c_str());
-
- sp<AReplyToken> replyID;
- CHECK(msg->senderAwaitsResponse(&replyID));
+ ALOGD("[%s] Deferring setSurface from OutputPortSettingsChangedState",
+ mCodec->mComponentName.c_str());
mCodec->deferMessage(msg);
- sp<AMessage> response = new AMessage;
- response->setInt32("err", OK);
- response->postReply(replyID);
-
handled = true;
break;
}
@@ -8594,7 +8588,7 @@
ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str());
status_t err = OK;
- if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) {
+ if (!mCodec->mBuffers[kPortIndexOutput].empty()) {
ALOGE("disabled port should be empty, but has %zu buffers",
mCodec->mBuffers[kPortIndexOutput].size());
err = FAILED_TRANSACTION;
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index 88b15ae..529ae97 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -477,6 +477,10 @@
return OK;
}
+void ACodecBufferChannel::pollForRenderedBuffers() {
+ // TODO(b/266211548): Poll the native window for rendered buffers.
+}
+
status_t ACodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {
std::shared_ptr<const std::vector<const BufferInfo>> array(
std::atomic_load(&mInputBuffers));
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 10baec4..32e40c3 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -33,75 +33,6 @@
},
}
-cc_library_static {
- name: "libstagefright_esds",
- apex_available: [
- "//apex_available:platform",
- "com.android.media",
- ],
- min_sdk_version: "29",
-
- srcs: ["ESDS.cpp"],
-
- cflags: [
- "-Werror",
- "-Wall",
- ],
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- ],
- cfi: true,
- },
- shared_libs: [
- "libstagefright_foundation",
- "libutils"
- ],
- host_supported: true,
- target: {
- darwin: {
- enabled: false,
- },
- },
-}
-
-cc_library_static {
- name: "libstagefright_metadatautils",
- apex_available: [
- "//apex_available:platform",
- "com.android.media",
- ],
- min_sdk_version: "29",
-
- srcs: ["MetaDataUtils.cpp"],
-
- cflags: [
- "-Werror",
- "-Wall",
- ],
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- ],
- cfi: true,
- },
-
- header_libs: [
- "libaudioclient_headers",
- "libstagefright_foundation_headers",
- "media_ndk_headers",
- ],
-
- host_supported: true,
- target: {
- darwin: {
- enabled: false,
- },
- },
-
- export_include_dirs: ["include"],
-}
-
cc_library_shared {
name: "libstagefright_codecbase",
@@ -166,6 +97,10 @@
"liblog",
],
+ static_libs: [
+ "libstagefright_esds",
+ ],
+
export_include_dirs: [
"include",
],
@@ -220,6 +155,7 @@
"libEGL",
"libGLESv1_CM",
"libGLESv2",
+ "libvulkan",
"libgui",
"liblog",
"libprocessgroup",
@@ -365,7 +301,6 @@
"libstagefright_codecbase",
"libstagefright_foundation",
"libstagefright_omx_utils",
- "libRScpp",
"libhidlallocatorutils",
"libhidlbase",
"libhidlmemory",
@@ -382,11 +317,9 @@
"libstagefright_esds",
"libstagefright_color_conversion",
"libyuv_static",
- "libstagefright_mediafilter",
"libstagefright_webm",
"libstagefright_timedtext",
"libogg",
- "libwebm",
"libstagefright_id3",
"framework-permission-aidl-cpp",
"libmediandk_format",
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index bfe8538..584dad6 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -522,7 +522,7 @@
}
status_t AudioSource::getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones) {
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
if (mRecord != 0) {
return mRecord->getActiveMicrophones(activeMicrophones);
}
diff --git a/media/libstagefright/DataConverter.cpp b/media/libstagefright/DataConverter.cpp
index 52be054..b53ac77 100644
--- a/media/libstagefright/DataConverter.cpp
+++ b/media/libstagefright/DataConverter.cpp
@@ -24,6 +24,10 @@
#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AUtils.h>
+#include <system/audio.h>
+#include <audio_utils/primitives.h>
+#include <audio_utils/format.h>
+
namespace android {
@@ -81,12 +85,38 @@
return numSamples * mTargetSampleSize;
}
+static audio_format_t getAudioFormat(AudioEncoding e) {
+ audio_format_t format = AUDIO_FORMAT_INVALID;
+ switch (e) {
+ case kAudioEncodingPcm16bit:
+ format = AUDIO_FORMAT_PCM_16_BIT;
+ break;
+ case kAudioEncodingPcm8bit:
+ format = AUDIO_FORMAT_PCM_8_BIT;
+ break;
+ case kAudioEncodingPcmFloat:
+ format = AUDIO_FORMAT_PCM_FLOAT;
+ break;
+ case kAudioEncodingPcm24bitPacked:
+ format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
+ break;
+ case kAudioEncodingPcm32bit:
+ format = AUDIO_FORMAT_PCM_32_BIT;
+ break;
+ default:
+ ALOGE("Invalid AudioEncoding %d", e);
+ }
+ return format;
+}
static size_t getAudioSampleSize(AudioEncoding e) {
switch (e) {
- case kAudioEncodingPcm16bit: return 2;
- case kAudioEncodingPcm8bit: return 1;
- case kAudioEncodingPcmFloat: return 4;
+ case kAudioEncodingPcm16bit:
+ case kAudioEncodingPcm8bit:
+ case kAudioEncodingPcmFloat:
+ case kAudioEncodingPcm24bitPacked:
+ case kAudioEncodingPcm32bit:
+ return audio_bytes_per_sample(getAudioFormat(e));
default: return 0;
}
}
@@ -116,7 +146,15 @@
} else if (mTo == kAudioEncodingPcmFloat && mFrom == kAudioEncodingPcm16bit) {
memcpy_to_float_from_i16((float*)tgt->base(), (const int16_t*)src->data(), src->size() / 2);
} else {
- return INVALID_OPERATION;
+ audio_format_t srcFormat = getAudioFormat(mFrom);
+ audio_format_t dstFormat = getAudioFormat(mTo);
+
+ if ((srcFormat == AUDIO_FORMAT_INVALID) || (dstFormat == AUDIO_FORMAT_INVALID))
+ return INVALID_OPERATION;
+
+ size_t frames = src->size() / audio_bytes_per_sample(srcFormat);
+ memcpy_by_audio_format((void*)tgt->base(), dstFormat, (void*)src->data(),
+ srcFormat, frames);
}
return OK;
}
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 344456c..42815b3 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -352,6 +352,10 @@
status_t err = OK;
bool done = false;
size_t retriesLeft = kRetryCount;
+ if (!mDecoder) {
+ ALOGE("decoder is not initialized");
+ return NO_INIT;
+ }
do {
size_t index;
int64_t ptsUs = 0LL;
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 34b840e..fbc684b 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -30,7 +30,7 @@
#include <media/stagefright/MetaData.h>
#include <arpa/inet.h>
-#include "include/ESDS.h"
+#include <media/esds/ESDS.h>
namespace android {
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 63d3180..386b790 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -51,7 +51,7 @@
#include <media/mediarecorder.h>
#include <cutils/properties.h>
-#include "include/ESDS.h"
+#include <media/esds/ESDS.h>
#include "include/HevcUtils.h"
#ifndef __predict_false
diff --git a/media/libstagefright/MediaAppender.cpp b/media/libstagefright/MediaAppender.cpp
index 21dcfa1..2d9c651 100644
--- a/media/libstagefright/MediaAppender.cpp
+++ b/media/libstagefright/MediaAppender.cpp
@@ -308,7 +308,11 @@
ALOGE("MediaAppender::start() is called in invalid state %d", mState);
return INVALID_OPERATION;
}
- mMuxer = new (std::nothrow) MediaMuxer(mFd, mFormat);
+ mMuxer = MediaMuxer::create(mFd, mFormat);
+ if (mMuxer == nullptr) {
+ ALOGE("MediaMuxer::create failed");
+ return INVALID_OPERATION;
+ }
for (const auto& n : mFmtIndexMap) {
ssize_t muxIndex = mMuxer->addTrack(n.second);
if (muxIndex < 0) {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 3044c20..9b8cc5e 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -75,7 +75,6 @@
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MediaFilter.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/PersistentSurface.h>
#include <media/stagefright/SurfaceUtils.h>
@@ -89,6 +88,7 @@
using aidl::android::media::BnResourceManagerClient;
using aidl::android::media::IResourceManagerClient;
using aidl::android::media::IResourceManagerService;
+using aidl::android::media::ClientInfoParcel;
// key for media statistics
static const char *kCodecKeyName = "codec";
@@ -210,8 +210,8 @@
////////////////////////////////////////////////////////////////////////////////
struct ResourceManagerClient : public BnResourceManagerClient {
- explicit ResourceManagerClient(MediaCodec* codec, int32_t pid) :
- mMediaCodec(codec), mPid(pid) {}
+ explicit ResourceManagerClient(MediaCodec* codec, int32_t pid, int32_t uid) :
+ mMediaCodec(codec), mPid(pid), mUid(uid) {}
Status reclaimResource(bool* _aidl_return) override {
sp<MediaCodec> codec = mMediaCodec.promote();
@@ -223,7 +223,10 @@
if (service == nullptr) {
ALOGW("MediaCodec::ResourceManagerClient unable to find ResourceManagerService");
}
- service->removeClient(mPid, getId(this));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(this)};
+ service->removeClient(clientInfo);
*_aidl_return = true;
return Status::ok();
}
@@ -261,6 +264,7 @@
private:
wp<MediaCodec> mMediaCodec;
int32_t mPid;
+ int32_t mUid;
DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient);
};
@@ -286,10 +290,15 @@
void markClientForPendingRemoval();
bool reclaimResource(const std::vector<MediaResourceParcel> &resources);
+ inline void setCodecName(const char* name) {
+ mCodecName = name;
+ }
+
private:
Mutex mLock;
pid_t mPid;
uid_t mUid;
+ std::string mCodecName;
std::shared_ptr<IResourceManagerService> mService;
std::shared_ptr<IResourceManagerClient> mClient;
::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
@@ -396,7 +405,11 @@
if (mService == nullptr) {
return;
}
- mService->addResource(mPid, mUid, getId(mClient), mClient, resources);
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(mClient),
+ .name = mCodecName};
+ mService->addResource(clientInfo, mClient, resources);
}
void MediaCodec::ResourceManagerServiceProxy::removeResource(
@@ -408,7 +421,11 @@
if (mService == nullptr) {
return;
}
- mService->removeResource(mPid, getId(mClient), resources);
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(mClient),
+ .name = mCodecName};
+ mService->removeResource(clientInfo, resources);
}
void MediaCodec::ResourceManagerServiceProxy::removeClient() {
@@ -416,7 +433,11 @@
if (mService == nullptr) {
return;
}
- mService->removeClient(mPid, getId(mClient));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(mClient),
+ .name = mCodecName};
+ mService->removeClient(clientInfo);
}
void MediaCodec::ResourceManagerServiceProxy::markClientForPendingRemoval() {
@@ -424,7 +445,11 @@
if (mService == nullptr) {
return;
}
- mService->markClientForPendingRemoval(mPid, getId(mClient));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(mClient),
+ .name = mCodecName};
+ mService->markClientForPendingRemoval(clientInfo);
}
bool MediaCodec::ResourceManagerServiceProxy::reclaimResource(
@@ -434,7 +459,11 @@
return false;
}
bool success;
- Status status = mService->reclaimResource(mPid, resources, &success);
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(mClient),
+ .name = mCodecName};
+ Status status = mService->reclaimResource(clientInfo, resources, &success);
return status.isOk() && success;
}
@@ -504,6 +533,7 @@
kWhatOutputFramesRendered = 'outR',
kWhatOutputBuffersChanged = 'outC',
kWhatFirstTunnelFrameReady = 'ftfR',
+ kWhatPollForRenderedBuffers = 'plrb',
};
class BufferCallback : public CodecBase::BufferCallback {
@@ -837,7 +867,7 @@
mGetCodecBase(getCodecBase),
mGetCodecInfo(getCodecInfo) {
mResourceManagerProxy = new ResourceManagerServiceProxy(pid, uid,
- ::ndk::SharedRefBase::make<ResourceManagerClient>(this, pid));
+ ::ndk::SharedRefBase::make<ResourceManagerClient>(this, pid, uid));
if (!mGetCodecBase) {
mGetCodecBase = [](const AString &name, const char *owner) {
return GetCodecBase(name, owner);
@@ -1565,8 +1595,6 @@
} else if (name.startsWithIgnoreCase("omx.")) {
// at this time only ACodec specifies a mime type.
return new ACodec;
- } else if (name.startsWithIgnoreCase("android.filter.")) {
- return new MediaFilter;
} else {
return NULL;
}
@@ -1696,6 +1724,11 @@
std::vector<MediaResourceParcel> resources;
resources.push_back(MediaResource::CodecResource(secureCodec, toMediaResourceSubType(mDomain)));
+
+ // If the ComponentName is not set yet, use the name passed by the user.
+ if (mComponentName.empty()) {
+ mResourceManagerProxy->setCodecName(name.c_str());
+ }
for (int i = 0; i <= kMaxRetry; ++i) {
if (i > 0) {
// Don't try to reclaim resource for the first time.
@@ -3459,6 +3492,8 @@
if (mComponentName.c_str()) {
mediametrics_setCString(mMetricsHandle, kCodecCodec,
mComponentName.c_str());
+ // Update the codec name.
+ mResourceManagerProxy->setCodecName(mComponentName.c_str());
}
const char *owner = mCodecInfo ? mCodecInfo->getOwnerName() : "";
@@ -3481,8 +3516,8 @@
MediaCodecInfo::Attributes attr = mCodecInfo
? mCodecInfo->getAttributes()
: MediaCodecInfo::Attributes(0);
- if (!(attr & MediaCodecInfo::kFlagIsSoftwareOnly)) {
- // software codec is currently ignored.
+ if (mDomain == DOMAIN_VIDEO || !(attr & MediaCodecInfo::kFlagIsSoftwareOnly)) {
+ // software audio codecs are currently ignored.
mResourceManagerProxy->addResource(MediaResource::CodecResource(
mFlags & kFlagIsSecure, toMediaResourceSubType(mDomain)));
}
@@ -4610,6 +4645,14 @@
break;
}
+ case kWhatPollForRenderedBuffers:
+ {
+ if (isExecuting()) {
+ mBufferChannel->pollForRenderedBuffers();
+ }
+ break;
+ }
+
case kWhatSignalEndOfInputStream:
{
if (!isExecuting() || !mHaveInputSurface) {
@@ -4841,7 +4884,7 @@
// rendering.
int32_t dataSpace;
if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) {
- ALOGD("[%s] setting dataspace on output surface to #%x",
+ ALOGD("[%s] setting dataspace on output surface to %#x",
mComponentName.c_str(), dataSpace);
int err = native_window_set_buffers_data_space(
mSurface.get(), (android_dataspace)dataSpace);
@@ -5323,7 +5366,6 @@
size_t MediaCodec::CreateFramesRenderedMessage(
const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) {
size_t index = 0;
-
for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
it != done.cend(); ++it) {
if (it->getRenderTimeNs() < 0) {
@@ -5372,11 +5414,13 @@
int64_t mediaTimeUs = -1;
buffer->meta()->findInt64("timeUs", &mediaTimeUs);
+ bool noRenderTime = false;
int64_t renderTimeNs = 0;
if (!msg->findInt64("timestampNs", &renderTimeNs)) {
// use media timestamp if client did not request a specific render timestamp
ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);
renderTimeNs = mediaTimeUs * 1000;
+ noRenderTime = true;
}
if (mSoftRenderer != NULL) {
@@ -5394,6 +5438,29 @@
}
}
}
+
+ // If rendering to the screen, then schedule a time in the future to poll to see if this
+ // frame was ever rendered to seed onFrameRendered callbacks.
+ if (mIsSurfaceToScreen) {
+ // can't initialize this in the constructor because the Looper parent class needs to be
+ // initialized first
+ if (mMsgPollForRenderedBuffers == nullptr) {
+ mMsgPollForRenderedBuffers = new AMessage(kWhatPollForRenderedBuffers, this);
+ }
+ // Schedule the poll to occur 100ms after the render time - should be safe for
+ // determining if the frame was ever rendered. If no render time was specified, the
+ // presentation timestamp is used instead, which almost certainly occurs in the past,
+ // since it's almost always a zero-based offset from the start of the stream. In these
+ // scenarios, we expect the frame to be rendered with no delay.
+ int64_t delayUs = noRenderTime ? 0 : renderTimeNs / 1000 - ALooper::GetNowUs();
+ delayUs += 100 * 1000; /* 100ms in microseconds */
+ status_t err =
+ mMsgPollForRenderedBuffers->postUnique(/* token= */ mMsgPollForRenderedBuffers,
+ delayUs);
+ if (err != OK) {
+ ALOGE("unexpected failure to post pollForRenderedBuffers: %d", err);
+ }
+ }
status_t err = mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
if (err == NO_INIT) {
@@ -5413,7 +5480,7 @@
MediaCodec::BufferInfo *MediaCodec::peekNextPortBuffer(int32_t portIndex) {
CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
- List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
+ std::list<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
if (availBuffers->empty()) {
return nullptr;
@@ -5430,7 +5497,7 @@
return -EAGAIN;
}
- List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
+ std::list<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
size_t index = *availBuffers->begin();
CHECK_EQ(info, &mPortBuffers[portIndex][index]);
availBuffers->erase(availBuffers->begin());
@@ -5635,6 +5702,9 @@
}
status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) {
+ if (mState == UNINITIALIZED || mState == INITIALIZING) {
+ return NO_INIT;
+ }
updateLowLatency(params);
mapFormat(mComponentName, params, nullptr, false);
updateTunnelPeek(params);
diff --git a/media/libstagefright/MediaMuxer.cpp b/media/libstagefright/MediaMuxer.cpp
index a946f71..9f590e5 100644
--- a/media/libstagefright/MediaMuxer.cpp
+++ b/media/libstagefright/MediaMuxer.cpp
@@ -46,6 +46,30 @@
format == MediaMuxer::OUTPUT_FORMAT_HEIF;
}
+MediaMuxer* MediaMuxer::create(int fd, OutputFormat format) {
+ bool isInputValid = true;
+ if (isMp4Format(format)) {
+ isInputValid = MPEG4Writer::isFdOpenModeValid(fd);
+ } else if (format == OUTPUT_FORMAT_WEBM) {
+ isInputValid = WebmWriter::isFdOpenModeValid(fd);
+ } else if (format == OUTPUT_FORMAT_OGG) {
+ isInputValid = OggWriter::isFdOpenModeValid(fd);
+ } else {
+ ALOGE("MediaMuxer does not support output format %d", format);
+ return nullptr;
+ }
+ if (!isInputValid) {
+ ALOGE("File descriptor is not suitable for format %d", format);
+ return nullptr;
+ }
+
+ MediaMuxer *muxer = new (std::nothrow) MediaMuxer(fd, (MediaMuxer::OutputFormat)format);
+ if (muxer == nullptr) {
+ ALOGE("Failed to create writer object");
+ }
+ return muxer;
+}
+
MediaMuxer::MediaMuxer(int fd, OutputFormat format)
: mFormat(format),
mState(UNINITIALIZED) {
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 2b45f2d..0536f2a 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -20,7 +20,7 @@
#include <media/stagefright/NuMediaExtractor.h>
-#include "include/ESDS.h"
+#include <media/esds/ESDS.h>
#include <datasource/DataSourceFactory.h>
#include <datasource/FileSource.h>
diff --git a/media/libstagefright/OWNERS b/media/libstagefright/OWNERS
index e67496e..f02e168 100644
--- a/media/libstagefright/OWNERS
+++ b/media/libstagefright/OWNERS
@@ -7,3 +7,5 @@
# go/android-fwk-media-solutions for info on areas of ownership.
include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
+
+per-file Camera*.cpp = file:/camera/OWNERS
diff --git a/media/libstagefright/OggWriter.cpp b/media/libstagefright/OggWriter.cpp
index 0f5e95e..cff37a3 100644
--- a/media/libstagefright/OggWriter.cpp
+++ b/media/libstagefright/OggWriter.cpp
@@ -96,6 +96,7 @@
return ERROR_UNSUPPORTED;
}
+ // NOLINTNEXTLINE(clang-analyzer-unix.MallocSizeof)
mOs = (OggStreamState*) malloc(sizeof(ogg_stream_state));
if (ogg_stream_init((ogg_stream_state*)mOs, rand()) == -1) {
ALOGE("ogg stream init failed");
@@ -242,13 +243,15 @@
mDone = true;
- void* dummy;
- pthread_join(mThread, &dummy);
+ status_t status = mSource->stop();
- status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
+ void *pthread_res;
+ pthread_join(mThread, &pthread_res);
+
+ status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(pthread_res));
{
- status_t status = mSource->stop();
- if (err == OK && (status != OK && status != ERROR_END_OF_STREAM)) {
+ if (err == OK &&
+ (status != OK && status != ERROR_END_OF_STREAM)) {
err = status;
}
}
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index f526e05..291b892 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -193,10 +193,38 @@
status_t pushBlankBuffersToNativeWindow(ANativeWindow *nativeWindow /* nonnull */) {
status_t err = NO_ERROR;
- ANativeWindowBuffer* anb = NULL;
+ ANativeWindowBuffer* anb = nullptr;
int numBufs = 0;
int minUndequeuedBufs = 0;
+ auto handleError = [](ANativeWindow *nativeWindow, ANativeWindowBuffer* anb, status_t err)
+ {
+ if (anb != nullptr) {
+ nativeWindow->cancelBuffer(nativeWindow, anb, -1);
+ anb = nullptr;
+ }
+
+ // Clean up after success or error.
+ status_t err2 = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_CPU);
+ if (err2 != NO_ERROR) {
+ ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
+ strerror(-err2), -err2);
+ if (err == NO_ERROR) {
+ err = err2;
+ }
+ }
+
+ err2 = nativeWindowConnect(nativeWindow, "pushBlankBuffersToNativeWindow(err2)");
+ if (err2 != NO_ERROR) {
+ ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err);
+ if (err == NO_ERROR) {
+ err = err2;
+ }
+ }
+
+ return err;
+ };
+
// We need to reconnect to the ANativeWindow as a CPU client to ensure that
// no frames get dropped by SurfaceFlinger assuming that these are video
// frames.
@@ -217,7 +245,7 @@
nativeWindow, 1, 1, HAL_PIXEL_FORMAT_RGBX_8888, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
false /* reconnect */);
if (err != NO_ERROR) {
- goto error;
+ return handleError(nativeWindow, anb, err);
}
static_cast<Surface*>(nativeWindow)->getIGraphicBufferProducer()->allowAllocation(true);
@@ -232,14 +260,14 @@
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
"failed: %s (%d)", strerror(-err), -err);
- goto error;
+ return handleError(nativeWindow, anb, err);
}
numBufs = minUndequeuedBufs + 1;
err = native_window_set_buffer_count(nativeWindow, numBufs);
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", strerror(-err), -err);
- goto error;
+ return handleError(nativeWindow, anb, err);
}
// We push numBufs + 1 buffers to ensure that we've drawn into the same
@@ -257,7 +285,7 @@
sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
// Fill the buffer with the a 1x1 checkerboard pattern ;)
- uint32_t *img = NULL;
+ uint32_t *img = nullptr;
err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: lock failed: %s (%d)", strerror(-err), -err);
@@ -278,34 +306,10 @@
break;
}
- anb = NULL;
+ anb = nullptr;
}
-error:
-
- if (anb != NULL) {
- nativeWindow->cancelBuffer(nativeWindow, anb, -1);
- anb = NULL;
- }
-
- // Clean up after success or error.
- status_t err2 = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_CPU);
- if (err2 != NO_ERROR) {
- ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", strerror(-err2), -err2);
- if (err == NO_ERROR) {
- err = err2;
- }
- }
-
- err2 = nativeWindowConnect(nativeWindow, "pushBlankBuffersToNativeWindow(err2)");
- if (err2 != NO_ERROR) {
- ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err);
- if (err == NO_ERROR) {
- err = err2;
- }
- }
-
- return err;
+ return handleError(nativeWindow, anb, err);
}
status_t nativeWindowConnect(ANativeWindow *surface, const char *reason) {
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index a443ed9..863177d 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -24,7 +24,7 @@
#include <utility>
#include <vector>
-#include "include/ESDS.h"
+#include <media/esds/ESDS.h>
#include "include/HevcUtils.h"
#include <cutils/properties.h>
@@ -794,6 +794,12 @@
{ "thumbnail-height", kKeyThumbnailHeight },
{ "track-id", kKeyTrackID },
{ "valid-samples", kKeyValidSamples },
+ { "dvb-component-tag", kKeyDvbComponentTag},
+ { "dvb-audio-description", kKeyDvbAudioDescription},
+ { "dvb-teletext-magazine-number", kKeyDvbTeletextMagazineNumber},
+ { "dvb-teletext-page-number", kKeyDvbTeletextPageNumber},
+ { "profile", kKeyAudioProfile },
+ { "level", kKeyAudioLevel },
}
};
@@ -1002,6 +1008,26 @@
msg->setInt32("is-sync-frame", 1);
}
+ int32_t dvbComponentTag = 0;
+ if (meta->findInt32(kKeyDvbComponentTag, &dvbComponentTag)) {
+ msg->setInt32("dvb-component-tag", dvbComponentTag);
+ }
+
+ int32_t dvbAudioDescription = 0;
+ if (meta->findInt32(kKeyDvbAudioDescription, &dvbAudioDescription)) {
+ msg->setInt32("dvb-audio-description", dvbAudioDescription);
+ }
+
+ int32_t dvbTeletextMagazineNumber = 0;
+ if (meta->findInt32(kKeyDvbTeletextMagazineNumber, &dvbTeletextMagazineNumber)) {
+ msg->setInt32("dvb-teletext-magazine-number", dvbTeletextMagazineNumber);
+ }
+
+ int32_t dvbTeletextPageNumber = 0;
+ if (meta->findInt32(kKeyDvbTeletextPageNumber, &dvbTeletextPageNumber)) {
+ msg->setInt32("dvb-teletext-page-number", dvbTeletextPageNumber);
+ }
+
const char *lang;
if (meta->findCString(kKeyMediaLanguage, &lang)) {
msg->setString("language", lang);
@@ -1788,6 +1814,26 @@
meta->setInt32(kKeyMaxBitRate, maxBitrate);
}
+ int32_t dvbComponentTag = 0;
+ if (msg->findInt32("dvb-component-tag", &dvbComponentTag) && dvbComponentTag > 0) {
+ meta->setInt32(kKeyDvbComponentTag, dvbComponentTag);
+ }
+
+ int32_t dvbAudioDescription = 0;
+ if (msg->findInt32("dvb-audio-description", &dvbAudioDescription)) {
+ meta->setInt32(kKeyDvbAudioDescription, dvbAudioDescription);
+ }
+
+ int32_t dvbTeletextMagazineNumber = 0;
+ if (msg->findInt32("dvb-teletext-magazine-number", &dvbTeletextMagazineNumber)) {
+ meta->setInt32(kKeyDvbTeletextMagazineNumber, dvbTeletextMagazineNumber);
+ }
+
+ int32_t dvbTeletextPageNumber = 0;
+ if (msg->findInt32("dvb-teletext-page-number", &dvbTeletextPageNumber)) {
+ meta->setInt32(kKeyDvbTeletextPageNumber, dvbTeletextPageNumber);
+ }
+
AString lang;
if (msg->findString("language", &lang)) {
meta->setCString(kKeyMediaLanguage, lang.c_str());
@@ -1911,10 +1957,10 @@
if (msg->findString("ts-schema", &tsSchema)) {
unsigned int numLayers = 0;
unsigned int numBLayers = 0;
- char dummy;
+ char placeholder;
int tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c",
- &numLayers, &dummy, &numBLayers, &dummy);
- if ((tags == 1 || (tags == 3 && dummy == '+'))
+ &numLayers, &placeholder, &numBLayers, &placeholder);
+ if ((tags == 1 || (tags == 3 && placeholder == '+'))
&& numLayers > 0 && numLayers < UINT32_MAX - numBLayers
&& numLayers + numBLayers <= INT32_MAX) {
meta->setInt32(kKeyTemporalLayerCount, numLayers + numBLayers);
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 4711315..2409315 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -441,7 +441,7 @@
((dataSpace & ~HAL_DATASPACE_RANGE_MASK) | HAL_DATASPACE_RANGE_FULL);
}
- ALOGD("setting dataspace on output surface to #%x", dataSpace);
+ ALOGD("setting dataspace on output surface to %#x", dataSpace);
if ((err = native_window_set_buffers_data_space(mNativeWindow.get(), dataSpace))) {
ALOGW("failed to set dataspace on surface (%d)", err);
}
diff --git a/media/libstagefright/colorconversion/fuzzer/Android.bp b/media/libstagefright/colorconversion/fuzzer/Android.bp
new file mode 100644
index 0000000..76b054a
--- /dev/null
+++ b/media/libstagefright/colorconversion/fuzzer/Android.bp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_colorconversion_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_colorconversion_license",
+ ],
+}
+
+cc_defaults {
+ name: "libcolorconversion_fuzzer_defaults",
+ static_libs: [
+ "libyuv_static",
+ "libstagefright_color_conversion",
+ "libstagefright",
+ "liblog",
+ ],
+ header_libs: [
+ "libstagefright_headers",
+ "libgui_headers",
+ ],
+ shared_libs: [
+ "libui",
+ "libnativewindow",
+ "libstagefright_codecbase",
+ "libstagefright_foundation",
+ "libutils",
+ "libgui",
+ "libbinder",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
+
+cc_fuzz {
+ name: "color_conversion_fuzzer",
+ srcs: [
+ "color_conversion_fuzzer.cpp",
+ ],
+ defaults: [
+ "libcolorconversion_fuzzer_defaults",
+ ],
+}
diff --git a/media/libstagefright/colorconversion/fuzzer/README.md b/media/libstagefright/colorconversion/fuzzer/README.md
new file mode 100644
index 0000000..220f749
--- /dev/null
+++ b/media/libstagefright/colorconversion/fuzzer/README.md
@@ -0,0 +1,28 @@
+# Fuzzers for libstagefright_color_conversion
+
+## Table of contents
++ [color_conversion_fuzzer](#ColorConversion)
+
+
+# <a name="ColorConversion"></a> Fuzzer for Colorconversion
+
+ColorConversion supports the following parameters:
+1. SrcColorFormatType (parameter name: "kSrcFormatType")
+2. DstColorFormatType (parameter name: "kDstFormatType")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+|`kSrcFormatType`| 0. `OMX_COLOR_FormatYUV420Planar`<br/>1. `OMX_COLOR_FormatYUV420Planar16`<br/>2. `OMX_COLOR_FormatYUV420SemiPlanar` <br/>3. `OMX_TI_COLOR_FormatYUV420PackedSemiPlanar` <br/>4.`OMX_COLOR_FormatCbYCrY`<br/>5.`OMX_QCOM_COLOR_FormatYVU420SemiPlanar`<br/>6.`COLOR_FormatYUVP010`|Value obtained from FuzzedDataProvider|
+|`kDstFormatType`| 0. `OMX_COLOR_Format16bitRGB565`<br/>1. `OMX_COLOR_Format32BitRGBA8888`<br/>2. `OMX_COLOR_Format32bitBGRA8888` <br/>3. `OMX_COLOR_Format16bitRGB565` <br/>4. `OMX_COLOR_Format32bitBGRA8888`<br/>5.`OMX_COLOR_FormatYUV444Y410`<br/>6. `COLOR_Format32bitABGR2101010`|Value obtained from FuzzedDataProvider|
+
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) color_conversion_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/color_conversion_fuzzer/color_conversion_fuzzer
+```
diff --git a/media/libstagefright/colorconversion/fuzzer/color_conversion_fuzzer.cpp b/media/libstagefright/colorconversion/fuzzer/color_conversion_fuzzer.cpp
new file mode 100644
index 0000000..7c2bfe5
--- /dev/null
+++ b/media/libstagefright/colorconversion/fuzzer/color_conversion_fuzzer.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2022 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 <media/stagefright/ColorConverter.h>
+#include <media/stagefright/MediaCodecConstants.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <iostream>
+#include <vector>
+#include "fuzzer/FuzzedDataProvider.h"
+
+using namespace android;
+using ::android::sp;
+
+static constexpr int32_t kMinFrameSize = 2;
+static constexpr int32_t kMaxFrameSize = 8192;
+
+static constexpr int32_t kSrcFormatType[] = {OMX_COLOR_FormatYUV420Planar,
+ OMX_COLOR_FormatYUV420Planar16,
+ OMX_COLOR_FormatYUV420SemiPlanar,
+ OMX_TI_COLOR_FormatYUV420PackedSemiPlanar,
+ OMX_COLOR_FormatCbYCrY,
+ OMX_QCOM_COLOR_FormatYVU420SemiPlanar,
+ COLOR_FormatYUVP010};
+
+static constexpr int32_t kDstFormatType[] = {
+ OMX_COLOR_Format16bitRGB565, OMX_COLOR_Format32BitRGBA8888, OMX_COLOR_Format32bitBGRA8888,
+ OMX_COLOR_FormatYUV444Y410, COLOR_Format32bitABGR2101010};
+
+class ColorConversionFuzzer {
+ public:
+ ColorConversionFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
+ void process();
+
+ private:
+ FuzzedDataProvider mFdp;
+ int32_t getFrameSize(OMX_COLOR_FORMATTYPE colorFormat, int32_t stride, int32_t height);
+ bool isValidFormat(OMX_COLOR_FORMATTYPE srcFormat, OMX_COLOR_FORMATTYPE dstFormat);
+};
+
+int32_t ColorConversionFuzzer::getFrameSize(OMX_COLOR_FORMATTYPE colorFormat, int32_t stride,
+ int32_t height) {
+ int32_t frameSize;
+ switch ((int32_t)colorFormat) {
+ case OMX_COLOR_Format16bitRGB565: {
+ frameSize = 2 * stride * height;
+ break;
+ }
+ case OMX_COLOR_FormatYUV420Planar16:
+ case COLOR_FormatYUVP010:
+ case OMX_COLOR_FormatYUV444Y410: {
+ frameSize = 3 * stride * height;
+ break;
+ }
+ case OMX_COLOR_Format32bitBGRA8888:
+ case OMX_COLOR_Format32BitRGBA8888:
+ case COLOR_Format32bitABGR2101010: {
+ frameSize = 4 * stride * height;
+ break;
+ }
+ case OMX_COLOR_FormatYUV420Planar:
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ case OMX_COLOR_FormatCbYCrY:
+ case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
+ case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
+ default: {
+ frameSize = stride * height + 2 * (((stride + 1) / 2) * ((height + 1) / 2));
+ break;
+ }
+ }
+ return frameSize;
+}
+
+void ColorConversionFuzzer::process() {
+ OMX_COLOR_FORMATTYPE srcColorFormat =
+ static_cast<OMX_COLOR_FORMATTYPE>(mFdp.PickValueInArray(kSrcFormatType));
+ OMX_COLOR_FORMATTYPE dstColorFormat =
+ static_cast<OMX_COLOR_FORMATTYPE>(mFdp.PickValueInArray(kDstFormatType));
+ std::unique_ptr<ColorConverter> converter(new ColorConverter(srcColorFormat, dstColorFormat));
+ if (converter->isValid()) {
+ int32_t srcLeft, srcTop, srcRight, srcBottom, width, height, stride;
+ width = mFdp.ConsumeIntegralInRange<int32_t>(kMinFrameSize, kMaxFrameSize);
+ height = mFdp.ConsumeIntegralInRange<int32_t>(kMinFrameSize, kMaxFrameSize);
+ stride = mFdp.ConsumeIntegralInRange<int32_t>(width, 2 * kMaxFrameSize);
+
+ srcLeft = mFdp.ConsumeIntegralInRange<int32_t>(0, width - 1);
+ srcTop = mFdp.ConsumeIntegralInRange<int32_t>(0, height - 1);
+ srcRight = mFdp.ConsumeIntegralInRange<int32_t>(srcLeft, width - 1);
+ srcBottom = mFdp.ConsumeIntegralInRange<int32_t>(srcTop, height - 1);
+
+ int32_t dstLeft, dstTop, dstRight, dstBottom;
+ dstLeft = mFdp.ConsumeIntegralInRange<int32_t>(0, width - 1);
+ dstTop = mFdp.ConsumeIntegralInRange<int32_t>(0, height - 1);
+ dstRight = mFdp.ConsumeIntegralInRange<int32_t>(dstLeft, width - 1);
+ dstBottom = mFdp.ConsumeIntegralInRange<int32_t>(dstTop, height - 1);
+
+ int32_t srcFrameSize = getFrameSize(srcColorFormat, stride, height);
+ int32_t dstFrameSize = getFrameSize(dstColorFormat, stride, height);
+ std::vector<uint8_t> srcFrame(srcFrameSize), dstFrame(dstFrameSize);
+ mFdp.ConsumeData(srcFrame.data(), srcFrameSize);
+ converter->convert(srcFrame.data(), width, height, stride, srcLeft, srcTop, srcRight,
+ srcBottom, dstFrame.data(), width, height, stride, dstLeft, dstTop,
+ dstRight, dstBottom);
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ ColorConversionFuzzer colorConversionFuzzer(data, size);
+ colorConversionFuzzer.process();
+ return 0;
+}
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index d7e2d18..b29c3b6 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -27,66 +27,77 @@
<Limit name="channel-count" max="2" />
<Limit name="sample-rate" ranges="8000,11025,12000,16000,22050,24000,32000,44100,48000" />
<Limit name="bitrate" range="8000-320000" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.amrnb.decoder" type="audio/3gpp">
<Alias name="OMX.google.amrnb.decoder" />
<Limit name="channel-count" max="1" />
<Limit name="sample-rate" ranges="8000" />
<Limit name="bitrate" range="4750-12200" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.amrwb.decoder" type="audio/amr-wb">
<Alias name="OMX.google.amrwb.decoder" />
<Limit name="channel-count" max="1" />
<Limit name="sample-rate" ranges="16000" />
<Limit name="bitrate" range="6600-23850" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.aac.decoder" type="audio/mp4a-latm">
<Alias name="OMX.google.aac.decoder" />
<Limit name="channel-count" max="8" />
<Limit name="sample-rate" ranges="7350,8000,11025,12000,16000,22050,24000,32000,44100,48000" />
<Limit name="bitrate" range="8000-960000" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.g711.alaw.decoder" type="audio/g711-alaw">
<Alias name="OMX.google.g711.alaw.decoder" />
<Limit name="channel-count" max="6" />
<Limit name="sample-rate" ranges="8000-48000" />
<Limit name="bitrate" range="64000" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.g711.mlaw.decoder" type="audio/g711-mlaw">
<Alias name="OMX.google.g711.mlaw.decoder" />
<Limit name="channel-count" max="6" />
<Limit name="sample-rate" ranges="8000-48000" />
<Limit name="bitrate" range="64000" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.vorbis.decoder" type="audio/vorbis">
<Alias name="OMX.google.vorbis.decoder" />
<Limit name="channel-count" max="8" />
<Limit name="sample-rate" ranges="8000-96000" />
<Limit name="bitrate" range="32000-500000" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.opus.decoder" type="audio/opus">
<Alias name="OMX.google.opus.decoder" />
<Limit name="channel-count" max="8" />
<Limit name="sample-rate" ranges="8000,12000,16000,24000,48000" />
<Limit name="bitrate" range="6000-510000" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.raw.decoder" type="audio/raw">
<Alias name="OMX.google.raw.decoder" />
<Limit name="channel-count" max="8" />
- <Limit name="sample-rate" ranges="8000-96000" />
+ <Limit name="sample-rate" ranges="8000-192000" />
<Limit name="bitrate" range="1-10000000" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.flac.decoder" type="audio/flac">
<Alias name="OMX.google.flac.decoder" />
<Limit name="channel-count" max="8" />
<Limit name="sample-rate" ranges="1-655350" />
<Limit name="bitrate" range="1-21000000" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.gsm.decoder" type="audio/gsm" domain="telephony">
<Alias name="OMX.google.gsm.decoder" />
<Limit name="channel-count" max="1" />
<Limit name="sample-rate" ranges="8000" />
<Limit name="bitrate" range="13000" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.mpeg4.decoder" type="video/mp4v-es">
<Alias name="OMX.google.mpeg4.decoder" />
@@ -97,6 +108,7 @@
<Limit name="blocks-per-second" range="1-432000" />
<Limit name="bitrate" range="1-40000000" />
<Feature name="adaptive-playback" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.h263.decoder" type="video/3gpp">
<Alias name="OMX.google.h263.decoder" />
@@ -106,6 +118,7 @@
<Limit name="alignment" value="2x2" />
<Limit name="bitrate" range="1-384000" />
<Feature name="adaptive-playback" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.avc.decoder" type="video/avc" variant="slow-cpu,!slow-cpu">
<Alias name="OMX.google.h264.decoder" />
@@ -126,6 +139,7 @@
<Limit name="bitrate" range="1-40000000" />
</Variant>
<Feature name="adaptive-playback" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.hevc.decoder" type="video/hevc" variant="slow-cpu,!slow-cpu">
<Alias name="OMX.google.hevc.decoder" />
@@ -146,6 +160,7 @@
<Limit name="bitrate" range="1-5000000" />
</Variant>
<Feature name="adaptive-playback" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.vp8.decoder" type="video/x-vnd.on2.vp8" variant="slow-cpu,!slow-cpu">
<Alias name="OMX.google.vp8.decoder" />
@@ -163,6 +178,7 @@
<Limit name="bitrate" range="1-40000000" />
</Variant>
<Feature name="adaptive-playback" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.vp9.decoder" type="video/x-vnd.on2.vp9" variant="slow-cpu,!slow-cpu">
<Alias name="OMX.google.vp9.decoder" />
@@ -181,6 +197,7 @@
<Limit name="bitrate" range="1-5000000" />
</Variant>
<Feature name="adaptive-playback" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.av1.decoder" type="video/av01" variant="!slow-cpu">
<Limit name="size" min="2x2" max="2048x2048" />
@@ -190,6 +207,7 @@
<Limit name="blocks-per-second" range="1-2073600" />
<Limit name="bitrate" range="1-120000000" />
<Feature name="adaptive-playback" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.mpeg2.decoder" type="video/mpeg2" domain="tv">
<Alias name="OMX.google.mpeg2.decoder" />
@@ -200,6 +218,7 @@
<Limit name="blocks-per-second" range="1-244800" />
<Limit name="bitrate" range="1-20000000" />
<Feature name="adaptive-playback" />
+ <Attribute name="software-codec" />
</MediaCodec>
</Decoders>
<Encoders>
@@ -209,6 +228,7 @@
<Limit name="sample-rate" ranges="8000,11025,12000,16000,22050,24000,32000,44100,48000" />
<!-- also may support 64000, 88200 and 96000 Hz -->
<Limit name="bitrate" range="8000-960000" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.amrnb.encoder" type="audio/3gpp">
<Alias name="OMX.google.amrnb.encoder" />
@@ -216,6 +236,7 @@
<Limit name="sample-rate" ranges="8000" />
<Limit name="bitrate" range="4750-12200" />
<Feature name="bitrate-modes" value="CBR" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.amrwb.encoder" type="audio/amr-wb">
<Alias name="OMX.google.amrwb.encoder" />
@@ -223,6 +244,7 @@
<Limit name="sample-rate" ranges="16000" />
<Limit name="bitrate" range="6600-23850" />
<Feature name="bitrate-modes" value="CBR" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.flac.encoder" type="audio/flac">
<Alias name="OMX.google.flac.encoder" />
@@ -231,6 +253,7 @@
<Limit name="bitrate" range="1-21000000" />
<Limit name="complexity" range="0-8" default="5" />
<Feature name="bitrate-modes" value="CQ" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.opus.encoder" type="audio/opus">
<Limit name="channel-count" max="2" />
@@ -238,6 +261,7 @@
<Limit name="bitrate" range="500-512000" />
<Limit name="complexity" range="0-10" default="5" />
<Feature name="bitrate-modes" value="CBR,VBR" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.h263.encoder" type="video/3gpp">
<Alias name="OMX.google.h263.encoder" />
@@ -245,6 +269,7 @@
<Limit name="size" min="176x144" max="176x144" />
<Limit name="alignment" value="16x16" />
<Limit name="bitrate" range="1-128000" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.mpeg4.encoder" type="video/mp4v-es">
<Alias name="OMX.google.mpeg4.encoder" />
@@ -254,6 +279,7 @@
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="12-1485" />
<Limit name="bitrate" range="1-64000" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.avc.encoder" type="video/avc" variant="slow-cpu,!slow-cpu">
<Alias name="OMX.google.h264.encoder" />
@@ -277,6 +303,7 @@
<!-- Video Quality control -->
<!-- supports QP bounding with standard keys -->
<Feature name="qp-bounds" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.vp8.encoder" type="video/x-vnd.on2.vp8" variant="slow-cpu,!slow-cpu">
<Alias name="OMX.google.vp8.encoder" />
@@ -296,6 +323,7 @@
<Limit name="bitrate" range="1-20000000" />
</Variant>
<Feature name="bitrate-modes" value="VBR,CBR" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.hevc.encoder" type="video/hevc" variant="!slow-cpu">
<!-- profiles and levels: ProfileMain : MainTierLevel51 -->
@@ -309,6 +337,7 @@
<Limit name="complexity" range="0-10" default="0" />
<Limit name="quality" range="0-100" default="80" />
<Feature name="bitrate-modes" value="VBR,CBR,CQ" />
+ <Attribute name="software-codec" />
</MediaCodec>
<MediaCodec name="c2.android.vp9.encoder" type="video/x-vnd.on2.vp9" variant="!slow-cpu">
<Alias name="OMX.google.vp9.encoder" />
@@ -320,6 +349,7 @@
<Limit name="block-count" range="1-3600" /> <!-- max 1280x720 -->
<Limit name="bitrate" range="1-40000000" />
<Feature name="bitrate-modes" value="VBR,CBR" />
+ <Attribute name="software-codec" />
</MediaCodec>
</Encoders>
</MediaCodecs>
diff --git a/media/libstagefright/exports.lds b/media/libstagefright/exports.lds
index f5ddf1e..7fe6d6c 100644
--- a/media/libstagefright/exports.lds
+++ b/media/libstagefright/exports.lds
@@ -8,19 +8,19 @@
_ZNK7android14ColorConverter*;
_ZN7android16SoftwareRenderer*;
ABGRToARGB;
- ABGRToI420;
+ ABGRToI420*;
ABGRToUVRow_Any_NEON*;
ABGRToUVRow_C;
ABGRToUVRow_NEON*;
ABGRToYRow_Any_NEON*;
ABGRToYRow_C;
ABGRToYRow_NEON*;
- Android420ToI420;
+ Android420ToI420*;
ARGB1555ToARGB;
ARGB1555ToARGBRow_Any_NEON*;
ARGB1555ToARGBRow_C;
ARGB1555ToARGBRow_NEON*;
- ARGB1555ToI420;
+ ARGB1555ToI420*;
ARGB1555ToUVRow_Any_NEON*;
ARGB1555ToUVRow_C;
ARGB1555ToUVRow_NEON*;
@@ -31,7 +31,7 @@
ARGB4444ToARGBRow_Any_NEON*;
ARGB4444ToARGBRow_C;
ARGB4444ToARGBRow_NEON*;
- ARGB4444ToI420;
+ ARGB4444ToI420*;
ARGB4444ToUVRow_Any_NEON*;
ARGB4444ToUVRow_C;
ARGB4444ToUVRow_NEON*;
@@ -115,7 +115,7 @@
ARGBToARGB4444Row_C;
ARGBToARGB4444Row_NEON*;
ARGBToBGRA;
- ARGBToI420;
+ ARGBToI420*;
ARGBToRAWRow_Any_NEON*;
ARGBToRAWRow_C;
ARGBToRAWRow_NEON*;
@@ -147,7 +147,7 @@
ARGBUnattenuateRow_C;
ArmCpuCaps*;
BGRAToARGB;
- BGRAToI420;
+ BGRAToI420*;
BGRAToUVRow_Any_NEON*;
BGRAToUVRow_C;
BGRAToUVRow_NEON*;
@@ -156,9 +156,9 @@
BGRAToYRow_NEON*;
BlendPlane;
BlendPlaneRow_C;
- CanonicalFourCC;
+ CanonicalFourCC*;
ComputeCumulativeSumRow_C;
- ConvertFromI420;
+ ConvertFromI420*;
CopyPlane;
CopyPlane_16;
CopyRow_16_C;
@@ -182,40 +182,40 @@
HalfFloatRow_Any_NEON*;
HalfFloatRow_C;
HalfFloatRow_NEON*;
- I400Copy;
+ I400Copy*;
I400Mirror;
I400ToARGB;
I400ToARGBRow_Any_NEON*;
I400ToARGBRow_C;
I400ToARGBRow_NEON*;
I400ToI400;
- I400ToI420;
+ I400ToI420*;
I420AlphaToABGR;
I420AlphaToARGB;
I420Blend;
- I420Copy;
+ I420Copy*;
I420Interpolate;
I420Mirror;
I420Rect;
- I420Scale;
- I420Scale_16;
+ I420Scale*;
+ I420Scale_16*;
I420ToABGR;
I420ToARGB;
I420ToARGB1555;
I420ToARGB4444;
I420ToBGRA;
I420ToI400;
- I420ToI422;
- I420ToI444;
- I420ToNV12;
- I420ToNV21;
+ I420ToI422*;
+ I420ToI444*;
+ I420ToNV12*;
+ I420ToNV21*;
I420ToRAW;
I420ToRGB24;
I420ToRGB565;
I420ToRGB565Dither;
I420ToRGBA;
- I420ToUYVY;
- I420ToYUY2;
+ I420ToUYVY*;
+ I420ToYUY2*;
I422AlphaToARGBRow_Any_NEON*;
I422AlphaToARGBRow_C;
I422AlphaToARGBRow_NEON*;
@@ -232,7 +232,7 @@
I422ToARGBRow_C;
I422ToARGBRow_NEON*;
I422ToBGRA;
- I422ToI420;
+ I422ToI420*;
I422ToRGB24Row_Any_NEON*;
I422ToRGB24Row_C;
I422ToRGB24Row_NEON*;
@@ -244,11 +244,11 @@
I422ToRGBARow_Any_NEON*;
I422ToRGBARow_C;
I422ToRGBARow_NEON*;
- I422ToUYVY;
+ I422ToUYVY*;
I422ToUYVYRow_Any_NEON*;
I422ToUYVYRow_C;
I422ToUYVYRow_NEON*;
- I422ToYUY2;
+ I422ToYUY2*;
I422ToYUY2Row_Any_NEON*;
I422ToYUY2Row_C;
I422ToYUY2Row_NEON*;
@@ -258,7 +258,7 @@
I444ToARGBRow_Any_NEON*;
I444ToARGBRow_C;
I444ToARGBRow_NEON*;
- I444ToI420;
+ I444ToI420*;
InitCpuFlags*;
InterpolatePlane;
InterpolateRow_16_C;
@@ -280,8 +280,8 @@
kYvuH709Constants;
kYvuI601Constants;
kYvuJPEGConstants;
- M420ToARGB;
- M420ToI420;
+ M420ToARGB*;
+ M420ToI420*;
MaskCpuFlags*;
MergeUVPlane;
MergeUVRow_Any_NEON*;
@@ -297,7 +297,7 @@
NV12ToARGBRow_Any_NEON*;
NV12ToARGBRow_C;
NV12ToARGBRow_NEON*;
- NV12ToI420;
+ NV12ToI420*;
NV12ToRGB565;
NV12ToRGB565Row_Any_NEON*;
NV12ToRGB565Row_C;
@@ -306,12 +306,12 @@
NV21ToARGBRow_Any_NEON*;
NV21ToARGBRow_C;
NV21ToARGBRow_NEON*;
- NV21ToI420;
+ NV21ToI420*;
RAWToARGB;
RAWToARGBRow_Any_NEON*;
RAWToARGBRow_C;
RAWToARGBRow_NEON*;
- RAWToI420;
+ RAWToI420*;
RAWToRGB24;
RAWToRGB24Row_Any_NEON*;
RAWToRGB24Row_C;
@@ -326,7 +326,7 @@
RGB24ToARGBRow_Any_NEON*;
RGB24ToARGBRow_C;
RGB24ToARGBRow_NEON*;
- RGB24ToI420;
+ RGB24ToI420*;
RGB24ToUVRow_Any_NEON*;
RGB24ToUVRow_C;
RGB24ToUVRow_NEON*;
@@ -337,7 +337,7 @@
RGB565ToARGBRow_Any_NEON*;
RGB565ToARGBRow_C;
RGB565ToARGBRow_NEON*;
- RGB565ToI420;
+ RGB565ToI420*;
RGB565ToUVRow_Any_NEON*;
RGB565ToUVRow_C;
RGB565ToUVRow_NEON*;
@@ -345,7 +345,7 @@
RGB565ToYRow_C;
RGB565ToYRow_NEON*;
RGBAToARGB;
- RGBAToI420;
+ RGBAToI420*;
RGBAToUVRow_Any_NEON*;
RGBAToUVRow_C;
RGBAToUVRow_NEON*;
@@ -355,7 +355,7 @@
RGBColorMatrix;
RGBColorTable;
RGBColorTableRow_C;
- Scale;
+ Scale*;
ScaleAddRow_16_C;
ScaleAddRow_C;
ScaleAddRows_NEON*;
@@ -395,12 +395,12 @@
ScaleFilterCols_NEON*;
ScaleFilterReduce;
ScaleFilterRows_NEON*;
- ScalePlane;
- ScalePlane_16;
- ScalePlaneBilinearDown;
- ScalePlaneBilinearDown_16;
- ScalePlaneBilinearUp;
- ScalePlaneBilinearUp_16;
+ ScalePlane*;
+ ScalePlane_16*;
+ ScalePlaneBilinearDown*;
+ ScalePlaneBilinearDown_16*;
+ ScalePlaneBilinearUp*;
+ ScalePlaneBilinearUp_16*;
ScalePlaneVertical;
ScalePlaneVertical_16;
ScaleRowDown2_16_C;
@@ -475,7 +475,7 @@
UYVYToARGBRow_Any_NEON*;
UYVYToARGBRow_C;
UYVYToARGBRow_NEON*;
- UYVYToI420;
+ UYVYToI420*;
UYVYToI422;
UYVYToNV12;
UYVYToUV422Row_Any_NEON*;
@@ -491,7 +491,7 @@
YUY2ToARGBRow_Any_NEON*;
YUY2ToARGBRow_C;
YUY2ToARGBRow_NEON*;
- YUY2ToI420;
+ YUY2ToI420*;
YUY2ToI422;
YUY2ToNV12;
YUY2ToUV422Row_Any_NEON*;
diff --git a/media/libstagefright/filters/Android.bp b/media/libstagefright/filters/Android.bp
deleted file mode 100644
index e6d59ad..0000000
--- a/media/libstagefright/filters/Android.bp
+++ /dev/null
@@ -1,52 +0,0 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
-}
-
-cc_library_static {
- name: "libstagefright_mediafilter",
-
- srcs: [
- "ColorConvert.cpp",
- "GraphicBufferListener.cpp",
- "IntrinsicBlurFilter.cpp",
- "MediaFilter.cpp",
- "RSFilter.cpp",
- "SaturationFilter.cpp",
- "saturationARGB.rscript",
- "SimpleFilter.cpp",
- "ZeroFilter.cpp",
- ],
-
- export_include_dirs: [
- "include",
- ],
-
- local_include_dirs: [
- "include/filters",
- ],
-
- cflags: [
- "-Wno-multichar",
- "-Werror",
- "-Wall",
- ],
-
- header_libs: [
- "libmediadrm_headers",
- ],
-
- shared_libs: [
- "libgui",
- "libmedia",
- "libhidlmemory",
- ],
-
- sanitize: {
- cfi: true,
- },
-}
diff --git a/media/libstagefright/filters/ColorConvert.cpp b/media/libstagefright/filters/ColorConvert.cpp
deleted file mode 100644
index a8d5dd2..0000000
--- a/media/libstagefright/filters/ColorConvert.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2014 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 "ColorConvert.h"
-
-#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-#ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-namespace android {
-
-void YUVToRGB(
- int32_t y, int32_t u, int32_t v,
- int32_t* r, int32_t* g, int32_t* b) {
- y -= 16;
- u -= 128;
- v -= 128;
-
- *b = 1192 * y + 2066 * u;
- *g = 1192 * y - 833 * v - 400 * u;
- *r = 1192 * y + 1634 * v;
-
- *r = min(262143, max(0, *r));
- *g = min(262143, max(0, *g));
- *b = min(262143, max(0, *b));
-
- *r >>= 10;
- *g >>= 10;
- *b >>= 10;
-}
-
-void convertYUV420spToARGB(
- uint8_t *pY, uint8_t *pUV, int32_t width, int32_t height,
- uint8_t *dest) {
- const int32_t bytes_per_pixel = 2;
-
- for (int32_t i = 0; i < height; i++) {
- for (int32_t j = 0; j < width; j++) {
- int32_t y = *(pY + i * width + j);
- int32_t u = *(pUV + (i/2) * width + bytes_per_pixel * (j/2));
- int32_t v = *(pUV + (i/2) * width + bytes_per_pixel * (j/2) + 1);
-
- int32_t r, g, b;
- YUVToRGB(y, u, v, &r, &g, &b);
-
- *dest++ = 0xFF;
- *dest++ = r;
- *dest++ = g;
- *dest++ = b;
- }
- }
-}
-
-void convertYUV420spToRGB888(
- uint8_t *pY, uint8_t *pUV, int32_t width, int32_t height,
- uint8_t *dest) {
- const int32_t bytes_per_pixel = 2;
-
- for (int32_t i = 0; i < height; i++) {
- for (int32_t j = 0; j < width; j++) {
- int32_t y = *(pY + i * width + j);
- int32_t u = *(pUV + (i/2) * width + bytes_per_pixel * (j/2));
- int32_t v = *(pUV + (i/2) * width + bytes_per_pixel * (j/2) + 1);
-
- int32_t r, g, b;
- YUVToRGB(y, u, v, &r, &g, &b);
-
- *dest++ = r;
- *dest++ = g;
- *dest++ = b;
- }
- }
-}
-
-// HACK - not even slightly optimized
-// TODO: remove when RGBA support is added to SoftwareRenderer
-void convertRGBAToARGB(
- uint8_t *src, int32_t width, int32_t height, uint32_t stride,
- uint8_t *dest) {
- for (int32_t i = 0; i < height; ++i) {
- for (int32_t j = 0; j < width; ++j) {
- uint8_t r = *src++;
- uint8_t g = *src++;
- uint8_t b = *src++;
- uint8_t a = *src++;
- *dest++ = a;
- *dest++ = r;
- *dest++ = g;
- *dest++ = b;
- }
- src += (stride - width) * 4;
- }
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/GraphicBufferListener.cpp b/media/libstagefright/filters/GraphicBufferListener.cpp
deleted file mode 100644
index db061c1..0000000
--- a/media/libstagefright/filters/GraphicBufferListener.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2014 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 "GraphicBufferListener"
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaErrors.h>
-
-#include <gui/BufferItem.h>
-#include <utils/String8.h>
-
-#include "GraphicBufferListener.h"
-
-namespace android {
-
-status_t GraphicBufferListener::init(
- const sp<AMessage> ¬ify,
- size_t bufferWidth, size_t bufferHeight, size_t bufferCount) {
- mNotify = notify;
-
- String8 name("GraphicBufferListener");
- BufferQueue::createBufferQueue(&mProducer, &mConsumer);
- mConsumer->setConsumerName(name);
- mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight);
- mConsumer->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
-
- status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
- if (err != NO_ERROR) {
- ALOGE("Unable to set BQ max acquired buffer count to %zu: %d",
- bufferCount, err);
- return err;
- }
-
- wp<BufferQueue::ConsumerListener> listener =
- static_cast<BufferQueue::ConsumerListener*>(this);
- sp<BufferQueue::ProxyConsumerListener> proxy =
- new BufferQueue::ProxyConsumerListener(listener);
-
- err = mConsumer->consumerConnect(proxy, false);
- if (err != NO_ERROR) {
- ALOGE("Error connecting to BufferQueue: %s (%d)",
- strerror(-err), err);
- return err;
- }
-
- ALOGV("init() successful.");
-
- return OK;
-}
-
-void GraphicBufferListener::onFrameAvailable(const BufferItem& /* item */) {
- ALOGV("onFrameAvailable() called");
-
- {
- Mutex::Autolock autoLock(mMutex);
- mNumFramesAvailable++;
- }
-
- sp<AMessage> notify = mNotify->dup();
- mNotify->setWhat(kWhatFrameAvailable);
- mNotify->post();
-}
-
-void GraphicBufferListener::onBuffersReleased() {
- ALOGV("onBuffersReleased() called");
- // nothing to do
-}
-
-void GraphicBufferListener::onSidebandStreamChanged() {
- ALOGW("GraphicBufferListener cannot consume sideband streams.");
- // nothing to do
-}
-
-BufferItem GraphicBufferListener::getBufferItem() {
- BufferItem item;
-
- {
- Mutex::Autolock autoLock(mMutex);
- if (mNumFramesAvailable <= 0) {
- ALOGE("getBuffer() called with no frames available");
- return item;
- }
- mNumFramesAvailable--;
- }
-
- status_t err = mConsumer->acquireBuffer(&item, 0);
- if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
- // shouldn't happen, since we track num frames available
- ALOGE("frame was not available");
- item.mSlot = -1;
- return item;
- } else if (err != OK) {
- ALOGE("acquireBuffer returned err=%d", err);
- item.mSlot = -1;
- return item;
- }
-
- // Wait for it to become available.
- err = item.mFence->waitForever("GraphicBufferListener::getBufferItem");
- if (err != OK) {
- ALOGW("failed to wait for buffer fence: %d", err);
- // keep going
- }
-
- // If this is the first time we're seeing this buffer, add it to our
- // slot table.
- if (item.mGraphicBuffer != NULL) {
- ALOGV("setting mBufferSlot %d", item.mSlot);
- mBufferSlot[item.mSlot] = item.mGraphicBuffer;
- }
-
- return item;
-}
-
-sp<GraphicBuffer> GraphicBufferListener::getBuffer(BufferItem item) {
- sp<GraphicBuffer> buf;
- if (item.mSlot < 0 || item.mSlot >= BufferQueue::NUM_BUFFER_SLOTS) {
- ALOGE("getBuffer() received invalid BufferItem: mSlot==%d", item.mSlot);
- return buf;
- }
-
- buf = mBufferSlot[item.mSlot];
- CHECK(buf.get() != NULL);
-
- return buf;
-}
-
-status_t GraphicBufferListener::releaseBuffer(BufferItem item) {
- if (item.mSlot < 0 || item.mSlot >= BufferQueue::NUM_BUFFER_SLOTS) {
- ALOGE("getBuffer() received invalid BufferItem: mSlot==%d", item.mSlot);
- return ERROR_OUT_OF_RANGE;
- }
-
- mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/IntrinsicBlurFilter.cpp b/media/libstagefright/filters/IntrinsicBlurFilter.cpp
deleted file mode 100644
index e00afd9..0000000
--- a/media/libstagefright/filters/IntrinsicBlurFilter.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2014 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 "IntrinsicBlurFilter"
-
-#include <utils/Log.h>
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "IntrinsicBlurFilter.h"
-
-namespace android {
-
-status_t IntrinsicBlurFilter::configure(const sp<AMessage> &msg) {
- status_t err = SimpleFilter::configure(msg);
- if (err != OK) {
- return err;
- }
-
- if (!msg->findString("cacheDir", &mCacheDir)) {
- ALOGE("Failed to find cache directory in config message.");
- return NAME_NOT_FOUND;
- }
-
- return OK;
-}
-
-status_t IntrinsicBlurFilter::start() {
- // TODO: use a single RS context object for entire application
- mRS = new RSC::RS();
-
- if (!mRS->init(mCacheDir.c_str())) {
- ALOGE("Failed to initialize RenderScript context.");
- return NO_INIT;
- }
-
- // 32-bit elements for ARGB8888
- RSC::sp<const RSC::Element> e = RSC::Element::U8_4(mRS);
-
- RSC::Type::Builder tb(mRS, e);
- tb.setX(mWidth);
- tb.setY(mHeight);
- RSC::sp<const RSC::Type> t = tb.create();
-
- mAllocIn = RSC::Allocation::createTyped(mRS, t);
- mAllocOut = RSC::Allocation::createTyped(mRS, t);
-
- mBlur = RSC::ScriptIntrinsicBlur::create(mRS, e);
- mBlur->setRadius(mBlurRadius);
- mBlur->setInput(mAllocIn);
-
- return OK;
-}
-
-void IntrinsicBlurFilter::reset() {
- mBlur.clear();
- mAllocOut.clear();
- mAllocIn.clear();
- mRS.clear();
-}
-
-status_t IntrinsicBlurFilter::setParameters(const sp<AMessage> &msg) {
- sp<AMessage> params;
- CHECK(msg->findMessage("params", ¶ms));
-
- float blurRadius;
- if (params->findFloat("blur-radius", &blurRadius)) {
- mBlurRadius = blurRadius;
- }
-
- return OK;
-}
-
-status_t IntrinsicBlurFilter::processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
- mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
- mBlur->forEach(mAllocOut);
- mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/MediaFilter.cpp b/media/libstagefright/filters/MediaFilter.cpp
deleted file mode 100644
index c7baa73..0000000
--- a/media/libstagefright/filters/MediaFilter.cpp
+++ /dev/null
@@ -1,840 +0,0 @@
-/*
- * Copyright (C) 2014 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 "MediaFilter"
-
-#include <inttypes.h>
-#include <utils/Trace.h>
-
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include <media/stagefright/BufferProducerWrapper.h>
-#include <media/stagefright/MediaCodecConstants.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MediaFilter.h>
-
-#include <media/MediaCodecBuffer.h>
-
-#include <gui/BufferItem.h>
-
-#include "ColorConvert.h"
-#include "GraphicBufferListener.h"
-#include "IntrinsicBlurFilter.h"
-#include "RSFilter.h"
-#include "SaturationFilter.h"
-#include "ZeroFilter.h"
-
-namespace android {
-
-class MediaFilter::BufferChannel : public BufferChannelBase {
-public:
- BufferChannel(const sp<AMessage> &in, const sp<AMessage> &out)
- : mInputBufferFilled(in), mOutputBufferDrained(out) {
- }
-
- ~BufferChannel() override = default;
-
- // BufferChannelBase
-
- status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override {
- sp<AMessage> msg = mInputBufferFilled->dup();
- msg->setObject("buffer", buffer);
- msg->post();
- return OK;
- }
-
- status_t queueSecureInputBuffer(
- const sp<MediaCodecBuffer> &,
- bool,
- const uint8_t *,
- const uint8_t *,
- CryptoPlugin::Mode,
- CryptoPlugin::Pattern,
- const CryptoPlugin::SubSample *,
- size_t,
- AString *) override {
- return INVALID_OPERATION;
- }
-
- status_t renderOutputBuffer(
- const sp<MediaCodecBuffer> &buffer, int64_t /* timestampNs */) override {
- sp<AMessage> msg = mOutputBufferDrained->dup();
- msg->setObject("buffer", buffer);
- msg->post();
- return OK;
- }
-
- status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override {
- if (FindBufferIndex(&mInputBuffers, buffer) >= 0) {
- sp<AMessage> msg = mInputBufferFilled->dup();
- msg->setObject("buffer", buffer);
- msg->post();
- return OK;
- }
- sp<AMessage> msg = mOutputBufferDrained->dup();
- msg->setObject("buffer", buffer);
- msg->post();
- return OK;
- }
-
- void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
- if (!array) {
- return;
- }
- array->clear();
- array->appendVector(mInputBuffers);
- }
-
- void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
- if (!array) {
- return;
- }
- array->clear();
- array->appendVector(mOutputBuffers);
- }
-
- // For MediaFilter
-
- void fillThisBuffer(const sp<MediaCodecBuffer> &buffer) {
- ssize_t index = FindBufferIndex(&mInputBuffers, buffer);
- mCallback->onInputBufferAvailable(index, buffer);
- }
-
- void drainThisBuffer(const sp<MediaCodecBuffer> &buffer, int flags) {
- ssize_t index = FindBufferIndex(&mOutputBuffers, buffer);
- buffer->meta()->setInt32("flags", flags);
- mCallback->onOutputBufferAvailable(index, buffer);
- }
-
- template <class T>
- void setInputBuffers(T begin, T end) {
- mInputBuffers.clear();
- for (T it = begin; it != end; ++it) {
- mInputBuffers.push_back(it->mData);
- }
- }
-
- template <class T>
- void setOutputBuffers(T begin, T end) {
- mOutputBuffers.clear();
- for (T it = begin; it != end; ++it) {
- mOutputBuffers.push_back(it->mData);
- }
- }
-
-private:
- sp<AMessage> mInputBufferFilled;
- sp<AMessage> mOutputBufferDrained;
- Vector<sp<MediaCodecBuffer>> mInputBuffers;
- Vector<sp<MediaCodecBuffer>> mOutputBuffers;
-
- static ssize_t FindBufferIndex(
- Vector<sp<MediaCodecBuffer>> *array, const sp<MediaCodecBuffer> &buffer) {
- for (size_t i = 0; i < array->size(); ++i) {
- if (array->itemAt(i) == buffer) {
- return i;
- }
- }
- return -1;
- }
-};
-
-// parameter: number of input and output buffers
-static const size_t kBufferCountActual = 4;
-
-MediaFilter::MediaFilter()
- : mState(UNINITIALIZED),
- mGeneration(0),
- mGraphicBufferListener(NULL) {
-}
-
-MediaFilter::~MediaFilter() {
-}
-
-//////////////////// PUBLIC FUNCTIONS //////////////////////////////////////////
-
-std::shared_ptr<BufferChannelBase> MediaFilter::getBufferChannel() {
- if (!mBufferChannel) {
- mBufferChannel = std::make_shared<BufferChannel>(
- new AMessage(kWhatInputBufferFilled, this),
- new AMessage(kWhatOutputBufferDrained, this));
- }
- return mBufferChannel;
-}
-
-void MediaFilter::initiateAllocateComponent(const sp<AMessage> &msg) {
- msg->setWhat(kWhatAllocateComponent);
- msg->setTarget(this);
- msg->post();
-}
-
-void MediaFilter::initiateConfigureComponent(const sp<AMessage> &msg) {
- msg->setWhat(kWhatConfigureComponent);
- msg->setTarget(this);
- msg->post();
-}
-
-void MediaFilter::initiateCreateInputSurface() {
- (new AMessage(kWhatCreateInputSurface, this))->post();
-}
-
-void MediaFilter::initiateSetInputSurface(
- const sp<PersistentSurface> & /* surface */) {
- ALOGW("initiateSetInputSurface() unsupported");
-}
-
-void MediaFilter::initiateStart() {
- (new AMessage(kWhatStart, this))->post();
-}
-
-void MediaFilter::initiateShutdown(bool keepComponentAllocated) {
- sp<AMessage> msg = new AMessage(kWhatShutdown, this);
- msg->setInt32("keepComponentAllocated", keepComponentAllocated);
- msg->post();
-}
-
-void MediaFilter::signalFlush() {
- (new AMessage(kWhatFlush, this))->post();
-}
-
-void MediaFilter::signalResume() {
- (new AMessage(kWhatResume, this))->post();
-}
-
-// nothing to do
-void MediaFilter::signalRequestIDRFrame() {
- return;
-}
-
-void MediaFilter::signalSetParameters(const sp<AMessage> ¶ms) {
- sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
- msg->setMessage("params", params);
- msg->post();
-}
-
-void MediaFilter::signalEndOfInputStream() {
- (new AMessage(kWhatSignalEndOfInputStream, this))->post();
-}
-
-void MediaFilter::onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatAllocateComponent:
- {
- onAllocateComponent(msg);
- break;
- }
- case kWhatConfigureComponent:
- {
- onConfigureComponent(msg);
- break;
- }
- case kWhatStart:
- {
- onStart();
- break;
- }
- case kWhatProcessBuffers:
- {
- processBuffers();
- break;
- }
- case kWhatInputBufferFilled:
- {
- onInputBufferFilled(msg);
- break;
- }
- case kWhatOutputBufferDrained:
- {
- onOutputBufferDrained(msg);
- break;
- }
- case kWhatShutdown:
- {
- onShutdown(msg);
- break;
- }
- case kWhatFlush:
- {
- onFlush();
- break;
- }
- case kWhatResume:
- {
- // nothing to do
- break;
- }
- case kWhatSetParameters:
- {
- onSetParameters(msg);
- break;
- }
- case kWhatCreateInputSurface:
- {
- onCreateInputSurface();
- break;
- }
- case GraphicBufferListener::kWhatFrameAvailable:
- {
- onInputFrameAvailable();
- break;
- }
- case kWhatSignalEndOfInputStream:
- {
- onSignalEndOfInputStream();
- break;
- }
- default:
- {
- ALOGE("Message not handled:\n%s", msg->debugString().c_str());
- break;
- }
- }
-}
-
-//////////////////// HELPER FUNCTIONS //////////////////////////////////////////
-
-void MediaFilter::signalProcessBuffers() {
- (new AMessage(kWhatProcessBuffers, this))->post();
-}
-
-void MediaFilter::signalError(status_t error) {
- mCallback->onError(error, ACTION_CODE_FATAL);
-}
-
-status_t MediaFilter::allocateBuffersOnPort(OMX_U32 portIndex) {
- CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
- const bool isInput = portIndex == kPortIndexInput;
- const size_t bufferSize = isInput ? mMaxInputSize : mMaxOutputSize;
-
- CHECK(mBuffers[portIndex].isEmpty());
-
- ALOGV("Allocating %zu buffers of size %zu on %s port",
- kBufferCountActual, bufferSize,
- isInput ? "input" : "output");
-
- // trigger output format change
- sp<AMessage> outputFormat = mOutputFormat->dup();
- for (size_t i = 0; i < kBufferCountActual; ++i) {
- BufferInfo info;
- info.mStatus = BufferInfo::OWNED_BY_US;
- info.mBufferID = i;
- info.mGeneration = mGeneration;
- info.mOutputFlags = 0;
- info.mData = new MediaCodecBuffer(
- isInput ? mInputFormat : outputFormat,
- new ABuffer(bufferSize));
- info.mData->meta()->setInt64("timeUs", 0);
-
- mBuffers[portIndex].push_back(info);
-
- if (!isInput) {
- mAvailableOutputBuffers.push(
- &mBuffers[portIndex].editItemAt(i));
- }
- }
- if (isInput) {
- mBufferChannel->setInputBuffers(
- mBuffers[portIndex].begin(), mBuffers[portIndex].end());
- } else {
- mBufferChannel->setOutputBuffers(
- mBuffers[portIndex].begin(), mBuffers[portIndex].end());
- }
-
- return OK;
-}
-
-MediaFilter::BufferInfo* MediaFilter::findBuffer(
- uint32_t portIndex, const sp<MediaCodecBuffer> &buffer,
- ssize_t *index) {
- for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
- BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
-
- if (info->mData == buffer) {
- if (index != NULL) {
- *index = i;
- }
- return info;
- }
- }
-
- TRESPASS();
-
- return NULL;
-}
-
-void MediaFilter::postFillThisBuffer(BufferInfo *info) {
- ALOGV("postFillThisBuffer on buffer %d", info->mBufferID);
- if (mPortEOS[kPortIndexInput]) {
- return;
- }
-
- CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
-
- info->mGeneration = mGeneration;
-
- info->mData->meta()->clear();
-
- sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, this);
- reply->setInt32("buffer-id", info->mBufferID);
-
- info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
-
- mBufferChannel->fillThisBuffer(info->mData);
-}
-
-void MediaFilter::postDrainThisBuffer(BufferInfo *info) {
- CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
-
- info->mGeneration = mGeneration;
-
- sp<AMessage> reply = new AMessage(kWhatOutputBufferDrained, this);
- reply->setInt32("buffer-id", info->mBufferID);
-
- mBufferChannel->drainThisBuffer(info->mData, info->mOutputFlags);
-
- info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
-}
-
-void MediaFilter::postEOS() {
- mCallback->onEos(ERROR_END_OF_STREAM);
-
- ALOGV("Sent kWhatEOS.");
-}
-
-void MediaFilter::requestFillEmptyInput() {
- if (mPortEOS[kPortIndexInput]) {
- return;
- }
-
- for (size_t i = 0; i < mBuffers[kPortIndexInput].size(); ++i) {
- BufferInfo *info = &mBuffers[kPortIndexInput].editItemAt(i);
-
- if (info->mStatus == BufferInfo::OWNED_BY_US) {
- postFillThisBuffer(info);
- }
- }
-}
-
-void MediaFilter::processBuffers() {
- if (mAvailableInputBuffers.empty() || mAvailableOutputBuffers.empty()) {
- ALOGV("Skipping process (buffers unavailable)");
- return;
- }
-
- if (mPortEOS[kPortIndexOutput]) {
- // TODO notify caller of queueInput error when it is supported
- // in MediaCodec
- ALOGW("Tried to process a buffer after EOS.");
- return;
- }
-
- BufferInfo *inputInfo = mAvailableInputBuffers[0];
- mAvailableInputBuffers.removeAt(0);
- BufferInfo *outputInfo = mAvailableOutputBuffers[0];
- mAvailableOutputBuffers.removeAt(0);
-
- status_t err;
- err = mFilter->processBuffers(inputInfo->mData, outputInfo->mData);
- if (err != (status_t)OK) {
- outputInfo->mData->meta()->setInt32("err", err);
- }
-
- int64_t timeUs;
- CHECK(inputInfo->mData->meta()->findInt64("timeUs", &timeUs));
- outputInfo->mData->meta()->setInt64("timeUs", timeUs);
- outputInfo->mOutputFlags = 0;
- int32_t eos = 0;
- if (inputInfo->mData->meta()->findInt32("eos", &eos) && eos != 0) {
- outputInfo->mOutputFlags |= BUFFER_FLAG_END_OF_STREAM;
- mPortEOS[kPortIndexOutput] = true;
- outputInfo->mData->meta()->setInt32("eos", eos);
- postEOS();
- ALOGV("Output stream saw EOS.");
- }
-
- ALOGV("Processed input buffer %u [%zu], output buffer %u [%zu]",
- inputInfo->mBufferID, inputInfo->mData->size(),
- outputInfo->mBufferID, outputInfo->mData->size());
-
- if (mGraphicBufferListener != NULL) {
- delete inputInfo;
- } else {
- postFillThisBuffer(inputInfo);
- }
- postDrainThisBuffer(outputInfo);
-
- // prevent any corner case where buffers could get stuck in queue
- signalProcessBuffers();
-}
-
-void MediaFilter::onAllocateComponent(const sp<AMessage> &msg) {
- CHECK_EQ(mState, UNINITIALIZED);
-
- CHECK(msg->findString("componentName", &mComponentName));
- const char* name = mComponentName.c_str();
- if (!strcasecmp(name, "android.filter.zerofilter")) {
- mFilter = new ZeroFilter;
- } else if (!strcasecmp(name, "android.filter.saturation")) {
- mFilter = new SaturationFilter;
- } else if (!strcasecmp(name, "android.filter.intrinsicblur")) {
- mFilter = new IntrinsicBlurFilter;
- } else if (!strcasecmp(name, "android.filter.RenderScript")) {
- mFilter = new RSFilter;
- } else {
- ALOGE("Unrecognized filter name: %s", name);
- signalError(NAME_NOT_FOUND);
- return;
- }
-
- mCallback->onComponentAllocated(mComponentName.c_str());
- mState = INITIALIZED;
- ALOGV("Handled kWhatAllocateComponent.");
-}
-
-void MediaFilter::onConfigureComponent(const sp<AMessage> &msg) {
- // TODO: generalize to allow audio filters as well as video
-
- CHECK_EQ(mState, INITIALIZED);
-
- // get params - at least mime, width & height
- AString mime;
- CHECK(msg->findString("mime", &mime));
- if (strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_RAW)) {
- ALOGE("Bad mime: %s", mime.c_str());
- signalError(BAD_VALUE);
- return;
- }
-
- CHECK(msg->findInt32("width", &mWidth));
- CHECK(msg->findInt32("height", &mHeight));
- if (!msg->findInt32("stride", &mStride)) {
- mStride = mWidth;
- }
- if (!msg->findInt32("slice-height", &mSliceHeight)) {
- mSliceHeight = mHeight;
- }
-
- mMaxInputSize = mWidth * mHeight * 4; // room for ARGB8888
- int32_t maxInputSize;
- if (msg->findInt32("max-input-size", &maxInputSize)
- && (size_t)maxInputSize > mMaxInputSize) {
- mMaxInputSize = maxInputSize;
- }
-
- if (!msg->findInt32("color-format", &mColorFormatIn)) {
- // default to OMX_COLOR_Format32bitARGB8888
- mColorFormatIn = OMX_COLOR_Format32bitARGB8888;
- msg->setInt32("color-format", mColorFormatIn);
- }
- mColorFormatOut = mColorFormatIn;
-
- mMaxOutputSize = mWidth * mHeight * 4; // room for ARGB8888
-
- AString cacheDir;
- if (!msg->findString("cacheDir", &cacheDir)) {
- ALOGE("Failed to find cache directory in config message.");
- signalError(NAME_NOT_FOUND);
- return;
- }
-
- status_t err;
- err = mFilter->configure(msg);
- if (err != (status_t)OK) {
- ALOGE("Failed to configure filter component, err %d", err);
- signalError(err);
- return;
- }
-
- mInputFormat = new AMessage();
- mInputFormat->setString("mime", mime.c_str());
- mInputFormat->setInt32("stride", mStride);
- mInputFormat->setInt32("slice-height", mSliceHeight);
- mInputFormat->setInt32("color-format", mColorFormatIn);
- mInputFormat->setRect("crop", 0, 0, mStride, mSliceHeight);
- mInputFormat->setInt32("width", mWidth);
- mInputFormat->setInt32("height", mHeight);
-
- mOutputFormat = new AMessage();
- mOutputFormat->setString("mime", mime.c_str());
- mOutputFormat->setInt32("stride", mStride);
- mOutputFormat->setInt32("slice-height", mSliceHeight);
- mOutputFormat->setInt32("color-format", mColorFormatOut);
- mOutputFormat->setRect("crop", 0, 0, mStride, mSliceHeight);
- mOutputFormat->setInt32("width", mWidth);
- mOutputFormat->setInt32("height", mHeight);
- mOutputFormat->setInt32("using-sw-renderer", 1);
-
- mCallback->onComponentConfigured(mInputFormat, mOutputFormat);
- mState = CONFIGURED;
- ALOGV("Handled kWhatConfigureComponent.");
-}
-
-void MediaFilter::onStart() {
- CHECK_EQ(mState, CONFIGURED);
-
- allocateBuffersOnPort(kPortIndexInput);
-
- allocateBuffersOnPort(kPortIndexOutput);
-
- mCallback->onStartCompleted();
-
- status_t err = mFilter->start();
- if (err != (status_t)OK) {
- ALOGE("Failed to start filter component, err %d", err);
- signalError(err);
- return;
- }
-
- mPortEOS[kPortIndexInput] = false;
- mPortEOS[kPortIndexOutput] = false;
- mInputEOSResult = OK;
- mState = STARTED;
-
- requestFillEmptyInput();
- ALOGV("Handled kWhatStart.");
-}
-
-void MediaFilter::onInputBufferFilled(const sp<AMessage> &msg) {
- sp<RefBase> obj;
- CHECK(msg->findObject("buffer", &obj));
- sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
- ssize_t index = -1;
- BufferInfo *info = findBuffer(kPortIndexInput, buffer, &index);
-
- if (mState != STARTED) {
- // we're not running, so we'll just keep that buffer...
- info->mStatus = BufferInfo::OWNED_BY_US;
- return;
- }
-
- if (info->mGeneration != mGeneration) {
- ALOGV("Caught a stale input buffer [index %zd]", index);
- // buffer is stale (taken before a flush/shutdown) - repost it
- CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
- postFillThisBuffer(info);
- return;
- }
-
- CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
- info->mStatus = BufferInfo::OWNED_BY_US;
-
- int32_t err = OK;
- bool eos = false;
-
- int32_t isCSD;
- if (buffer != NULL && buffer->meta()->findInt32("csd", &isCSD)
- && isCSD != 0) {
- // ignore codec-specific data buffers
- ALOGW("MediaFilter received a codec-specific data buffer");
- postFillThisBuffer(info);
- return;
- }
-
- int32_t tmp;
- if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
- eos = true;
- err = ERROR_END_OF_STREAM;
- }
-
- mAvailableInputBuffers.push_back(info);
- processBuffers();
-
- if (eos) {
- mPortEOS[kPortIndexInput] = true;
- mInputEOSResult = err;
- }
-
- ALOGV("Handled kWhatInputBufferFilled. [index %zd]", index);
-}
-
-void MediaFilter::onOutputBufferDrained(const sp<AMessage> &msg) {
- sp<RefBase> obj;
- CHECK(msg->findObject("buffer", &obj));
- sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
- ssize_t index = -1;
- BufferInfo *info = findBuffer(kPortIndexOutput, buffer, &index);
-
- if (mState != STARTED) {
- // we're not running, so we'll just keep that buffer...
- info->mStatus = BufferInfo::OWNED_BY_US;
- return;
- }
-
- if (info->mGeneration != mGeneration) {
- ALOGV("Caught a stale output buffer [index %zd]", index);
- // buffer is stale (taken before a flush/shutdown) - keep it
- CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
- return;
- }
-
- CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
- info->mStatus = BufferInfo::OWNED_BY_US;
-
- mAvailableOutputBuffers.push_back(info);
-
- processBuffers();
-
- ALOGV("Handled kWhatOutputBufferDrained. [index %zd]", index);
-}
-
-void MediaFilter::onShutdown(const sp<AMessage> &msg) {
- mGeneration++;
-
- if (mState != UNINITIALIZED) {
- mFilter->reset();
- }
-
- int32_t keepComponentAllocated;
- CHECK(msg->findInt32("keepComponentAllocated", &keepComponentAllocated));
- if (!keepComponentAllocated || mState == UNINITIALIZED) {
- mState = UNINITIALIZED;
- } else {
- mState = INITIALIZED;
- }
-
- if (keepComponentAllocated) {
- mCallback->onStopCompleted();
- } else {
- mCallback->onReleaseCompleted();
- }
-}
-
-void MediaFilter::onFlush() {
- mGeneration++;
-
- mAvailableInputBuffers.clear();
- for (size_t i = 0; i < mBuffers[kPortIndexInput].size(); ++i) {
- BufferInfo *info = &mBuffers[kPortIndexInput].editItemAt(i);
- info->mStatus = BufferInfo::OWNED_BY_US;
- }
- mAvailableOutputBuffers.clear();
- for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
- BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
- info->mStatus = BufferInfo::OWNED_BY_US;
- mAvailableOutputBuffers.push_back(info);
- }
-
- mPortEOS[kPortIndexInput] = false;
- mPortEOS[kPortIndexOutput] = false;
- mInputEOSResult = OK;
-
- mCallback->onFlushCompleted();
- ALOGV("Posted kWhatFlushCompleted");
-
- // MediaCodec returns all input buffers after flush, so in
- // onInputBufferFilled we call postFillThisBuffer on them
-}
-
-void MediaFilter::onSetParameters(const sp<AMessage> &msg) {
- CHECK(mState != STARTED);
-
- status_t err = mFilter->setParameters(msg);
- if (err != (status_t)OK) {
- ALOGE("setParameters returned err %d", err);
- }
-}
-
-void MediaFilter::onCreateInputSurface() {
- CHECK(mState == CONFIGURED);
-
- mGraphicBufferListener = new GraphicBufferListener;
-
- sp<AMessage> notify = new AMessage();
- notify->setTarget(this);
- status_t err = mGraphicBufferListener->init(
- notify, mStride, mSliceHeight, kBufferCountActual);
-
- if (err != OK) {
- ALOGE("Failed to init mGraphicBufferListener: %d", err);
- signalError(err);
- return;
- }
-
- mCallback->onInputSurfaceCreated(
- nullptr, nullptr,
- new BufferProducerWrapper(
- mGraphicBufferListener->getIGraphicBufferProducer()));
-}
-
-void MediaFilter::onInputFrameAvailable() {
- BufferItem item = mGraphicBufferListener->getBufferItem();
- sp<GraphicBuffer> buf = mGraphicBufferListener->getBuffer(item);
-
- // get pointer to graphic buffer
- void* bufPtr;
- buf->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &bufPtr);
-
- // HACK - there is no OMX_COLOR_FORMATTYPE value for RGBA, so the format
- // conversion is hardcoded until we add this.
- // TODO: check input format and convert only if necessary
- // copy RGBA graphic buffer into temporary ARGB input buffer
- BufferInfo *inputInfo = new BufferInfo;
- inputInfo->mData = new MediaCodecBuffer(
- mInputFormat, new ABuffer(buf->getWidth() * buf->getHeight() * 4));
- ALOGV("Copying surface data into temp buffer.");
- convertRGBAToARGB(
- (uint8_t*)bufPtr, buf->getWidth(), buf->getHeight(),
- buf->getStride(), inputInfo->mData->data());
- inputInfo->mBufferID = item.mSlot;
- inputInfo->mGeneration = mGeneration;
- inputInfo->mOutputFlags = 0;
- inputInfo->mStatus = BufferInfo::OWNED_BY_US;
- inputInfo->mData->meta()->setInt64("timeUs", item.mTimestamp / 1000);
-
- mAvailableInputBuffers.push_back(inputInfo);
-
- mGraphicBufferListener->releaseBuffer(item);
-
- signalProcessBuffers();
-}
-
-void MediaFilter::onSignalEndOfInputStream() {
- // if using input surface, need to send an EOS output buffer
- if (mGraphicBufferListener != NULL) {
- Vector<BufferInfo> *outputBufs = &mBuffers[kPortIndexOutput];
- BufferInfo* eosBuf;
- bool foundBuf = false;
- for (size_t i = 0; i < kBufferCountActual; i++) {
- eosBuf = &outputBufs->editItemAt(i);
- if (eosBuf->mStatus == BufferInfo::OWNED_BY_US) {
- foundBuf = true;
- break;
- }
- }
-
- if (!foundBuf) {
- ALOGE("onSignalEndOfInputStream failed to find an output buffer");
- return;
- }
-
- eosBuf->mOutputFlags = BUFFER_FLAG_END_OF_STREAM;
- eosBuf->mGeneration = mGeneration;
- eosBuf->mData->setRange(0, 0);
- postDrainThisBuffer(eosBuf);
- ALOGV("Posted EOS on output buffer %u", eosBuf->mBufferID);
- }
-
- mPortEOS[kPortIndexOutput] = true;
- mCallback->onSignaledInputEOS(OK);
-
- ALOGV("Output stream saw EOS.");
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/RSFilter.cpp b/media/libstagefright/filters/RSFilter.cpp
deleted file mode 100644
index 225a375..0000000
--- a/media/libstagefright/filters/RSFilter.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2014 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 "RSFilter"
-
-#include <utils/Log.h>
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "RSFilter.h"
-
-namespace android {
-
-RSFilter::RSFilter() {
-
-}
-
-RSFilter::~RSFilter() {
-
-}
-
-status_t RSFilter::configure(const sp<AMessage> &msg) {
- status_t err = SimpleFilter::configure(msg);
- if (err != OK) {
- return err;
- }
-
- if (!msg->findString("cacheDir", &mCacheDir)) {
- ALOGE("Failed to find cache directory in config message.");
- return NAME_NOT_FOUND;
- }
-
- sp<RenderScriptWrapper> wrapper;
- if (!msg->findObject("rs-wrapper", (sp<RefBase>*)&wrapper)) {
- ALOGE("Failed to find RenderScriptWrapper in config message.");
- return NAME_NOT_FOUND;
- }
-
- mRS = wrapper->mContext;
- mCallback = wrapper->mCallback;
-
- return OK;
-}
-
-status_t RSFilter::start() {
- // 32-bit elements for ARGB8888
- RSC::sp<const RSC::Element> e = RSC::Element::U8_4(mRS);
-
- RSC::Type::Builder tb(mRS, e);
- tb.setX(mWidth);
- tb.setY(mHeight);
- RSC::sp<const RSC::Type> t = tb.create();
-
- mAllocIn = RSC::Allocation::createTyped(mRS, t);
- mAllocOut = RSC::Allocation::createTyped(mRS, t);
-
- return OK;
-}
-
-void RSFilter::reset() {
- mCallback.clear();
- mAllocOut.clear();
- mAllocIn.clear();
- mRS.clear();
-}
-
-status_t RSFilter::setParameters(const sp<AMessage> &msg) {
- return mCallback->handleSetParameters(msg);
-}
-
-status_t RSFilter::processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
- mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
- mCallback->processBuffers(mAllocIn.get(), mAllocOut.get());
- mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/SaturationFilter.cpp b/media/libstagefright/filters/SaturationFilter.cpp
deleted file mode 100644
index 0a1df05..0000000
--- a/media/libstagefright/filters/SaturationFilter.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2014 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 "SaturationFilter"
-
-#include <utils/Log.h>
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "SaturationFilter.h"
-
-namespace android {
-
-status_t SaturationFilter::configure(const sp<AMessage> &msg) {
- status_t err = SimpleFilter::configure(msg);
- if (err != OK) {
- return err;
- }
-
- if (!msg->findString("cacheDir", &mCacheDir)) {
- ALOGE("Failed to find cache directory in config message.");
- return NAME_NOT_FOUND;
- }
-
- return OK;
-}
-
-status_t SaturationFilter::start() {
- // TODO: use a single RS context object for entire application
- mRS = new RSC::RS();
-
- if (!mRS->init(mCacheDir.c_str())) {
- ALOGE("Failed to initialize RenderScript context.");
- return NO_INIT;
- }
-
- // 32-bit elements for ARGB8888
- RSC::sp<const RSC::Element> e = RSC::Element::U8_4(mRS);
-
- RSC::Type::Builder tb(mRS, e);
- tb.setX(mWidth);
- tb.setY(mHeight);
- RSC::sp<const RSC::Type> t = tb.create();
-
- mAllocIn = RSC::Allocation::createTyped(mRS, t);
- mAllocOut = RSC::Allocation::createTyped(mRS, t);
-
- mScript = new ScriptC_saturationARGB(mRS);
-
- mScript->set_gSaturation(mSaturation);
-
- return OK;
-}
-
-void SaturationFilter::reset() {
- mScript.clear();
- mAllocOut.clear();
- mAllocIn.clear();
- mRS.clear();
-}
-
-status_t SaturationFilter::setParameters(const sp<AMessage> &msg) {
- sp<AMessage> params;
- CHECK(msg->findMessage("params", ¶ms));
-
- float saturation;
- if (params->findFloat("saturation", &saturation)) {
- mSaturation = saturation;
- }
-
- return OK;
-}
-
-status_t SaturationFilter::processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
- mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
- mScript->forEach_root(mAllocIn, mAllocOut);
- mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/SimpleFilter.cpp b/media/libstagefright/filters/SimpleFilter.cpp
deleted file mode 100644
index 6c1ca2c..0000000
--- a/media/libstagefright/filters/SimpleFilter.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2014 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 <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "SimpleFilter.h"
-
-namespace android {
-
-status_t SimpleFilter::configure(const sp<AMessage> &msg) {
- CHECK(msg->findInt32("width", &mWidth));
- CHECK(msg->findInt32("height", &mHeight));
- if (!msg->findInt32("stride", &mStride)) {
- mStride = mWidth;
- }
- if (!msg->findInt32("slice-height", &mSliceHeight)) {
- mSliceHeight = mHeight;
- }
- CHECK(msg->findInt32("color-format", &mColorFormatIn));
- mColorFormatOut = mColorFormatIn;
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/ZeroFilter.cpp b/media/libstagefright/filters/ZeroFilter.cpp
deleted file mode 100644
index 74b94b7..0000000
--- a/media/libstagefright/filters/ZeroFilter.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2014 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 "ZeroFilter"
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "ZeroFilter.h"
-
-namespace android {
-
-status_t ZeroFilter::setParameters(const sp<AMessage> &msg) {
- sp<AMessage> params;
- CHECK(msg->findMessage("params", ¶ms));
-
- int32_t invert;
- if (params->findInt32("invert", &invert)) {
- mInvertData = (invert != 0);
- }
-
- return OK;
-}
-
-status_t ZeroFilter::processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
- // assuming identical input & output buffers, since we're a copy filter
- if (mInvertData) {
- uint32_t* src = (uint32_t*)srcBuffer->data();
- uint32_t* dest = (uint32_t*)outBuffer->data();
- for (size_t i = 0; i < srcBuffer->size() / 4; ++i) {
- *(dest++) = *(src++) ^ 0xFFFFFFFF;
- }
- } else {
- memcpy(outBuffer->data(), srcBuffer->data(), srcBuffer->size());
- }
- outBuffer->setRange(0, srcBuffer->size());
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/include/filters/ColorConvert.h b/media/libstagefright/filters/include/filters/ColorConvert.h
deleted file mode 100644
index 13faa02..0000000
--- a/media/libstagefright/filters/include/filters/ColorConvert.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COLOR_CONVERT_H_
-#define COLOR_CONVERT_H_
-
-#include <inttypes.h>
-
-namespace android {
-
-void YUVToRGB(
- int32_t y, int32_t u, int32_t v,
- int32_t* r, int32_t* g, int32_t* b);
-
-void convertYUV420spToARGB(
- uint8_t *pY, uint8_t *pUV, int32_t width, int32_t height,
- uint8_t *dest);
-
-void convertYUV420spToRGB888(
- uint8_t *pY, uint8_t *pUV, int32_t width, int32_t height,
- uint8_t *dest);
-
-// TODO: remove when RGBA support is added to SoftwareRenderer
-void convertRGBAToARGB(
- uint8_t *src, int32_t width, int32_t height, uint32_t stride,
- uint8_t *dest);
-
-} // namespace android
-
-#endif // COLOR_CONVERT_H_
diff --git a/media/libstagefright/filters/include/filters/GraphicBufferListener.h b/media/libstagefright/filters/include/filters/GraphicBufferListener.h
deleted file mode 100644
index 586bf65..0000000
--- a/media/libstagefright/filters/include/filters/GraphicBufferListener.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef GRAPHIC_BUFFER_LISTENER_H_
-#define GRAPHIC_BUFFER_LISTENER_H_
-
-#include <gui/BufferQueue.h>
-
-namespace android {
-
-struct AMessage;
-
-struct GraphicBufferListener : public BufferQueue::ConsumerListener {
-public:
- GraphicBufferListener() {};
-
- status_t init(
- const sp<AMessage> ¬ify,
- size_t bufferWidth, size_t bufferHeight, size_t bufferCount);
-
- virtual void onFrameAvailable(const BufferItem& item);
- virtual void onBuffersReleased();
- virtual void onSidebandStreamChanged();
-
- // Returns the handle to the producer side of the BufferQueue. Buffers
- // queued on this will be received by GraphicBufferListener.
- sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
- return mProducer;
- }
-
- BufferItem getBufferItem();
- sp<GraphicBuffer> getBuffer(BufferItem item);
- status_t releaseBuffer(BufferItem item);
-
- enum {
- kWhatFrameAvailable = 'frav',
- };
-
-private:
- sp<AMessage> mNotify;
- size_t mNumFramesAvailable;
-
- mutable Mutex mMutex;
-
- // Our BufferQueue interfaces. mProducer is passed to the producer through
- // getIGraphicBufferProducer, and mConsumer is used internally to retrieve
- // the buffers queued by the producer.
- sp<IGraphicBufferProducer> mProducer;
- sp<IGraphicBufferConsumer> mConsumer;
-
- // Cache of GraphicBuffers from the buffer queue.
- sp<GraphicBuffer> mBufferSlot[BufferQueue::NUM_BUFFER_SLOTS];
-};
-
-} // namespace android
-
-#endif // GRAPHIC_BUFFER_LISTENER_H
diff --git a/media/libstagefright/filters/include/filters/IntrinsicBlurFilter.h b/media/libstagefright/filters/include/filters/IntrinsicBlurFilter.h
deleted file mode 100644
index a2aabfa..0000000
--- a/media/libstagefright/filters/include/filters/IntrinsicBlurFilter.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INTRINSIC_BLUR_FILTER_H_
-#define INTRINSIC_BLUR_FILTER_H_
-
-#include "RenderScript.h"
-#include "SimpleFilter.h"
-
-namespace android {
-
-struct IntrinsicBlurFilter : public SimpleFilter {
-public:
- IntrinsicBlurFilter() : mBlurRadius(1.f) {};
-
- virtual status_t configure(const sp<AMessage> &msg);
- virtual status_t start();
- virtual void reset();
- virtual status_t setParameters(const sp<AMessage> &msg);
- virtual status_t processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
-
-protected:
- virtual ~IntrinsicBlurFilter() {};
-
-private:
- AString mCacheDir;
- RSC::sp<RSC::RS> mRS;
- RSC::sp<RSC::Allocation> mAllocIn;
- RSC::sp<RSC::Allocation> mAllocOut;
- RSC::sp<RSC::ScriptIntrinsicBlur> mBlur;
- float mBlurRadius;
-};
-
-} // namespace android
-
-#endif // INTRINSIC_BLUR_FILTER_H_
diff --git a/media/libstagefright/filters/include/filters/RSFilter.h b/media/libstagefright/filters/include/filters/RSFilter.h
deleted file mode 100644
index 3326284..0000000
--- a/media/libstagefright/filters/include/filters/RSFilter.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RS_FILTER_H_
-#define RS_FILTER_H_
-
-#include <media/stagefright/RenderScriptWrapper.h>
-#include <RenderScript.h>
-
-#include "SimpleFilter.h"
-
-namespace android {
-
-struct AString;
-
-struct RSFilter : public SimpleFilter {
-public:
- RSFilter();
-
- virtual status_t configure(const sp<AMessage> &msg);
- virtual status_t start();
- virtual void reset();
- virtual status_t setParameters(const sp<AMessage> &msg);
- virtual status_t processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
-
-protected:
- virtual ~RSFilter();
-
-private:
- AString mCacheDir;
- sp<RenderScriptWrapper::RSFilterCallback> mCallback;
- RSC::sp<RSC::RS> mRS;
- RSC::sp<RSC::Allocation> mAllocIn;
- RSC::sp<RSC::Allocation> mAllocOut;
-};
-
-} // namespace android
-
-#endif // RS_FILTER_H_
diff --git a/media/libstagefright/filters/include/filters/SaturationFilter.h b/media/libstagefright/filters/include/filters/SaturationFilter.h
deleted file mode 100644
index 317e469..0000000
--- a/media/libstagefright/filters/include/filters/SaturationFilter.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SATURATION_FILTER_H_
-#define SATURATION_FILTER_H_
-
-#include <RenderScript.h>
-
-#include "ScriptC_saturationARGB.h"
-#include "SimpleFilter.h"
-
-namespace android {
-
-struct SaturationFilter : public SimpleFilter {
-public:
- SaturationFilter() : mSaturation(1.f) {};
-
- virtual status_t configure(const sp<AMessage> &msg);
- virtual status_t start();
- virtual void reset();
- virtual status_t setParameters(const sp<AMessage> &msg);
- virtual status_t processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
-
-protected:
- virtual ~SaturationFilter() {};
-
-private:
- AString mCacheDir;
- RSC::sp<RSC::RS> mRS;
- RSC::sp<RSC::Allocation> mAllocIn;
- RSC::sp<RSC::Allocation> mAllocOut;
- RSC::sp<ScriptC_saturationARGB> mScript;
- float mSaturation;
-};
-
-} // namespace android
-
-#endif // SATURATION_FILTER_H_
diff --git a/media/libstagefright/filters/include/filters/SimpleFilter.h b/media/libstagefright/filters/include/filters/SimpleFilter.h
deleted file mode 100644
index a3c2d76..0000000
--- a/media/libstagefright/filters/include/filters/SimpleFilter.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SIMPLE_FILTER_H_
-#define SIMPLE_FILTER_H_
-
-#include <stdint.h>
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-struct AMessage;
-class MediaCodecBuffer;
-
-struct SimpleFilter : public RefBase {
-public:
- SimpleFilter() : mWidth(0), mHeight(0), mStride(0), mSliceHeight(0),
- mColorFormatIn(0), mColorFormatOut(0) {};
-
- virtual status_t configure(const sp<AMessage> &msg);
-
- virtual status_t start() = 0;
- virtual void reset() = 0;
- virtual status_t setParameters(const sp<AMessage> &msg) = 0;
- virtual status_t processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) = 0;
-
-protected:
- int32_t mWidth, mHeight;
- int32_t mStride, mSliceHeight;
- int32_t mColorFormatIn, mColorFormatOut;
-
- virtual ~SimpleFilter() {};
-};
-
-} // namespace android
-
-#endif // SIMPLE_FILTER_H_
diff --git a/media/libstagefright/filters/include/filters/ZeroFilter.h b/media/libstagefright/filters/include/filters/ZeroFilter.h
deleted file mode 100644
index f941cc8..0000000
--- a/media/libstagefright/filters/include/filters/ZeroFilter.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ZERO_FILTER_H_
-#define ZERO_FILTER_H_
-
-#include "SimpleFilter.h"
-
-namespace android {
-
-struct ZeroFilter : public SimpleFilter {
-public:
- ZeroFilter() : mInvertData(false) {};
-
- virtual status_t start() { return OK; };
- virtual void reset() {};
- virtual status_t setParameters(const sp<AMessage> &msg);
- virtual status_t processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
-
-protected:
- virtual ~ZeroFilter() {};
-
-private:
- bool mInvertData;
-};
-
-} // namespace android
-
-#endif // ZERO_FILTER_H_
diff --git a/media/libstagefright/filters/saturation.rscript b/media/libstagefright/filters/saturation.rscript
deleted file mode 100644
index 2c867ac..0000000
--- a/media/libstagefright/filters/saturation.rscript
+++ /dev/null
@@ -1,40 +0,0 @@
-// Sample script for RGB888 support (compare to saturationARGB.rs)
-/*
- * Copyright (C) 2014 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 version(1)
-#pragma rs java_package_name(com.android.rs.cppbasic)
-#pragma rs_fp_relaxed
-
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-
-// global variables (parameters accessible to application code)
-float gSaturation = 1.0f;
-
-void root(const uchar3 *v_in, uchar3 *v_out) {
- // scale 0-255 uchar to 0-1.0 float
- float3 in = {v_in->r * 0.003921569f, v_in->g * 0.003921569f,
- v_in->b * 0.003921569f};
-
- // apply saturation filter
- float3 result = dot(in, gMonoMult);
- result = mix(result, in, gSaturation);
-
- // convert to uchar, copied from rsPackColorTo8888
- v_out->x = (uchar)clamp((result.r * 255.f + 0.5f), 0.f, 255.f);
- v_out->y = (uchar)clamp((result.g * 255.f + 0.5f), 0.f, 255.f);
- v_out->z = (uchar)clamp((result.b * 255.f + 0.5f), 0.f, 255.f);
-}
diff --git a/media/libstagefright/filters/saturationARGB.rscript b/media/libstagefright/filters/saturationARGB.rscript
deleted file mode 100644
index 1de9dd8..0000000
--- a/media/libstagefright/filters/saturationARGB.rscript
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2014 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 version(1)
-#pragma rs java_package_name(com.android.rs.cppbasic)
-#pragma rs_fp_relaxed
-
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-
-// global variables (parameters accessible to application code)
-float gSaturation = 1.0f;
-
-void root(const uchar4 *v_in, uchar4 *v_out) {
- v_out->x = v_in->x; // don't modify A
-
- // get RGB, scale 0-255 uchar to 0-1.0 float
- float3 rgb = {v_in->y * 0.003921569f, v_in->z * 0.003921569f,
- v_in->w * 0.003921569f};
-
- // apply saturation filter
- float3 result = dot(rgb, gMonoMult);
- result = mix(result, rgb, gSaturation);
-
- v_out->y = (uchar)clamp((result.r * 255.f + 0.5f), 0.f, 255.f);
- v_out->z = (uchar)clamp((result.g * 255.f + 0.5f), 0.f, 255.f);
- v_out->w = (uchar)clamp((result.b * 255.f + 0.5f), 0.f, 255.f);
-}
diff --git a/media/libstagefright/foundation/tests/AMessage_test.cpp b/media/libstagefright/foundation/tests/AMessage_test.cpp
deleted file mode 100644
index 2b11326..0000000
--- a/media/libstagefright/foundation/tests/AMessage_test.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index da962d1..f3b0600 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -97,6 +97,7 @@
const sp<MediaCodecBuffer> &buffer) override;
virtual status_t renderOutputBuffer(
const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
+ virtual void pollForRenderedBuffers() override;
virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 5a21755..38a4c1e 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -18,6 +18,8 @@
#define A_CODEC_H_
#include <stdint.h>
+#include <list>
+#include <vector>
#include <android/native_window.h>
#include <media/hardware/MetadataBufferType.h>
#include <media/MediaCodecInfo.h>
@@ -265,11 +267,11 @@
sp<AMessage> mBaseOutputFormat;
FrameRenderTracker mRenderTracker; // render information for buffers rendered by ACodec
- Vector<BufferInfo> mBuffers[2];
+ std::vector<BufferInfo> mBuffers[2];
bool mPortEOS[2];
status_t mInputEOSResult;
- List<sp<AMessage> > mDeferredQueue;
+ std::list<sp<AMessage>> mDeferredQueue;
sp<AMessage> mLastOutputFormat;
bool mIsVideo;
diff --git a/media/libstagefright/include/media/stagefright/AudioSource.h b/media/libstagefright/include/media/stagefright/AudioSource.h
index 5e84977..65d5246 100644
--- a/media/libstagefright/include/media/stagefright/AudioSource.h
+++ b/media/libstagefright/include/media/stagefright/AudioSource.h
@@ -21,7 +21,6 @@
#include <media/AudioRecord.h>
#include <media/AudioSystem.h>
#include <media/stagefright/MediaSource.h>
-#include <media/MicrophoneInfo.h>
#include <media/stagefright/MediaBuffer.h>
#include <utils/List.h>
@@ -83,7 +82,7 @@
status_t addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
status_t removeAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
- status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones);
status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
status_t setPreferredMicrophoneFieldDimension(float zoom);
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index 48721ec..aa02151 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -407,6 +407,14 @@
*/
virtual status_t renderOutputBuffer(
const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) = 0;
+
+ /**
+ * Poll for updates about rendered buffers.
+ *
+ * Triggers callbacks to CodecCallback::onOutputFramesRendered.
+ */
+ virtual void pollForRenderedBuffers() = 0;
+
/**
* Discard a buffer to the underlying CodecBase object.
*
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 6644e8e..29b196f 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -18,6 +18,7 @@
#define MEDIA_CODEC_H_
+#include <list>
#include <memory>
#include <vector>
@@ -494,7 +495,7 @@
// stop/flush/reset/release.
Mutex mBufferLock;
- List<size_t> mAvailPortBuffers[2];
+ std::list<size_t> mAvailPortBuffers[2];
std::vector<BufferInfo> mPortBuffers[2];
int32_t mDequeueInputTimeoutGeneration;
@@ -512,7 +513,7 @@
sp<IDescrambler> mDescrambler;
- List<sp<ABuffer> > mCSD;
+ std::list<sp<ABuffer> > mCSD;
sp<AMessage> mActivityNotify;
@@ -628,6 +629,9 @@
// when low latency is on
int64_t mInputBufferCounter; // number of input buffers queued since last reset/flush
+ // A rescheduleable message that periodically polls for rendered buffers
+ sp<AMessage> mMsgPollForRenderedBuffers;
+
class ReleaseSurface;
std::unique_ptr<ReleaseSurface> mReleaseSurface;
diff --git a/media/libstagefright/include/media/stagefright/MediaFilter.h b/media/libstagefright/include/media/stagefright/MediaFilter.h
deleted file mode 100644
index 1255e0f..0000000
--- a/media/libstagefright/include/media/stagefright/MediaFilter.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MEDIA_FILTER_H_
-#define MEDIA_FILTER_H_
-
-#include <media/stagefright/CodecBase.h>
-
-namespace android {
-
-struct GraphicBufferListener;
-struct SimpleFilter;
-
-struct MediaFilter : public CodecBase {
- MediaFilter();
-
- virtual std::shared_ptr<BufferChannelBase> getBufferChannel() override;
- virtual void initiateAllocateComponent(const sp<AMessage> &msg);
- virtual void initiateConfigureComponent(const sp<AMessage> &msg);
- virtual void initiateCreateInputSurface();
- virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface);
-
- virtual void initiateStart();
- virtual void initiateShutdown(bool keepComponentAllocated = false);
-
- virtual void signalFlush();
- virtual void signalResume();
-
- virtual void signalRequestIDRFrame();
- virtual void signalSetParameters(const sp<AMessage> &msg);
- virtual void signalEndOfInputStream();
-
- virtual void onMessageReceived(const sp<AMessage> &msg);
-
-protected:
- virtual ~MediaFilter();
-
-private:
- struct BufferInfo {
- enum Status {
- OWNED_BY_US,
- OWNED_BY_UPSTREAM,
- };
-
- uint32_t mBufferID;
- int32_t mGeneration;
- int32_t mOutputFlags;
- Status mStatus;
-
- sp<MediaCodecBuffer> mData;
- };
-
- class BufferChannel;
-
- enum State {
- UNINITIALIZED,
- INITIALIZED,
- CONFIGURED,
- STARTED,
- };
-
- enum {
- kWhatInputBufferFilled = 'inpF',
- kWhatOutputBufferDrained = 'outD',
- kWhatShutdown = 'shut',
- kWhatFlush = 'flus',
- kWhatResume = 'resm',
- kWhatAllocateComponent = 'allo',
- kWhatConfigureComponent = 'conf',
- kWhatCreateInputSurface = 'cisf',
- kWhatSignalEndOfInputStream = 'eois',
- kWhatStart = 'star',
- kWhatSetParameters = 'setP',
- kWhatProcessBuffers = 'proc',
- };
-
- enum {
- kPortIndexInput = 0,
- kPortIndexOutput = 1
- };
-
- // member variables
- AString mComponentName;
- State mState;
- status_t mInputEOSResult;
- int32_t mWidth, mHeight;
- int32_t mStride, mSliceHeight;
- int32_t mColorFormatIn, mColorFormatOut;
- size_t mMaxInputSize, mMaxOutputSize;
- int32_t mGeneration;
- sp<AMessage> mInputFormat;
- sp<AMessage> mOutputFormat;
-
- Vector<BufferInfo> mBuffers[2];
- Vector<BufferInfo*> mAvailableInputBuffers;
- Vector<BufferInfo*> mAvailableOutputBuffers;
- bool mPortEOS[2];
-
- sp<SimpleFilter> mFilter;
- sp<GraphicBufferListener> mGraphicBufferListener;
-
- std::shared_ptr<BufferChannel> mBufferChannel;
-
- // helper functions
- void signalProcessBuffers();
- void signalError(status_t error);
-
- status_t allocateBuffersOnPort(OMX_U32 portIndex);
- BufferInfo *findBuffer(
- uint32_t portIndex, const sp<MediaCodecBuffer> &buffer,
- ssize_t *index = NULL);
- void postFillThisBuffer(BufferInfo *info);
- void postDrainThisBuffer(BufferInfo *info);
- void postEOS();
- void requestFillEmptyInput();
- void processBuffers();
-
- void onAllocateComponent(const sp<AMessage> &msg);
- void onConfigureComponent(const sp<AMessage> &msg);
- void onStart();
- void onInputBufferFilled(const sp<AMessage> &msg);
- void onOutputBufferDrained(const sp<AMessage> &msg);
- void onShutdown(const sp<AMessage> &msg);
- void onFlush();
- void onSetParameters(const sp<AMessage> &msg);
- void onCreateInputSurface();
- void onInputFrameAvailable();
- void onSignalEndOfInputStream();
-
- DISALLOW_EVIL_CONSTRUCTORS(MediaFilter);
-};
-
-} // namespace android
-
-#endif // MEDIA_FILTER_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaMuxer.h b/media/libstagefright/include/media/stagefright/MediaMuxer.h
index e97a65e..33aaf11 100644
--- a/media/libstagefright/include/media/stagefright/MediaMuxer.h
+++ b/media/libstagefright/include/media/stagefright/MediaMuxer.h
@@ -48,9 +48,13 @@
// deleting the output file after stop.
struct MediaMuxer : public MediaMuxerBase {
public:
- // Construct the muxer with the file descriptor. Note that the MediaMuxer
- // will close this file at stop().
- MediaMuxer(int fd, OutputFormat format);
+ /**
+ * Creates the muxer for a given output format.
+ * @param fd : file descriptor of the output file.
+ * @param format : output format of the muxer. e.g.: webm/mp4/ogg
+ * @return writer's object or nullptr if error.
+ */
+ static MediaMuxer* create(int fd, OutputFormat format);
virtual ~MediaMuxer();
@@ -127,6 +131,11 @@
sp<AMessage> getTrackFormat(size_t idx);
private:
+ // Construct the muxer with the file descriptor. Note that the MediaMuxer
+ // will close this file at stop().
+ // This constructor is made private to ensure that MediaMuxer::create() is used instead.
+ MediaMuxer(int fd, OutputFormat format);
+
const OutputFormat mFormat;
sp<MediaWriter> mWriter;
Vector< sp<MediaAdapter> > mTrackList; // Each track has its MediaAdapter.
diff --git a/media/libstagefright/include/media/stagefright/MediaWriter.h b/media/libstagefright/include/media/stagefright/MediaWriter.h
index 9f20185..2b14811 100644
--- a/media/libstagefright/include/media/stagefright/MediaWriter.h
+++ b/media/libstagefright/include/media/stagefright/MediaWriter.h
@@ -31,6 +31,29 @@
mMaxFileDurationLimitUs(0) {
}
+ // Returns true if the file descriptor is opened using a mode
+ // which meets minimum writer/muxer requirements.
+ static bool isFdOpenModeValid(int fd) {
+ // check for invalid file descriptor.
+ int flags = fcntl(fd, F_GETFL);
+ if (flags == -1) {
+ ALOGE("Invalid File Status Flags and/or mode : %d", flags);
+ return false;
+ }
+ // fd must be in read-write mode or write-only mode.
+ if ((flags & (O_RDWR | O_WRONLY)) == 0) {
+ ALOGE("File must be writable");
+ return false;
+ }
+ // Verify fd is seekable
+ off64_t off = lseek64(fd, 0, SEEK_SET);
+ if (off < 0) {
+ ALOGE("File descriptor is not seekable");
+ return false;
+ }
+ return true;
+ }
+
virtual status_t addSource(const sp<MediaSource> &source) = 0;
virtual bool reachedEOS() = 0;
virtual status_t start(MetaData *params = NULL) = 0;
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index 31faafb..a7d2eb9 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -117,6 +117,12 @@
kKeyVideoProfile = 'vprf', // int32_t
kKeyVideoLevel = 'vlev', // int32_t
+ // audio profile and level
+ // The codec framework doesn't distinguish between video and audio profiles,
+ // so there is no need to define a separate key
+ kKeyAudioProfile = 'vprf', // int32_t
+ kKeyAudioLevel = 'vlev', // int32_t
+
kKey2ByteNalLength = '2NAL', // int32_t (bool)
// Identify the file output format for authoring
@@ -278,6 +284,18 @@
kKeyLastSampleIndexInChunk = 'lsic', //int64_t, index of last sample in a chunk.
kKeySampleTimeBeforeAppend = 'lsba', // int64_t, timestamp of last sample of a track.
+ // DVB component tag
+ kKeyDvbComponentTag = 'copt', // int32_t, component tag for DVB video/audio/subtitle
+
+ // DVB audio description
+ kKeyDvbAudioDescription = 'addt', // bool (int32_t), DVB audio description only defined for
+ // audio component
+
+ // DVB teletext magazine number
+ kKeyDvbTeletextMagazineNumber = 'ttxm', // int32_t, DVB teletext magazine number
+
+ // DVB teletext page number
+ kKeyDvbTeletextPageNumber = 'ttxp', // int32_t, DVB teletext page number
};
enum {
diff --git a/media/libstagefright/include/media/stagefright/RenderScriptWrapper.h b/media/libstagefright/include/media/stagefright/RenderScriptWrapper.h
deleted file mode 100644
index b42649e..0000000
--- a/media/libstagefright/include/media/stagefright/RenderScriptWrapper.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RENDERSCRIPT_WRAPPER_H_
-#define RENDERSCRIPT_WRAPPER_H_
-
-#include <RenderScript.h>
-
-namespace android {
-
-struct RenderScriptWrapper : public RefBase {
-public:
- struct RSFilterCallback : public RefBase {
- public:
- // called by RSFilter to process each input buffer
- virtual status_t processBuffers(
- RSC::Allocation* inBuffer,
- RSC::Allocation* outBuffer) = 0;
-
- virtual status_t handleSetParameters(const sp<AMessage> &msg) = 0;
- };
-
- sp<RSFilterCallback> mCallback;
- RSC::sp<RSC::RS> mContext;
-};
-
-} // namespace android
-
-#endif // RENDERSCRIPT_WRAPPER_H_
diff --git a/media/libstagefright/renderfright/Android.bp b/media/libstagefright/renderfright/Android.bp
index 3c00a1c..3598e8d 100644
--- a/media/libstagefright/renderfright/Android.bp
+++ b/media/libstagefright/renderfright/Android.bp
@@ -32,6 +32,7 @@
"libEGL",
"libGLESv1_CM",
"libGLESv2",
+ "libvulkan",
"liblog",
"libnativewindow",
"libprocessgroup",
diff --git a/media/libstagefright/renderfright/gl/ProgramCache.cpp b/media/libstagefright/renderfright/gl/ProgramCache.cpp
index 56d35a9..af55172 100644
--- a/media/libstagefright/renderfright/gl/ProgramCache.cpp
+++ b/media/libstagefright/renderfright/gl/ProgramCache.cpp
@@ -373,7 +373,11 @@
return color * slope;
} else if (nits < x1) {
// scale [x0, x1] to [y0, y1] linearly
- float slope = (y1 - y0) / (x1 - x0);
+ // Use highp since some compilers may do this
+ // operation as reciprocal multiplication with
+ // re-association that could exceed the range
+ // of mediump float.
+ highp float slope = (y1 - y0) / (x1 - x0);
nits = y0 + (nits - x0) * slope;
} else if (nits < x2) {
// scale [x1, x2] to [y1, y2] using Hermite interp
diff --git a/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp b/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
index c43e1f8..19c8577 100644
--- a/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
+++ b/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <fstream>
+#include <memory>
#include <media/stagefright/foundation/ABitReader.h>
#include <HevcUtils.h>
@@ -88,10 +89,10 @@
stringLine >> type >> chunkLength;
ASSERT_GT(chunkLength, 0) << "Length of data chunk must be greater than 0";
- char *data = (char *)malloc(chunkLength);
+ std::unique_ptr<char[]> data(new char[chunkLength]);
ASSERT_NE(data, nullptr) << "Failed to allocate data buffer of size: " << chunkLength;
- mMediaFileStream.read(data, chunkLength);
+ mMediaFileStream.read(data.get(), chunkLength);
ASSERT_EQ(mMediaFileStream.gcount(), chunkLength)
<< "Failed to read complete file, bytes read: " << mMediaFileStream.gcount();
@@ -105,7 +106,7 @@
offset += 3;
ASSERT_LE(offset, chunkLength) << "NAL unit offset must not exceed the chunk length";
- uint8_t *nalUnit = (uint8_t *)(data + offset);
+ uint8_t *nalUnit = (uint8_t *)(data.get() + offset);
size_t nalUnitLength = chunkLength - offset;
// Add NAL units only if they're of type: VPS/SPS/PPS/SEI
@@ -118,20 +119,18 @@
size_t sizeNalUnit = hevcParams.getSize(index);
ASSERT_EQ(sizeNalUnit, nalUnitLength) << "Invalid size returned for NAL: " << type;
- uint8_t *destination = (uint8_t *)malloc(nalUnitLength);
+ std::unique_ptr<uint8_t[]> destination(new uint8_t[nalUnitLength]);
ASSERT_NE(destination, nullptr)
<< "Failed to allocate buffer of size: " << nalUnitLength;
- bool status = hevcParams.write(index, destination, nalUnitLength);
+ bool status = hevcParams.write(index, destination.get(), nalUnitLength);
ASSERT_TRUE(status) << "Unable to write NAL Unit data";
- free(destination);
index++;
} else {
err = hevcParams.addNalUnit(nalUnit, nalUnitLength);
ASSERT_NE(err, (status_t)OK) << "Invalid NAL Unit added, type: " << type;
}
- free(data);
}
size_t numNalUnits = hevcParams.getNumNalUnitsOfType(kVPSCode);
@@ -166,10 +165,10 @@
<< "Expected NAL type: 34(PPS), found: " << typeNalUnit;
size_t hvccBoxSize = kHvccBoxMaxSize;
- uint8_t *hvcc = (uint8_t *)malloc(kHvccBoxMaxSize);
+ std::unique_ptr<uint8_t[]> hvcc(new uint8_t[kHvccBoxMaxSize]);
ASSERT_NE(hvcc, nullptr) << "Failed to allocate a hvcc buffer of size: " << kHvccBoxMaxSize;
- err = hevcParams.makeHvcc(hvcc, &hvccBoxSize, kNALSizeLength);
+ err = hevcParams.makeHvcc(hvcc.get(), &hvccBoxSize, kNALSizeLength);
ASSERT_EQ(err, (status_t)OK) << "Unable to create hvcc box";
ASSERT_GT(hvccBoxSize, kHvccBoxMinSize)
@@ -179,8 +178,6 @@
if (frameRate != mFrameRate)
cout << "[ WARN ] Expected frame rate: " << mFrameRate << " Found: " << frameRate
<< endl;
-
- free(hvcc);
}
// Info File contains the type and length for each chunk/frame
diff --git a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
index d94c8ff..9f46a74 100644
--- a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
+++ b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
@@ -66,8 +66,8 @@
for (size_t i = 0; i < extractor->countTracks(); ++i) {
sp<MetaData> meta = extractor->getTrackMetaData(i);
- const char *trackMime;
- if (!strcasecmp(mime.c_str(), trackMime)) {
+ std::string trackMime = dataProvider->PickValueInArray(kTestedMimeTypes);
+ if (!strcasecmp(mime.c_str(), trackMime.c_str())) {
sp<IMediaSource> track = extractor->getTrack(i);
if (track == NULL) {
return NULL;
diff --git a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
index 98bfb94..6856ac0 100644
--- a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
+++ b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
@@ -42,6 +42,51 @@
kMaxValue = MPEG2TS,
};
+static std::string kTestedMimeTypes[] = {"audio/3gpp",
+ "audio/amr-wb",
+ "audio/vorbis",
+ "audio/opus",
+ "audio/mp4a-latm",
+ "audio/mpeg",
+ "audio/mpeg-L1",
+ "audio/mpeg-L2",
+ "audio/midi",
+ "audio/qcelp",
+ "audio/g711-alaw",
+ "audio/g711-mlaw",
+ "audio/flac",
+ "audio/aac-adts",
+ "audio/gsm",
+ "audio/ac3",
+ "audio/eac3",
+ "audio/eac3-joc",
+ "audio/ac4",
+ "audio/scrambled",
+ "audio/alac",
+ "audio/x-ms-wma",
+ "audio/x-adpcm-ms",
+ "audio/x-adpcm-dvi-ima",
+ "video/avc",
+ "video/hevc",
+ "video/mp4v-es",
+ "video/3gpp",
+ "video/x-vnd.on2.vp8",
+ "video/x-vnd.on2.vp9",
+ "video/av01",
+ "video/mpeg2",
+ "video/dolby-vision",
+ "video/scrambled",
+ "video/divx",
+ "video/divx3",
+ "video/xvid",
+ "video/x-motion-jpeg",
+ "text/3gpp-tt",
+ "application/x-subrip",
+ "text/vtt",
+ "text/cea-608",
+ "text/cea-708",
+ "application/x-id3v4"};
+
std::string genMimeType(FuzzedDataProvider *dataProvider);
sp<IMediaExtractor> genMediaExtractor(FuzzedDataProvider *dataProvider, uint16_t dataAmount);
sp<MediaSource> genMediaSource(FuzzedDataProvider *dataProvider, uint16_t maxMediaBlobSize);
diff --git a/media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.cpp b/media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.cpp
index 5df3267..70d73c8 100644
--- a/media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.cpp
+++ b/media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.cpp
@@ -52,7 +52,10 @@
MediaMuxer::OutputFormat format =
(MediaMuxer::OutputFormat)fdp.ConsumeIntegralInRange<int32_t>(0, 4);
- sp<MediaMuxer> mMuxer(new MediaMuxer(fd, format));
+ sp<MediaMuxer> mMuxer = MediaMuxer::create(fd, format);
+ if (mMuxer == nullptr) {
+ return 0;
+ }
while (fdp.remaining_bytes() > 1) {
switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 4)) {
diff --git a/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp b/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
index a8e64b6..ecdaac5 100644
--- a/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
+++ b/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
@@ -70,6 +70,7 @@
MOCK_METHOD(status_t, discardBuffer, (const sp<MediaCodecBuffer> &buffer), (override));
MOCK_METHOD(void, getInputBufferArray, (Vector<sp<MediaCodecBuffer>> *array), (override));
MOCK_METHOD(void, getOutputBufferArray, (Vector<sp<MediaCodecBuffer>> *array), (override));
+ MOCK_METHOD(void, pollForRenderedBuffers, (), (override));
};
class MockCodec : public CodecBase {
diff --git a/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp b/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
index f934b54..b2044d3 100644
--- a/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
+++ b/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
@@ -22,6 +22,7 @@
#include <string.h>
#include <sys/stat.h>
#include <fstream>
+#include <memory>
#include <binder/Parcel.h>
#include <media/stagefright/foundation/AString.h>
@@ -240,10 +241,10 @@
if (remaining < tempFontNameLength) break;
const uint8_t *tmpFont = tmpData;
- char *tmpFontName = strndup((const char *)tmpFont, tempFontNameLength);
+ std::unique_ptr<char[]> tmpFontName(new char[tempFontNameLength]);
+ strncpy(tmpFontName.get(), (const char *)tmpFont, tempFontNameLength);
ASSERT_NE(tmpFontName, nullptr) << "Font Name is null";
- ALOGI("FontName = %s", tmpFontName);
- free(tmpFontName);
+ ALOGI("FontName = %s", tmpFontName.get());
tmpData += tempFontNameLength;
remaining -= tempFontNameLength;
fontRecordEntries.push_back({tempFontID, tempFontNameLength, tmpFont});
diff --git a/media/libstagefright/webm/WebmFrameThread.cpp b/media/libstagefright/webm/WebmFrameThread.cpp
index 59ce8db..cdbd745 100644
--- a/media/libstagefright/webm/WebmFrameThread.cpp
+++ b/media/libstagefright/webm/WebmFrameThread.cpp
@@ -197,7 +197,6 @@
}
status_t WebmFrameSinkThread::stop() {
- mDone = true;
mVideoFrames.push(WebmFrame::EOS);
mAudioFrames.push(WebmFrame::EOS);
return WebmFrameThread::stop();
diff --git a/media/libstagefright/webm/WebmWriter.cpp b/media/libstagefright/webm/WebmWriter.cpp
index 5eaadbd..3823c36 100644
--- a/media/libstagefright/webm/WebmWriter.cpp
+++ b/media/libstagefright/webm/WebmWriter.cpp
@@ -54,6 +54,19 @@
static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
+bool WebmWriter::isFdOpenModeValid(int fd) {
+ // check for invalid file descriptor.
+ if (!MediaWriter::isFdOpenModeValid(fd)) {
+ return false;
+ }
+ int flags = fcntl(fd, F_GETFL);
+ if ((flags & O_RDWR) == 0) {
+ ALOGE("File must be in read-write mode for webm writer");
+ return false;
+ }
+ return true;
+}
+
WebmWriter::WebmWriter(int fd)
: mFd(dup(fd)),
mInitCheck(mFd < 0 ? NO_INIT : OK),
diff --git a/media/libstagefright/webm/include/webm/WebmWriter.h b/media/libstagefright/webm/include/webm/WebmWriter.h
index ed5bc4c..e339add 100644
--- a/media/libstagefright/webm/include/webm/WebmWriter.h
+++ b/media/libstagefright/webm/include/webm/WebmWriter.h
@@ -36,6 +36,10 @@
class WebmWriter : public MediaWriter {
public:
+ // Returns true if the file descriptor is opened using a mode
+ // which is compatible with WebmWriter.
+ // Note that this overloads that method in the base class.
+ static bool isFdOpenModeValid(int fd);
explicit WebmWriter(int fd);
~WebmWriter() { reset(); }
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index edddaa4..19f9549 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -26,7 +26,33 @@
],
}
-cc_binary {
+prebuilt_etc {
+ name: "mediaserver.zygote64_32.rc",
+ src: "mediaserver.zygote64_32.rc",
+ sub_dir: "init/hw",
+}
+
+prebuilt_etc {
+ name: "mediaserver.zygote64.rc",
+ src: "mediaserver.zygote64.rc",
+ sub_dir: "init/hw",
+}
+
+soong_config_module_type {
+ name: "mediaserver_cc_binary",
+ module_type: "cc_binary",
+ config_namespace: "ANDROID",
+ bool_variables: ["TARGET_DYNAMIC_64_32_MEDIASERVER"],
+ properties: [
+ "compile_multilib",
+ "init_rc",
+ "multilib.lib32.suffix",
+ "multilib.lib64.suffix",
+ "required",
+ ],
+}
+
+mediaserver_cc_binary {
name: "mediaserver",
srcs: ["main_mediaserver.cpp"],
@@ -55,12 +81,32 @@
// ****************************************************************
compile_multilib: "prefer32",
- init_rc: ["mediaserver.rc"],
-
cflags: [
"-Werror",
"-Wall",
],
vintf_fragments: ["manifest_media_c2_software.xml"],
+
+ soong_config_variables: {
+ TARGET_DYNAMIC_64_32_MEDIASERVER: {
+ compile_multilib: "both",
+ multilib: {
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
+ },
+ required: [
+ "mediaserver.zygote64_32.rc",
+ "mediaserver.zygote64.rc",
+ ],
+ init_rc: ["mediaserver_dynamic.rc"],
+ conditions_default: {
+ init_rc: ["mediaserver.rc"],
+ },
+ },
+ },
}
diff --git a/media/mediaserver/mediaserver.zygote64.rc b/media/mediaserver/mediaserver.zygote64.rc
new file mode 100644
index 0000000..8842b01
--- /dev/null
+++ b/media/mediaserver/mediaserver.zygote64.rc
@@ -0,0 +1,6 @@
+service media /system/bin/mediaserver64
+ class main
+ user media
+ group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh HighPerformance
diff --git a/media/mediaserver/mediaserver.zygote64_32.rc b/media/mediaserver/mediaserver.zygote64_32.rc
new file mode 100644
index 0000000..4039073
--- /dev/null
+++ b/media/mediaserver/mediaserver.zygote64_32.rc
@@ -0,0 +1,6 @@
+service media /system/bin/mediaserver32
+ class main
+ user media
+ group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh HighPerformance
diff --git a/media/mediaserver/mediaserver_dynamic.rc b/media/mediaserver/mediaserver_dynamic.rc
new file mode 100644
index 0000000..65d5c40
--- /dev/null
+++ b/media/mediaserver/mediaserver_dynamic.rc
@@ -0,0 +1,4 @@
+on property:init.svc.media=*
+ setprop init.svc.mediadrm ${init.svc.media}
+
+import /system/etc/init/hw/mediaserver.${ro.zygote}.rc
diff --git a/media/libstagefright/bqhelper/Android.bp b/media/module/bqhelper/Android.bp
similarity index 97%
rename from media/libstagefright/bqhelper/Android.bp
rename to media/module/bqhelper/Android.bp
index 0e2b472..df658ee 100644
--- a/media/libstagefright/bqhelper/Android.bp
+++ b/media/module/bqhelper/Android.bp
@@ -4,7 +4,6 @@
// all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
}
cc_defaults {
diff --git a/media/libstagefright/bqhelper/FrameDropper.cpp b/media/module/bqhelper/FrameDropper.cpp
similarity index 100%
rename from media/libstagefright/bqhelper/FrameDropper.cpp
rename to media/module/bqhelper/FrameDropper.cpp
diff --git a/media/libstagefright/bqhelper/GraphicBufferSource.cpp b/media/module/bqhelper/GraphicBufferSource.cpp
similarity index 100%
rename from media/libstagefright/bqhelper/GraphicBufferSource.cpp
rename to media/module/bqhelper/GraphicBufferSource.cpp
diff --git a/media/libstagefright/bqhelper/TEST_MAPPING b/media/module/bqhelper/TEST_MAPPING
similarity index 100%
rename from media/libstagefright/bqhelper/TEST_MAPPING
rename to media/module/bqhelper/TEST_MAPPING
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/ComponentWrapper.h b/media/module/bqhelper/include/media/stagefright/bqhelper/ComponentWrapper.h
similarity index 100%
rename from media/libstagefright/bqhelper/include/media/stagefright/bqhelper/ComponentWrapper.h
rename to media/module/bqhelper/include/media/stagefright/bqhelper/ComponentWrapper.h
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/FrameDropper.h b/media/module/bqhelper/include/media/stagefright/bqhelper/FrameDropper.h
similarity index 100%
rename from media/libstagefright/bqhelper/include/media/stagefright/bqhelper/FrameDropper.h
rename to media/module/bqhelper/include/media/stagefright/bqhelper/FrameDropper.h
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h b/media/module/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
similarity index 100%
rename from media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
rename to media/module/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
diff --git a/media/libstagefright/bqhelper/tests/Android.bp b/media/module/bqhelper/tests/Android.bp
similarity index 88%
rename from media/libstagefright/bqhelper/tests/Android.bp
rename to media/module/bqhelper/tests/Android.bp
index 95953ee..3004ec4 100644
--- a/media/libstagefright/bqhelper/tests/Android.bp
+++ b/media/module/bqhelper/tests/Android.bp
@@ -4,7 +4,6 @@
// all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
}
cc_test {
diff --git a/media/libstagefright/bqhelper/tests/FrameDropper_test.cpp b/media/module/bqhelper/tests/FrameDropper_test.cpp
similarity index 100%
rename from media/libstagefright/bqhelper/tests/FrameDropper_test.cpp
rename to media/module/bqhelper/tests/FrameDropper_test.cpp
diff --git a/media/bufferpool/1.0/Accessor.cpp b/media/module/bufferpool/1.0/Accessor.cpp
similarity index 100%
rename from media/bufferpool/1.0/Accessor.cpp
rename to media/module/bufferpool/1.0/Accessor.cpp
diff --git a/media/bufferpool/1.0/Accessor.h b/media/module/bufferpool/1.0/Accessor.h
similarity index 100%
rename from media/bufferpool/1.0/Accessor.h
rename to media/module/bufferpool/1.0/Accessor.h
diff --git a/media/bufferpool/1.0/AccessorImpl.cpp b/media/module/bufferpool/1.0/AccessorImpl.cpp
similarity index 100%
rename from media/bufferpool/1.0/AccessorImpl.cpp
rename to media/module/bufferpool/1.0/AccessorImpl.cpp
diff --git a/media/bufferpool/1.0/AccessorImpl.h b/media/module/bufferpool/1.0/AccessorImpl.h
similarity index 100%
rename from media/bufferpool/1.0/AccessorImpl.h
rename to media/module/bufferpool/1.0/AccessorImpl.h
diff --git a/media/bufferpool/1.0/Android.bp b/media/module/bufferpool/1.0/Android.bp
similarity index 100%
rename from media/bufferpool/1.0/Android.bp
rename to media/module/bufferpool/1.0/Android.bp
diff --git a/media/bufferpool/1.0/BufferPoolClient.cpp b/media/module/bufferpool/1.0/BufferPoolClient.cpp
similarity index 100%
rename from media/bufferpool/1.0/BufferPoolClient.cpp
rename to media/module/bufferpool/1.0/BufferPoolClient.cpp
diff --git a/media/bufferpool/1.0/BufferPoolClient.h b/media/module/bufferpool/1.0/BufferPoolClient.h
similarity index 100%
rename from media/bufferpool/1.0/BufferPoolClient.h
rename to media/module/bufferpool/1.0/BufferPoolClient.h
diff --git a/media/bufferpool/1.0/BufferStatus.cpp b/media/module/bufferpool/1.0/BufferStatus.cpp
similarity index 100%
rename from media/bufferpool/1.0/BufferStatus.cpp
rename to media/module/bufferpool/1.0/BufferStatus.cpp
diff --git a/media/bufferpool/1.0/BufferStatus.h b/media/module/bufferpool/1.0/BufferStatus.h
similarity index 100%
rename from media/bufferpool/1.0/BufferStatus.h
rename to media/module/bufferpool/1.0/BufferStatus.h
diff --git a/media/bufferpool/1.0/ClientManager.cpp b/media/module/bufferpool/1.0/ClientManager.cpp
similarity index 100%
rename from media/bufferpool/1.0/ClientManager.cpp
rename to media/module/bufferpool/1.0/ClientManager.cpp
diff --git a/media/bufferpool/1.0/Connection.cpp b/media/module/bufferpool/1.0/Connection.cpp
similarity index 100%
rename from media/bufferpool/1.0/Connection.cpp
rename to media/module/bufferpool/1.0/Connection.cpp
diff --git a/media/bufferpool/1.0/Connection.h b/media/module/bufferpool/1.0/Connection.h
similarity index 100%
rename from media/bufferpool/1.0/Connection.h
rename to media/module/bufferpool/1.0/Connection.h
diff --git a/media/bufferpool/1.0/TEST_MAPPING b/media/module/bufferpool/1.0/TEST_MAPPING
similarity index 100%
rename from media/bufferpool/1.0/TEST_MAPPING
rename to media/module/bufferpool/1.0/TEST_MAPPING
diff --git a/media/bufferpool/1.0/include/bufferpool/BufferPoolTypes.h b/media/module/bufferpool/1.0/include/bufferpool/BufferPoolTypes.h
similarity index 100%
rename from media/bufferpool/1.0/include/bufferpool/BufferPoolTypes.h
rename to media/module/bufferpool/1.0/include/bufferpool/BufferPoolTypes.h
diff --git a/media/bufferpool/1.0/include/bufferpool/ClientManager.h b/media/module/bufferpool/1.0/include/bufferpool/ClientManager.h
similarity index 100%
rename from media/bufferpool/1.0/include/bufferpool/ClientManager.h
rename to media/module/bufferpool/1.0/include/bufferpool/ClientManager.h
diff --git a/media/bufferpool/1.0/vts/Android.bp b/media/module/bufferpool/1.0/vts/Android.bp
similarity index 100%
rename from media/bufferpool/1.0/vts/Android.bp
rename to media/module/bufferpool/1.0/vts/Android.bp
diff --git a/media/bufferpool/1.0/vts/OWNERS b/media/module/bufferpool/1.0/vts/OWNERS
similarity index 100%
rename from media/bufferpool/1.0/vts/OWNERS
rename to media/module/bufferpool/1.0/vts/OWNERS
diff --git a/media/bufferpool/1.0/vts/allocator.cpp b/media/module/bufferpool/1.0/vts/allocator.cpp
similarity index 100%
rename from media/bufferpool/1.0/vts/allocator.cpp
rename to media/module/bufferpool/1.0/vts/allocator.cpp
diff --git a/media/bufferpool/1.0/vts/allocator.h b/media/module/bufferpool/1.0/vts/allocator.h
similarity index 100%
rename from media/bufferpool/1.0/vts/allocator.h
rename to media/module/bufferpool/1.0/vts/allocator.h
diff --git a/media/bufferpool/1.0/vts/multi.cpp b/media/module/bufferpool/1.0/vts/multi.cpp
similarity index 100%
rename from media/bufferpool/1.0/vts/multi.cpp
rename to media/module/bufferpool/1.0/vts/multi.cpp
diff --git a/media/bufferpool/1.0/vts/single.cpp b/media/module/bufferpool/1.0/vts/single.cpp
similarity index 100%
rename from media/bufferpool/1.0/vts/single.cpp
rename to media/module/bufferpool/1.0/vts/single.cpp
diff --git a/media/bufferpool/2.0/Accessor.cpp b/media/module/bufferpool/2.0/Accessor.cpp
similarity index 100%
rename from media/bufferpool/2.0/Accessor.cpp
rename to media/module/bufferpool/2.0/Accessor.cpp
diff --git a/media/bufferpool/2.0/Accessor.h b/media/module/bufferpool/2.0/Accessor.h
similarity index 100%
rename from media/bufferpool/2.0/Accessor.h
rename to media/module/bufferpool/2.0/Accessor.h
diff --git a/media/bufferpool/2.0/AccessorImpl.cpp b/media/module/bufferpool/2.0/AccessorImpl.cpp
similarity index 100%
rename from media/bufferpool/2.0/AccessorImpl.cpp
rename to media/module/bufferpool/2.0/AccessorImpl.cpp
diff --git a/media/bufferpool/2.0/AccessorImpl.h b/media/module/bufferpool/2.0/AccessorImpl.h
similarity index 100%
rename from media/bufferpool/2.0/AccessorImpl.h
rename to media/module/bufferpool/2.0/AccessorImpl.h
diff --git a/media/bufferpool/2.0/Android.bp b/media/module/bufferpool/2.0/Android.bp
similarity index 100%
rename from media/bufferpool/2.0/Android.bp
rename to media/module/bufferpool/2.0/Android.bp
diff --git a/media/bufferpool/2.0/BufferPoolClient.cpp b/media/module/bufferpool/2.0/BufferPoolClient.cpp
similarity index 100%
rename from media/bufferpool/2.0/BufferPoolClient.cpp
rename to media/module/bufferpool/2.0/BufferPoolClient.cpp
diff --git a/media/bufferpool/2.0/BufferPoolClient.h b/media/module/bufferpool/2.0/BufferPoolClient.h
similarity index 100%
rename from media/bufferpool/2.0/BufferPoolClient.h
rename to media/module/bufferpool/2.0/BufferPoolClient.h
diff --git a/media/bufferpool/2.0/BufferStatus.cpp b/media/module/bufferpool/2.0/BufferStatus.cpp
similarity index 100%
rename from media/bufferpool/2.0/BufferStatus.cpp
rename to media/module/bufferpool/2.0/BufferStatus.cpp
diff --git a/media/bufferpool/2.0/BufferStatus.h b/media/module/bufferpool/2.0/BufferStatus.h
similarity index 100%
rename from media/bufferpool/2.0/BufferStatus.h
rename to media/module/bufferpool/2.0/BufferStatus.h
diff --git a/media/bufferpool/2.0/ClientManager.cpp b/media/module/bufferpool/2.0/ClientManager.cpp
similarity index 100%
rename from media/bufferpool/2.0/ClientManager.cpp
rename to media/module/bufferpool/2.0/ClientManager.cpp
diff --git a/media/bufferpool/2.0/Connection.cpp b/media/module/bufferpool/2.0/Connection.cpp
similarity index 100%
rename from media/bufferpool/2.0/Connection.cpp
rename to media/module/bufferpool/2.0/Connection.cpp
diff --git a/media/bufferpool/2.0/Connection.h b/media/module/bufferpool/2.0/Connection.h
similarity index 100%
rename from media/bufferpool/2.0/Connection.h
rename to media/module/bufferpool/2.0/Connection.h
diff --git a/media/bufferpool/2.0/Observer.cpp b/media/module/bufferpool/2.0/Observer.cpp
similarity index 100%
rename from media/bufferpool/2.0/Observer.cpp
rename to media/module/bufferpool/2.0/Observer.cpp
diff --git a/media/bufferpool/2.0/Observer.h b/media/module/bufferpool/2.0/Observer.h
similarity index 100%
rename from media/bufferpool/2.0/Observer.h
rename to media/module/bufferpool/2.0/Observer.h
diff --git a/media/bufferpool/2.0/TEST_MAPPING b/media/module/bufferpool/2.0/TEST_MAPPING
similarity index 100%
rename from media/bufferpool/2.0/TEST_MAPPING
rename to media/module/bufferpool/2.0/TEST_MAPPING
diff --git a/media/bufferpool/2.0/include/bufferpool/BufferPoolTypes.h b/media/module/bufferpool/2.0/include/bufferpool/BufferPoolTypes.h
similarity index 100%
rename from media/bufferpool/2.0/include/bufferpool/BufferPoolTypes.h
rename to media/module/bufferpool/2.0/include/bufferpool/BufferPoolTypes.h
diff --git a/media/bufferpool/2.0/include/bufferpool/ClientManager.h b/media/module/bufferpool/2.0/include/bufferpool/ClientManager.h
similarity index 100%
rename from media/bufferpool/2.0/include/bufferpool/ClientManager.h
rename to media/module/bufferpool/2.0/include/bufferpool/ClientManager.h
diff --git a/media/bufferpool/2.0/tests/Android.bp b/media/module/bufferpool/2.0/tests/Android.bp
similarity index 100%
rename from media/bufferpool/2.0/tests/Android.bp
rename to media/module/bufferpool/2.0/tests/Android.bp
diff --git a/media/bufferpool/2.0/tests/AndroidTest.xml b/media/module/bufferpool/2.0/tests/AndroidTest.xml
similarity index 100%
rename from media/bufferpool/2.0/tests/AndroidTest.xml
rename to media/module/bufferpool/2.0/tests/AndroidTest.xml
diff --git a/media/bufferpool/2.0/tests/BufferpoolUnitTest.cpp b/media/module/bufferpool/2.0/tests/BufferpoolUnitTest.cpp
similarity index 100%
rename from media/bufferpool/2.0/tests/BufferpoolUnitTest.cpp
rename to media/module/bufferpool/2.0/tests/BufferpoolUnitTest.cpp
diff --git a/media/bufferpool/2.0/tests/OWNERS b/media/module/bufferpool/2.0/tests/OWNERS
similarity index 100%
rename from media/bufferpool/2.0/tests/OWNERS
rename to media/module/bufferpool/2.0/tests/OWNERS
diff --git a/media/bufferpool/2.0/tests/README.md b/media/module/bufferpool/2.0/tests/README.md
similarity index 100%
rename from media/bufferpool/2.0/tests/README.md
rename to media/module/bufferpool/2.0/tests/README.md
diff --git a/media/bufferpool/2.0/tests/allocator.cpp b/media/module/bufferpool/2.0/tests/allocator.cpp
similarity index 100%
rename from media/bufferpool/2.0/tests/allocator.cpp
rename to media/module/bufferpool/2.0/tests/allocator.cpp
diff --git a/media/bufferpool/2.0/tests/allocator.h b/media/module/bufferpool/2.0/tests/allocator.h
similarity index 100%
rename from media/bufferpool/2.0/tests/allocator.h
rename to media/module/bufferpool/2.0/tests/allocator.h
diff --git a/media/bufferpool/2.0/tests/cond.cpp b/media/module/bufferpool/2.0/tests/cond.cpp
similarity index 100%
rename from media/bufferpool/2.0/tests/cond.cpp
rename to media/module/bufferpool/2.0/tests/cond.cpp
diff --git a/media/bufferpool/2.0/tests/multi.cpp b/media/module/bufferpool/2.0/tests/multi.cpp
similarity index 100%
rename from media/bufferpool/2.0/tests/multi.cpp
rename to media/module/bufferpool/2.0/tests/multi.cpp
diff --git a/media/bufferpool/2.0/tests/single.cpp b/media/module/bufferpool/2.0/tests/single.cpp
similarity index 100%
rename from media/bufferpool/2.0/tests/single.cpp
rename to media/module/bufferpool/2.0/tests/single.cpp
diff --git a/media/codecs/amrnb/TEST_MAPPING b/media/module/codecs/amrnb/TEST_MAPPING
similarity index 100%
rename from media/codecs/amrnb/TEST_MAPPING
rename to media/module/codecs/amrnb/TEST_MAPPING
diff --git a/media/codecs/amrnb/common/Android.bp b/media/module/codecs/amrnb/common/Android.bp
similarity index 100%
rename from media/codecs/amrnb/common/Android.bp
rename to media/module/codecs/amrnb/common/Android.bp
diff --git a/media/codecs/amrnb/common/MODULE_LICENSE_APACHE2 b/media/module/codecs/amrnb/common/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/amrnb/common/MODULE_LICENSE_APACHE2
rename to media/module/codecs/amrnb/common/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/amrnb/common/NOTICE b/media/module/codecs/amrnb/common/NOTICE
similarity index 100%
rename from media/codecs/amrnb/common/NOTICE
rename to media/module/codecs/amrnb/common/NOTICE
diff --git a/media/codecs/amrnb/common/include/abs_s.h b/media/module/codecs/amrnb/common/include/abs_s.h
similarity index 100%
rename from media/codecs/amrnb/common/include/abs_s.h
rename to media/module/codecs/amrnb/common/include/abs_s.h
diff --git a/media/codecs/amrnb/common/include/add.h b/media/module/codecs/amrnb/common/include/add.h
similarity index 100%
rename from media/codecs/amrnb/common/include/add.h
rename to media/module/codecs/amrnb/common/include/add.h
diff --git a/media/codecs/amrnb/common/include/az_lsp.h b/media/module/codecs/amrnb/common/include/az_lsp.h
similarity index 100%
rename from media/codecs/amrnb/common/include/az_lsp.h
rename to media/module/codecs/amrnb/common/include/az_lsp.h
diff --git a/media/codecs/amrnb/common/include/basic_op.h b/media/module/codecs/amrnb/common/include/basic_op.h
similarity index 100%
rename from media/codecs/amrnb/common/include/basic_op.h
rename to media/module/codecs/amrnb/common/include/basic_op.h
diff --git a/media/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h b/media/module/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h
similarity index 100%
rename from media/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h
rename to media/module/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h
diff --git a/media/codecs/amrnb/common/include/basic_op_arm_v5.h b/media/module/codecs/amrnb/common/include/basic_op_arm_v5.h
similarity index 100%
rename from media/codecs/amrnb/common/include/basic_op_arm_v5.h
rename to media/module/codecs/amrnb/common/include/basic_op_arm_v5.h
diff --git a/media/codecs/amrnb/common/include/basic_op_c_equivalent.h b/media/module/codecs/amrnb/common/include/basic_op_c_equivalent.h
similarity index 100%
rename from media/codecs/amrnb/common/include/basic_op_c_equivalent.h
rename to media/module/codecs/amrnb/common/include/basic_op_c_equivalent.h
diff --git a/media/codecs/amrnb/common/include/basicop_malloc.h b/media/module/codecs/amrnb/common/include/basicop_malloc.h
similarity index 100%
rename from media/codecs/amrnb/common/include/basicop_malloc.h
rename to media/module/codecs/amrnb/common/include/basicop_malloc.h
diff --git a/media/codecs/amrnb/common/include/bitno_tab.h b/media/module/codecs/amrnb/common/include/bitno_tab.h
similarity index 100%
rename from media/codecs/amrnb/common/include/bitno_tab.h
rename to media/module/codecs/amrnb/common/include/bitno_tab.h
diff --git a/media/codecs/amrnb/common/include/bitreorder_tab.h b/media/module/codecs/amrnb/common/include/bitreorder_tab.h
similarity index 100%
rename from media/codecs/amrnb/common/include/bitreorder_tab.h
rename to media/module/codecs/amrnb/common/include/bitreorder_tab.h
diff --git a/media/codecs/amrnb/common/include/bits2prm.h b/media/module/codecs/amrnb/common/include/bits2prm.h
similarity index 100%
rename from media/codecs/amrnb/common/include/bits2prm.h
rename to media/module/codecs/amrnb/common/include/bits2prm.h
diff --git a/media/codecs/amrnb/common/include/cnst.h b/media/module/codecs/amrnb/common/include/cnst.h
similarity index 100%
rename from media/codecs/amrnb/common/include/cnst.h
rename to media/module/codecs/amrnb/common/include/cnst.h
diff --git a/media/codecs/amrnb/common/include/cnst_vad.h b/media/module/codecs/amrnb/common/include/cnst_vad.h
similarity index 100%
rename from media/codecs/amrnb/common/include/cnst_vad.h
rename to media/module/codecs/amrnb/common/include/cnst_vad.h
diff --git a/media/codecs/amrnb/common/include/copy.h b/media/module/codecs/amrnb/common/include/copy.h
similarity index 100%
rename from media/codecs/amrnb/common/include/copy.h
rename to media/module/codecs/amrnb/common/include/copy.h
diff --git a/media/codecs/amrnb/common/include/d_gain_c.h b/media/module/codecs/amrnb/common/include/d_gain_c.h
similarity index 100%
rename from media/codecs/amrnb/common/include/d_gain_c.h
rename to media/module/codecs/amrnb/common/include/d_gain_c.h
diff --git a/media/codecs/amrnb/common/include/d_gain_p.h b/media/module/codecs/amrnb/common/include/d_gain_p.h
similarity index 100%
rename from media/codecs/amrnb/common/include/d_gain_p.h
rename to media/module/codecs/amrnb/common/include/d_gain_p.h
diff --git a/media/codecs/amrnb/common/include/d_plsf.h b/media/module/codecs/amrnb/common/include/d_plsf.h
similarity index 100%
rename from media/codecs/amrnb/common/include/d_plsf.h
rename to media/module/codecs/amrnb/common/include/d_plsf.h
diff --git a/media/codecs/amrnb/common/include/div_32.h b/media/module/codecs/amrnb/common/include/div_32.h
similarity index 100%
rename from media/codecs/amrnb/common/include/div_32.h
rename to media/module/codecs/amrnb/common/include/div_32.h
diff --git a/media/codecs/amrnb/common/include/div_s.h b/media/module/codecs/amrnb/common/include/div_s.h
similarity index 100%
rename from media/codecs/amrnb/common/include/div_s.h
rename to media/module/codecs/amrnb/common/include/div_s.h
diff --git a/media/codecs/amrnb/common/include/dtx_common_def.h b/media/module/codecs/amrnb/common/include/dtx_common_def.h
similarity index 100%
rename from media/codecs/amrnb/common/include/dtx_common_def.h
rename to media/module/codecs/amrnb/common/include/dtx_common_def.h
diff --git a/media/codecs/amrnb/common/include/extract_h.h b/media/module/codecs/amrnb/common/include/extract_h.h
similarity index 100%
rename from media/codecs/amrnb/common/include/extract_h.h
rename to media/module/codecs/amrnb/common/include/extract_h.h
diff --git a/media/codecs/amrnb/common/include/extract_l.h b/media/module/codecs/amrnb/common/include/extract_l.h
similarity index 100%
rename from media/codecs/amrnb/common/include/extract_l.h
rename to media/module/codecs/amrnb/common/include/extract_l.h
diff --git a/media/codecs/amrnb/common/include/frame.h b/media/module/codecs/amrnb/common/include/frame.h
similarity index 100%
rename from media/codecs/amrnb/common/include/frame.h
rename to media/module/codecs/amrnb/common/include/frame.h
diff --git a/media/codecs/amrnb/common/include/frame_type_3gpp.h b/media/module/codecs/amrnb/common/include/frame_type_3gpp.h
similarity index 100%
rename from media/codecs/amrnb/common/include/frame_type_3gpp.h
rename to media/module/codecs/amrnb/common/include/frame_type_3gpp.h
diff --git a/media/codecs/amrnb/common/include/gc_pred.h b/media/module/codecs/amrnb/common/include/gc_pred.h
similarity index 100%
rename from media/codecs/amrnb/common/include/gc_pred.h
rename to media/module/codecs/amrnb/common/include/gc_pred.h
diff --git a/media/codecs/amrnb/common/include/gmed_n.h b/media/module/codecs/amrnb/common/include/gmed_n.h
similarity index 100%
rename from media/codecs/amrnb/common/include/gmed_n.h
rename to media/module/codecs/amrnb/common/include/gmed_n.h
diff --git a/media/codecs/amrnb/common/include/gsm_amr_typedefs.h b/media/module/codecs/amrnb/common/include/gsm_amr_typedefs.h
similarity index 100%
rename from media/codecs/amrnb/common/include/gsm_amr_typedefs.h
rename to media/module/codecs/amrnb/common/include/gsm_amr_typedefs.h
diff --git a/media/codecs/amrnb/common/include/int_lpc.h b/media/module/codecs/amrnb/common/include/int_lpc.h
similarity index 100%
rename from media/codecs/amrnb/common/include/int_lpc.h
rename to media/module/codecs/amrnb/common/include/int_lpc.h
diff --git a/media/codecs/amrnb/common/include/int_lsf.h b/media/module/codecs/amrnb/common/include/int_lsf.h
similarity index 100%
rename from media/codecs/amrnb/common/include/int_lsf.h
rename to media/module/codecs/amrnb/common/include/int_lsf.h
diff --git a/media/codecs/amrnb/common/include/inv_sqrt.h b/media/module/codecs/amrnb/common/include/inv_sqrt.h
similarity index 100%
rename from media/codecs/amrnb/common/include/inv_sqrt.h
rename to media/module/codecs/amrnb/common/include/inv_sqrt.h
diff --git a/media/codecs/amrnb/common/include/l_abs.h b/media/module/codecs/amrnb/common/include/l_abs.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_abs.h
rename to media/module/codecs/amrnb/common/include/l_abs.h
diff --git a/media/codecs/amrnb/common/include/l_add.h b/media/module/codecs/amrnb/common/include/l_add.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_add.h
rename to media/module/codecs/amrnb/common/include/l_add.h
diff --git a/media/codecs/amrnb/common/include/l_add_c.h b/media/module/codecs/amrnb/common/include/l_add_c.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_add_c.h
rename to media/module/codecs/amrnb/common/include/l_add_c.h
diff --git a/media/codecs/amrnb/common/include/l_comp.h b/media/module/codecs/amrnb/common/include/l_comp.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_comp.h
rename to media/module/codecs/amrnb/common/include/l_comp.h
diff --git a/media/codecs/amrnb/common/include/l_deposit_h.h b/media/module/codecs/amrnb/common/include/l_deposit_h.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_deposit_h.h
rename to media/module/codecs/amrnb/common/include/l_deposit_h.h
diff --git a/media/codecs/amrnb/common/include/l_deposit_l.h b/media/module/codecs/amrnb/common/include/l_deposit_l.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_deposit_l.h
rename to media/module/codecs/amrnb/common/include/l_deposit_l.h
diff --git a/media/codecs/amrnb/common/include/l_extract.h b/media/module/codecs/amrnb/common/include/l_extract.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_extract.h
rename to media/module/codecs/amrnb/common/include/l_extract.h
diff --git a/media/codecs/amrnb/common/include/l_mac.h b/media/module/codecs/amrnb/common/include/l_mac.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_mac.h
rename to media/module/codecs/amrnb/common/include/l_mac.h
diff --git a/media/codecs/amrnb/common/include/l_msu.h b/media/module/codecs/amrnb/common/include/l_msu.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_msu.h
rename to media/module/codecs/amrnb/common/include/l_msu.h
diff --git a/media/codecs/amrnb/common/include/l_mult.h b/media/module/codecs/amrnb/common/include/l_mult.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_mult.h
rename to media/module/codecs/amrnb/common/include/l_mult.h
diff --git a/media/codecs/amrnb/common/include/l_negate.h b/media/module/codecs/amrnb/common/include/l_negate.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_negate.h
rename to media/module/codecs/amrnb/common/include/l_negate.h
diff --git a/media/codecs/amrnb/common/include/l_shl.h b/media/module/codecs/amrnb/common/include/l_shl.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_shl.h
rename to media/module/codecs/amrnb/common/include/l_shl.h
diff --git a/media/codecs/amrnb/common/include/l_shr.h b/media/module/codecs/amrnb/common/include/l_shr.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_shr.h
rename to media/module/codecs/amrnb/common/include/l_shr.h
diff --git a/media/codecs/amrnb/common/include/l_shr_r.h b/media/module/codecs/amrnb/common/include/l_shr_r.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_shr_r.h
rename to media/module/codecs/amrnb/common/include/l_shr_r.h
diff --git a/media/codecs/amrnb/common/include/l_sub.h b/media/module/codecs/amrnb/common/include/l_sub.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_sub.h
rename to media/module/codecs/amrnb/common/include/l_sub.h
diff --git a/media/codecs/amrnb/common/include/log2.h b/media/module/codecs/amrnb/common/include/log2.h
similarity index 100%
rename from media/codecs/amrnb/common/include/log2.h
rename to media/module/codecs/amrnb/common/include/log2.h
diff --git a/media/codecs/amrnb/common/include/log2_norm.h b/media/module/codecs/amrnb/common/include/log2_norm.h
similarity index 100%
rename from media/codecs/amrnb/common/include/log2_norm.h
rename to media/module/codecs/amrnb/common/include/log2_norm.h
diff --git a/media/codecs/amrnb/common/include/lsfwt.h b/media/module/codecs/amrnb/common/include/lsfwt.h
similarity index 100%
rename from media/codecs/amrnb/common/include/lsfwt.h
rename to media/module/codecs/amrnb/common/include/lsfwt.h
diff --git a/media/codecs/amrnb/common/include/lsp.h b/media/module/codecs/amrnb/common/include/lsp.h
similarity index 100%
rename from media/codecs/amrnb/common/include/lsp.h
rename to media/module/codecs/amrnb/common/include/lsp.h
diff --git a/media/codecs/amrnb/common/include/lsp_az.h b/media/module/codecs/amrnb/common/include/lsp_az.h
similarity index 100%
rename from media/codecs/amrnb/common/include/lsp_az.h
rename to media/module/codecs/amrnb/common/include/lsp_az.h
diff --git a/media/codecs/amrnb/common/include/lsp_lsf.h b/media/module/codecs/amrnb/common/include/lsp_lsf.h
similarity index 100%
rename from media/codecs/amrnb/common/include/lsp_lsf.h
rename to media/module/codecs/amrnb/common/include/lsp_lsf.h
diff --git a/media/codecs/amrnb/common/include/lsp_tab.h b/media/module/codecs/amrnb/common/include/lsp_tab.h
similarity index 100%
rename from media/codecs/amrnb/common/include/lsp_tab.h
rename to media/module/codecs/amrnb/common/include/lsp_tab.h
diff --git a/media/codecs/amrnb/common/include/mac_32.h b/media/module/codecs/amrnb/common/include/mac_32.h
similarity index 100%
rename from media/codecs/amrnb/common/include/mac_32.h
rename to media/module/codecs/amrnb/common/include/mac_32.h
diff --git a/media/codecs/amrnb/common/include/mode.h b/media/module/codecs/amrnb/common/include/mode.h
similarity index 100%
rename from media/codecs/amrnb/common/include/mode.h
rename to media/module/codecs/amrnb/common/include/mode.h
diff --git a/media/codecs/amrnb/common/include/mpy_32.h b/media/module/codecs/amrnb/common/include/mpy_32.h
similarity index 100%
rename from media/codecs/amrnb/common/include/mpy_32.h
rename to media/module/codecs/amrnb/common/include/mpy_32.h
diff --git a/media/codecs/amrnb/common/include/mpy_32_16.h b/media/module/codecs/amrnb/common/include/mpy_32_16.h
similarity index 100%
rename from media/codecs/amrnb/common/include/mpy_32_16.h
rename to media/module/codecs/amrnb/common/include/mpy_32_16.h
diff --git a/media/codecs/amrnb/common/include/mult.h b/media/module/codecs/amrnb/common/include/mult.h
similarity index 100%
rename from media/codecs/amrnb/common/include/mult.h
rename to media/module/codecs/amrnb/common/include/mult.h
diff --git a/media/codecs/amrnb/common/include/mult_r.h b/media/module/codecs/amrnb/common/include/mult_r.h
similarity index 100%
rename from media/codecs/amrnb/common/include/mult_r.h
rename to media/module/codecs/amrnb/common/include/mult_r.h
diff --git a/media/codecs/amrnb/common/include/n_proc.h b/media/module/codecs/amrnb/common/include/n_proc.h
similarity index 100%
rename from media/codecs/amrnb/common/include/n_proc.h
rename to media/module/codecs/amrnb/common/include/n_proc.h
diff --git a/media/codecs/amrnb/common/include/negate.h b/media/module/codecs/amrnb/common/include/negate.h
similarity index 100%
rename from media/codecs/amrnb/common/include/negate.h
rename to media/module/codecs/amrnb/common/include/negate.h
diff --git a/media/codecs/amrnb/common/include/norm_l.h b/media/module/codecs/amrnb/common/include/norm_l.h
similarity index 100%
rename from media/codecs/amrnb/common/include/norm_l.h
rename to media/module/codecs/amrnb/common/include/norm_l.h
diff --git a/media/codecs/amrnb/common/include/norm_s.h b/media/module/codecs/amrnb/common/include/norm_s.h
similarity index 100%
rename from media/codecs/amrnb/common/include/norm_s.h
rename to media/module/codecs/amrnb/common/include/norm_s.h
diff --git a/media/codecs/amrnb/common/include/oper_32b.h b/media/module/codecs/amrnb/common/include/oper_32b.h
similarity index 100%
rename from media/codecs/amrnb/common/include/oper_32b.h
rename to media/module/codecs/amrnb/common/include/oper_32b.h
diff --git a/media/codecs/amrnb/common/include/p_ol_wgh.h b/media/module/codecs/amrnb/common/include/p_ol_wgh.h
similarity index 100%
rename from media/codecs/amrnb/common/include/p_ol_wgh.h
rename to media/module/codecs/amrnb/common/include/p_ol_wgh.h
diff --git a/media/codecs/amrnb/common/include/pow2.h b/media/module/codecs/amrnb/common/include/pow2.h
similarity index 100%
rename from media/codecs/amrnb/common/include/pow2.h
rename to media/module/codecs/amrnb/common/include/pow2.h
diff --git a/media/codecs/amrnb/common/include/pred_lt.h b/media/module/codecs/amrnb/common/include/pred_lt.h
similarity index 100%
rename from media/codecs/amrnb/common/include/pred_lt.h
rename to media/module/codecs/amrnb/common/include/pred_lt.h
diff --git a/media/codecs/amrnb/common/include/q_plsf.h b/media/module/codecs/amrnb/common/include/q_plsf.h
similarity index 100%
rename from media/codecs/amrnb/common/include/q_plsf.h
rename to media/module/codecs/amrnb/common/include/q_plsf.h
diff --git a/media/codecs/amrnb/common/include/q_plsf_3_tbl.h b/media/module/codecs/amrnb/common/include/q_plsf_3_tbl.h
similarity index 100%
rename from media/codecs/amrnb/common/include/q_plsf_3_tbl.h
rename to media/module/codecs/amrnb/common/include/q_plsf_3_tbl.h
diff --git a/media/codecs/amrnb/common/include/q_plsf_5_tbl.h b/media/module/codecs/amrnb/common/include/q_plsf_5_tbl.h
similarity index 100%
rename from media/codecs/amrnb/common/include/q_plsf_5_tbl.h
rename to media/module/codecs/amrnb/common/include/q_plsf_5_tbl.h
diff --git a/media/codecs/amrnb/common/include/qgain475_tab.h b/media/module/codecs/amrnb/common/include/qgain475_tab.h
similarity index 100%
rename from media/codecs/amrnb/common/include/qgain475_tab.h
rename to media/module/codecs/amrnb/common/include/qgain475_tab.h
diff --git a/media/codecs/amrnb/common/include/qua_gain.h b/media/module/codecs/amrnb/common/include/qua_gain.h
similarity index 100%
rename from media/codecs/amrnb/common/include/qua_gain.h
rename to media/module/codecs/amrnb/common/include/qua_gain.h
diff --git a/media/codecs/amrnb/common/include/qua_gain_tbl.h b/media/module/codecs/amrnb/common/include/qua_gain_tbl.h
similarity index 100%
rename from media/codecs/amrnb/common/include/qua_gain_tbl.h
rename to media/module/codecs/amrnb/common/include/qua_gain_tbl.h
diff --git a/media/codecs/amrnb/common/include/reorder.h b/media/module/codecs/amrnb/common/include/reorder.h
similarity index 100%
rename from media/codecs/amrnb/common/include/reorder.h
rename to media/module/codecs/amrnb/common/include/reorder.h
diff --git a/media/codecs/amrnb/common/include/residu.h b/media/module/codecs/amrnb/common/include/residu.h
similarity index 100%
rename from media/codecs/amrnb/common/include/residu.h
rename to media/module/codecs/amrnb/common/include/residu.h
diff --git a/media/codecs/amrnb/common/include/reverse_bits.h b/media/module/codecs/amrnb/common/include/reverse_bits.h
similarity index 100%
rename from media/codecs/amrnb/common/include/reverse_bits.h
rename to media/module/codecs/amrnb/common/include/reverse_bits.h
diff --git a/media/codecs/amrnb/common/include/round.h b/media/module/codecs/amrnb/common/include/round.h
similarity index 100%
rename from media/codecs/amrnb/common/include/round.h
rename to media/module/codecs/amrnb/common/include/round.h
diff --git a/media/codecs/amrnb/common/include/set_zero.h b/media/module/codecs/amrnb/common/include/set_zero.h
similarity index 100%
rename from media/codecs/amrnb/common/include/set_zero.h
rename to media/module/codecs/amrnb/common/include/set_zero.h
diff --git a/media/codecs/amrnb/common/include/shl.h b/media/module/codecs/amrnb/common/include/shl.h
similarity index 100%
rename from media/codecs/amrnb/common/include/shl.h
rename to media/module/codecs/amrnb/common/include/shl.h
diff --git a/media/codecs/amrnb/common/include/shr.h b/media/module/codecs/amrnb/common/include/shr.h
similarity index 100%
rename from media/codecs/amrnb/common/include/shr.h
rename to media/module/codecs/amrnb/common/include/shr.h
diff --git a/media/codecs/amrnb/common/include/shr_r.h b/media/module/codecs/amrnb/common/include/shr_r.h
similarity index 100%
rename from media/codecs/amrnb/common/include/shr_r.h
rename to media/module/codecs/amrnb/common/include/shr_r.h
diff --git a/media/codecs/amrnb/common/include/sqrt_l.h b/media/module/codecs/amrnb/common/include/sqrt_l.h
similarity index 100%
rename from media/codecs/amrnb/common/include/sqrt_l.h
rename to media/module/codecs/amrnb/common/include/sqrt_l.h
diff --git a/media/codecs/amrnb/common/include/sub.h b/media/module/codecs/amrnb/common/include/sub.h
similarity index 100%
rename from media/codecs/amrnb/common/include/sub.h
rename to media/module/codecs/amrnb/common/include/sub.h
diff --git a/media/codecs/amrnb/common/include/syn_filt.h b/media/module/codecs/amrnb/common/include/syn_filt.h
similarity index 100%
rename from media/codecs/amrnb/common/include/syn_filt.h
rename to media/module/codecs/amrnb/common/include/syn_filt.h
diff --git a/media/codecs/amrnb/common/include/typedef.h b/media/module/codecs/amrnb/common/include/typedef.h
similarity index 100%
rename from media/codecs/amrnb/common/include/typedef.h
rename to media/module/codecs/amrnb/common/include/typedef.h
diff --git a/media/codecs/amrnb/common/include/vad.h b/media/module/codecs/amrnb/common/include/vad.h
similarity index 100%
rename from media/codecs/amrnb/common/include/vad.h
rename to media/module/codecs/amrnb/common/include/vad.h
diff --git a/media/codecs/amrnb/common/include/vad1.h b/media/module/codecs/amrnb/common/include/vad1.h
similarity index 100%
rename from media/codecs/amrnb/common/include/vad1.h
rename to media/module/codecs/amrnb/common/include/vad1.h
diff --git a/media/codecs/amrnb/common/include/vad2.h b/media/module/codecs/amrnb/common/include/vad2.h
similarity index 100%
rename from media/codecs/amrnb/common/include/vad2.h
rename to media/module/codecs/amrnb/common/include/vad2.h
diff --git a/media/codecs/amrnb/common/include/weight_a.h b/media/module/codecs/amrnb/common/include/weight_a.h
similarity index 100%
rename from media/codecs/amrnb/common/include/weight_a.h
rename to media/module/codecs/amrnb/common/include/weight_a.h
diff --git a/media/codecs/amrnb/common/include/window_tab.h b/media/module/codecs/amrnb/common/include/window_tab.h
similarity index 100%
rename from media/codecs/amrnb/common/include/window_tab.h
rename to media/module/codecs/amrnb/common/include/window_tab.h
diff --git a/media/codecs/amrnb/common/include/wmf_to_ets.h b/media/module/codecs/amrnb/common/include/wmf_to_ets.h
similarity index 100%
rename from media/codecs/amrnb/common/include/wmf_to_ets.h
rename to media/module/codecs/amrnb/common/include/wmf_to_ets.h
diff --git a/media/codecs/amrnb/common/src/add.cpp b/media/module/codecs/amrnb/common/src/add.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/add.cpp
rename to media/module/codecs/amrnb/common/src/add.cpp
diff --git a/media/codecs/amrnb/common/src/az_lsp.cpp b/media/module/codecs/amrnb/common/src/az_lsp.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/az_lsp.cpp
rename to media/module/codecs/amrnb/common/src/az_lsp.cpp
diff --git a/media/codecs/amrnb/common/src/bitno_tab.cpp b/media/module/codecs/amrnb/common/src/bitno_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/bitno_tab.cpp
rename to media/module/codecs/amrnb/common/src/bitno_tab.cpp
diff --git a/media/codecs/amrnb/common/src/bitreorder_tab.cpp b/media/module/codecs/amrnb/common/src/bitreorder_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/bitreorder_tab.cpp
rename to media/module/codecs/amrnb/common/src/bitreorder_tab.cpp
diff --git a/media/codecs/amrnb/common/src/bits2prm.cpp b/media/module/codecs/amrnb/common/src/bits2prm.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/bits2prm.cpp
rename to media/module/codecs/amrnb/common/src/bits2prm.cpp
diff --git a/media/codecs/amrnb/common/src/c2_9pf_tab.cpp b/media/module/codecs/amrnb/common/src/c2_9pf_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/c2_9pf_tab.cpp
rename to media/module/codecs/amrnb/common/src/c2_9pf_tab.cpp
diff --git a/media/codecs/amrnb/common/src/copy.cpp b/media/module/codecs/amrnb/common/src/copy.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/copy.cpp
rename to media/module/codecs/amrnb/common/src/copy.cpp
diff --git a/media/codecs/amrnb/common/src/div_32.cpp b/media/module/codecs/amrnb/common/src/div_32.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/div_32.cpp
rename to media/module/codecs/amrnb/common/src/div_32.cpp
diff --git a/media/codecs/amrnb/common/src/div_s.cpp b/media/module/codecs/amrnb/common/src/div_s.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/div_s.cpp
rename to media/module/codecs/amrnb/common/src/div_s.cpp
diff --git a/media/codecs/amrnb/common/src/extract_h.cpp b/media/module/codecs/amrnb/common/src/extract_h.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/extract_h.cpp
rename to media/module/codecs/amrnb/common/src/extract_h.cpp
diff --git a/media/codecs/amrnb/common/src/extract_l.cpp b/media/module/codecs/amrnb/common/src/extract_l.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/extract_l.cpp
rename to media/module/codecs/amrnb/common/src/extract_l.cpp
diff --git a/media/codecs/amrnb/common/src/gains_tbl.cpp b/media/module/codecs/amrnb/common/src/gains_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/gains_tbl.cpp
rename to media/module/codecs/amrnb/common/src/gains_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/gc_pred.cpp b/media/module/codecs/amrnb/common/src/gc_pred.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/gc_pred.cpp
rename to media/module/codecs/amrnb/common/src/gc_pred.cpp
diff --git a/media/codecs/amrnb/common/src/gmed_n.cpp b/media/module/codecs/amrnb/common/src/gmed_n.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/gmed_n.cpp
rename to media/module/codecs/amrnb/common/src/gmed_n.cpp
diff --git a/media/codecs/amrnb/common/src/gray_tbl.cpp b/media/module/codecs/amrnb/common/src/gray_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/gray_tbl.cpp
rename to media/module/codecs/amrnb/common/src/gray_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/grid_tbl.cpp b/media/module/codecs/amrnb/common/src/grid_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/grid_tbl.cpp
rename to media/module/codecs/amrnb/common/src/grid_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/int_lpc.cpp b/media/module/codecs/amrnb/common/src/int_lpc.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/int_lpc.cpp
rename to media/module/codecs/amrnb/common/src/int_lpc.cpp
diff --git a/media/codecs/amrnb/common/src/inv_sqrt.cpp b/media/module/codecs/amrnb/common/src/inv_sqrt.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/inv_sqrt.cpp
rename to media/module/codecs/amrnb/common/src/inv_sqrt.cpp
diff --git a/media/codecs/amrnb/common/src/inv_sqrt_tbl.cpp b/media/module/codecs/amrnb/common/src/inv_sqrt_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/inv_sqrt_tbl.cpp
rename to media/module/codecs/amrnb/common/src/inv_sqrt_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/l_abs.cpp b/media/module/codecs/amrnb/common/src/l_abs.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/l_abs.cpp
rename to media/module/codecs/amrnb/common/src/l_abs.cpp
diff --git a/media/codecs/amrnb/common/src/l_deposit_h.cpp b/media/module/codecs/amrnb/common/src/l_deposit_h.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/l_deposit_h.cpp
rename to media/module/codecs/amrnb/common/src/l_deposit_h.cpp
diff --git a/media/codecs/amrnb/common/src/l_deposit_l.cpp b/media/module/codecs/amrnb/common/src/l_deposit_l.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/l_deposit_l.cpp
rename to media/module/codecs/amrnb/common/src/l_deposit_l.cpp
diff --git a/media/codecs/amrnb/common/src/l_shr_r.cpp b/media/module/codecs/amrnb/common/src/l_shr_r.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/l_shr_r.cpp
rename to media/module/codecs/amrnb/common/src/l_shr_r.cpp
diff --git a/media/codecs/amrnb/common/src/log2.cpp b/media/module/codecs/amrnb/common/src/log2.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/log2.cpp
rename to media/module/codecs/amrnb/common/src/log2.cpp
diff --git a/media/codecs/amrnb/common/src/log2_norm.cpp b/media/module/codecs/amrnb/common/src/log2_norm.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/log2_norm.cpp
rename to media/module/codecs/amrnb/common/src/log2_norm.cpp
diff --git a/media/codecs/amrnb/common/src/log2_tbl.cpp b/media/module/codecs/amrnb/common/src/log2_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/log2_tbl.cpp
rename to media/module/codecs/amrnb/common/src/log2_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/lsfwt.cpp b/media/module/codecs/amrnb/common/src/lsfwt.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/lsfwt.cpp
rename to media/module/codecs/amrnb/common/src/lsfwt.cpp
diff --git a/media/codecs/amrnb/common/src/lsp.cpp b/media/module/codecs/amrnb/common/src/lsp.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/lsp.cpp
rename to media/module/codecs/amrnb/common/src/lsp.cpp
diff --git a/media/codecs/amrnb/common/src/lsp_az.cpp b/media/module/codecs/amrnb/common/src/lsp_az.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/lsp_az.cpp
rename to media/module/codecs/amrnb/common/src/lsp_az.cpp
diff --git a/media/codecs/amrnb/common/src/lsp_lsf.cpp b/media/module/codecs/amrnb/common/src/lsp_lsf.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/lsp_lsf.cpp
rename to media/module/codecs/amrnb/common/src/lsp_lsf.cpp
diff --git a/media/codecs/amrnb/common/src/lsp_lsf_tbl.cpp b/media/module/codecs/amrnb/common/src/lsp_lsf_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/lsp_lsf_tbl.cpp
rename to media/module/codecs/amrnb/common/src/lsp_lsf_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/lsp_tab.cpp b/media/module/codecs/amrnb/common/src/lsp_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/lsp_tab.cpp
rename to media/module/codecs/amrnb/common/src/lsp_tab.cpp
diff --git a/media/codecs/amrnb/common/src/mult_r.cpp b/media/module/codecs/amrnb/common/src/mult_r.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/mult_r.cpp
rename to media/module/codecs/amrnb/common/src/mult_r.cpp
diff --git a/media/codecs/amrnb/common/src/negate.cpp b/media/module/codecs/amrnb/common/src/negate.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/negate.cpp
rename to media/module/codecs/amrnb/common/src/negate.cpp
diff --git a/media/codecs/amrnb/common/src/norm_l.cpp b/media/module/codecs/amrnb/common/src/norm_l.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/norm_l.cpp
rename to media/module/codecs/amrnb/common/src/norm_l.cpp
diff --git a/media/codecs/amrnb/common/src/norm_s.cpp b/media/module/codecs/amrnb/common/src/norm_s.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/norm_s.cpp
rename to media/module/codecs/amrnb/common/src/norm_s.cpp
diff --git a/media/codecs/amrnb/common/src/ph_disp_tab.cpp b/media/module/codecs/amrnb/common/src/ph_disp_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/ph_disp_tab.cpp
rename to media/module/codecs/amrnb/common/src/ph_disp_tab.cpp
diff --git a/media/codecs/amrnb/common/src/pow2.cpp b/media/module/codecs/amrnb/common/src/pow2.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/pow2.cpp
rename to media/module/codecs/amrnb/common/src/pow2.cpp
diff --git a/media/codecs/amrnb/common/src/pow2_tbl.cpp b/media/module/codecs/amrnb/common/src/pow2_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/pow2_tbl.cpp
rename to media/module/codecs/amrnb/common/src/pow2_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/pred_lt.cpp b/media/module/codecs/amrnb/common/src/pred_lt.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/pred_lt.cpp
rename to media/module/codecs/amrnb/common/src/pred_lt.cpp
diff --git a/media/codecs/amrnb/common/src/q_plsf.cpp b/media/module/codecs/amrnb/common/src/q_plsf.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/q_plsf.cpp
rename to media/module/codecs/amrnb/common/src/q_plsf.cpp
diff --git a/media/codecs/amrnb/common/src/q_plsf_3.cpp b/media/module/codecs/amrnb/common/src/q_plsf_3.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/q_plsf_3.cpp
rename to media/module/codecs/amrnb/common/src/q_plsf_3.cpp
diff --git a/media/codecs/amrnb/common/src/q_plsf_3_tbl.cpp b/media/module/codecs/amrnb/common/src/q_plsf_3_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/q_plsf_3_tbl.cpp
rename to media/module/codecs/amrnb/common/src/q_plsf_3_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/q_plsf_5.cpp b/media/module/codecs/amrnb/common/src/q_plsf_5.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/q_plsf_5.cpp
rename to media/module/codecs/amrnb/common/src/q_plsf_5.cpp
diff --git a/media/codecs/amrnb/common/src/q_plsf_5_tbl.cpp b/media/module/codecs/amrnb/common/src/q_plsf_5_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/q_plsf_5_tbl.cpp
rename to media/module/codecs/amrnb/common/src/q_plsf_5_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/qua_gain_tbl.cpp b/media/module/codecs/amrnb/common/src/qua_gain_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/qua_gain_tbl.cpp
rename to media/module/codecs/amrnb/common/src/qua_gain_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/reorder.cpp b/media/module/codecs/amrnb/common/src/reorder.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/reorder.cpp
rename to media/module/codecs/amrnb/common/src/reorder.cpp
diff --git a/media/codecs/amrnb/common/src/residu.cpp b/media/module/codecs/amrnb/common/src/residu.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/residu.cpp
rename to media/module/codecs/amrnb/common/src/residu.cpp
diff --git a/media/codecs/amrnb/common/src/round.cpp b/media/module/codecs/amrnb/common/src/round.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/round.cpp
rename to media/module/codecs/amrnb/common/src/round.cpp
diff --git a/media/codecs/amrnb/common/src/set_zero.cpp b/media/module/codecs/amrnb/common/src/set_zero.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/set_zero.cpp
rename to media/module/codecs/amrnb/common/src/set_zero.cpp
diff --git a/media/codecs/amrnb/common/src/shr.cpp b/media/module/codecs/amrnb/common/src/shr.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/shr.cpp
rename to media/module/codecs/amrnb/common/src/shr.cpp
diff --git a/media/codecs/amrnb/common/src/shr_r.cpp b/media/module/codecs/amrnb/common/src/shr_r.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/shr_r.cpp
rename to media/module/codecs/amrnb/common/src/shr_r.cpp
diff --git a/media/codecs/amrnb/common/src/sqrt_l.cpp b/media/module/codecs/amrnb/common/src/sqrt_l.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/sqrt_l.cpp
rename to media/module/codecs/amrnb/common/src/sqrt_l.cpp
diff --git a/media/codecs/amrnb/common/src/sqrt_l_tbl.cpp b/media/module/codecs/amrnb/common/src/sqrt_l_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/sqrt_l_tbl.cpp
rename to media/module/codecs/amrnb/common/src/sqrt_l_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/sub.cpp b/media/module/codecs/amrnb/common/src/sub.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/sub.cpp
rename to media/module/codecs/amrnb/common/src/sub.cpp
diff --git a/media/codecs/amrnb/common/src/syn_filt.cpp b/media/module/codecs/amrnb/common/src/syn_filt.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/syn_filt.cpp
rename to media/module/codecs/amrnb/common/src/syn_filt.cpp
diff --git a/media/codecs/amrnb/common/src/vad1.cpp b/media/module/codecs/amrnb/common/src/vad1.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/vad1.cpp
rename to media/module/codecs/amrnb/common/src/vad1.cpp
diff --git a/media/codecs/amrnb/common/src/weight_a.cpp b/media/module/codecs/amrnb/common/src/weight_a.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/weight_a.cpp
rename to media/module/codecs/amrnb/common/src/weight_a.cpp
diff --git a/media/codecs/amrnb/common/src/window_tab.cpp b/media/module/codecs/amrnb/common/src/window_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/window_tab.cpp
rename to media/module/codecs/amrnb/common/src/window_tab.cpp
diff --git a/media/codecs/amrnb/dec/Android.bp b/media/module/codecs/amrnb/dec/Android.bp
similarity index 100%
rename from media/codecs/amrnb/dec/Android.bp
rename to media/module/codecs/amrnb/dec/Android.bp
diff --git a/media/codecs/amrnb/dec/MODULE_LICENSE_APACHE2 b/media/module/codecs/amrnb/dec/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/amrnb/dec/MODULE_LICENSE_APACHE2
rename to media/module/codecs/amrnb/dec/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/amrnb/dec/NOTICE b/media/module/codecs/amrnb/dec/NOTICE
similarity index 100%
rename from media/codecs/amrnb/dec/NOTICE
rename to media/module/codecs/amrnb/dec/NOTICE
diff --git a/media/codecs/amrnb/dec/src/a_refl.cpp b/media/module/codecs/amrnb/dec/src/a_refl.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/a_refl.cpp
rename to media/module/codecs/amrnb/dec/src/a_refl.cpp
diff --git a/media/codecs/amrnb/dec/src/a_refl.h b/media/module/codecs/amrnb/dec/src/a_refl.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/a_refl.h
rename to media/module/codecs/amrnb/dec/src/a_refl.h
diff --git a/media/codecs/amrnb/dec/src/agc.cpp b/media/module/codecs/amrnb/dec/src/agc.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/agc.cpp
rename to media/module/codecs/amrnb/dec/src/agc.cpp
diff --git a/media/codecs/amrnb/dec/src/agc.h b/media/module/codecs/amrnb/dec/src/agc.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/agc.h
rename to media/module/codecs/amrnb/dec/src/agc.h
diff --git a/media/codecs/amrnb/dec/src/amrdecode.cpp b/media/module/codecs/amrnb/dec/src/amrdecode.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/amrdecode.cpp
rename to media/module/codecs/amrnb/dec/src/amrdecode.cpp
diff --git a/media/codecs/amrnb/dec/src/amrdecode.h b/media/module/codecs/amrnb/dec/src/amrdecode.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/amrdecode.h
rename to media/module/codecs/amrnb/dec/src/amrdecode.h
diff --git a/media/codecs/amrnb/dec/src/b_cn_cod.cpp b/media/module/codecs/amrnb/dec/src/b_cn_cod.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/b_cn_cod.cpp
rename to media/module/codecs/amrnb/dec/src/b_cn_cod.cpp
diff --git a/media/codecs/amrnb/dec/src/b_cn_cod.h b/media/module/codecs/amrnb/dec/src/b_cn_cod.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/b_cn_cod.h
rename to media/module/codecs/amrnb/dec/src/b_cn_cod.h
diff --git a/media/codecs/amrnb/dec/src/bgnscd.cpp b/media/module/codecs/amrnb/dec/src/bgnscd.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/bgnscd.cpp
rename to media/module/codecs/amrnb/dec/src/bgnscd.cpp
diff --git a/media/codecs/amrnb/dec/src/bgnscd.h b/media/module/codecs/amrnb/dec/src/bgnscd.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/bgnscd.h
rename to media/module/codecs/amrnb/dec/src/bgnscd.h
diff --git a/media/codecs/amrnb/dec/src/c_g_aver.cpp b/media/module/codecs/amrnb/dec/src/c_g_aver.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/c_g_aver.cpp
rename to media/module/codecs/amrnb/dec/src/c_g_aver.cpp
diff --git a/media/codecs/amrnb/dec/src/c_g_aver.h b/media/module/codecs/amrnb/dec/src/c_g_aver.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/c_g_aver.h
rename to media/module/codecs/amrnb/dec/src/c_g_aver.h
diff --git a/media/codecs/amrnb/dec/src/d1035pf.cpp b/media/module/codecs/amrnb/dec/src/d1035pf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d1035pf.cpp
rename to media/module/codecs/amrnb/dec/src/d1035pf.cpp
diff --git a/media/codecs/amrnb/dec/src/d1035pf.h b/media/module/codecs/amrnb/dec/src/d1035pf.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/d1035pf.h
rename to media/module/codecs/amrnb/dec/src/d1035pf.h
diff --git a/media/codecs/amrnb/dec/src/d2_11pf.cpp b/media/module/codecs/amrnb/dec/src/d2_11pf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d2_11pf.cpp
rename to media/module/codecs/amrnb/dec/src/d2_11pf.cpp
diff --git a/media/codecs/amrnb/dec/src/d2_11pf.h b/media/module/codecs/amrnb/dec/src/d2_11pf.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/d2_11pf.h
rename to media/module/codecs/amrnb/dec/src/d2_11pf.h
diff --git a/media/codecs/amrnb/dec/src/d2_9pf.cpp b/media/module/codecs/amrnb/dec/src/d2_9pf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d2_9pf.cpp
rename to media/module/codecs/amrnb/dec/src/d2_9pf.cpp
diff --git a/media/codecs/amrnb/dec/src/d2_9pf.h b/media/module/codecs/amrnb/dec/src/d2_9pf.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/d2_9pf.h
rename to media/module/codecs/amrnb/dec/src/d2_9pf.h
diff --git a/media/codecs/amrnb/dec/src/d3_14pf.cpp b/media/module/codecs/amrnb/dec/src/d3_14pf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d3_14pf.cpp
rename to media/module/codecs/amrnb/dec/src/d3_14pf.cpp
diff --git a/media/codecs/amrnb/dec/src/d3_14pf.h b/media/module/codecs/amrnb/dec/src/d3_14pf.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/d3_14pf.h
rename to media/module/codecs/amrnb/dec/src/d3_14pf.h
diff --git a/media/codecs/amrnb/dec/src/d4_17pf.cpp b/media/module/codecs/amrnb/dec/src/d4_17pf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d4_17pf.cpp
rename to media/module/codecs/amrnb/dec/src/d4_17pf.cpp
diff --git a/media/codecs/amrnb/dec/src/d4_17pf.h b/media/module/codecs/amrnb/dec/src/d4_17pf.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/d4_17pf.h
rename to media/module/codecs/amrnb/dec/src/d4_17pf.h
diff --git a/media/codecs/amrnb/dec/src/d8_31pf.cpp b/media/module/codecs/amrnb/dec/src/d8_31pf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d8_31pf.cpp
rename to media/module/codecs/amrnb/dec/src/d8_31pf.cpp
diff --git a/media/codecs/amrnb/dec/src/d8_31pf.h b/media/module/codecs/amrnb/dec/src/d8_31pf.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/d8_31pf.h
rename to media/module/codecs/amrnb/dec/src/d8_31pf.h
diff --git a/media/codecs/amrnb/dec/src/d_gain_c.cpp b/media/module/codecs/amrnb/dec/src/d_gain_c.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d_gain_c.cpp
rename to media/module/codecs/amrnb/dec/src/d_gain_c.cpp
diff --git a/media/codecs/amrnb/dec/src/d_gain_p.cpp b/media/module/codecs/amrnb/dec/src/d_gain_p.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d_gain_p.cpp
rename to media/module/codecs/amrnb/dec/src/d_gain_p.cpp
diff --git a/media/codecs/amrnb/dec/src/d_plsf.cpp b/media/module/codecs/amrnb/dec/src/d_plsf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d_plsf.cpp
rename to media/module/codecs/amrnb/dec/src/d_plsf.cpp
diff --git a/media/codecs/amrnb/dec/src/d_plsf_3.cpp b/media/module/codecs/amrnb/dec/src/d_plsf_3.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d_plsf_3.cpp
rename to media/module/codecs/amrnb/dec/src/d_plsf_3.cpp
diff --git a/media/codecs/amrnb/dec/src/d_plsf_5.cpp b/media/module/codecs/amrnb/dec/src/d_plsf_5.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d_plsf_5.cpp
rename to media/module/codecs/amrnb/dec/src/d_plsf_5.cpp
diff --git a/media/codecs/amrnb/dec/src/dec_amr.cpp b/media/module/codecs/amrnb/dec/src/dec_amr.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_amr.cpp
rename to media/module/codecs/amrnb/dec/src/dec_amr.cpp
diff --git a/media/codecs/amrnb/dec/src/dec_amr.h b/media/module/codecs/amrnb/dec/src/dec_amr.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_amr.h
rename to media/module/codecs/amrnb/dec/src/dec_amr.h
diff --git a/media/codecs/amrnb/dec/src/dec_gain.cpp b/media/module/codecs/amrnb/dec/src/dec_gain.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_gain.cpp
rename to media/module/codecs/amrnb/dec/src/dec_gain.cpp
diff --git a/media/codecs/amrnb/dec/src/dec_gain.h b/media/module/codecs/amrnb/dec/src/dec_gain.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_gain.h
rename to media/module/codecs/amrnb/dec/src/dec_gain.h
diff --git a/media/codecs/amrnb/dec/src/dec_input_format_tab.cpp b/media/module/codecs/amrnb/dec/src/dec_input_format_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_input_format_tab.cpp
rename to media/module/codecs/amrnb/dec/src/dec_input_format_tab.cpp
diff --git a/media/codecs/amrnb/dec/src/dec_lag3.cpp b/media/module/codecs/amrnb/dec/src/dec_lag3.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_lag3.cpp
rename to media/module/codecs/amrnb/dec/src/dec_lag3.cpp
diff --git a/media/codecs/amrnb/dec/src/dec_lag3.h b/media/module/codecs/amrnb/dec/src/dec_lag3.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_lag3.h
rename to media/module/codecs/amrnb/dec/src/dec_lag3.h
diff --git a/media/codecs/amrnb/dec/src/dec_lag6.cpp b/media/module/codecs/amrnb/dec/src/dec_lag6.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_lag6.cpp
rename to media/module/codecs/amrnb/dec/src/dec_lag6.cpp
diff --git a/media/codecs/amrnb/dec/src/dec_lag6.h b/media/module/codecs/amrnb/dec/src/dec_lag6.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_lag6.h
rename to media/module/codecs/amrnb/dec/src/dec_lag6.h
diff --git a/media/codecs/amrnb/dec/src/dtx_dec.cpp b/media/module/codecs/amrnb/dec/src/dtx_dec.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/dtx_dec.cpp
rename to media/module/codecs/amrnb/dec/src/dtx_dec.cpp
diff --git a/media/codecs/amrnb/dec/src/dtx_dec.h b/media/module/codecs/amrnb/dec/src/dtx_dec.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/dtx_dec.h
rename to media/module/codecs/amrnb/dec/src/dtx_dec.h
diff --git a/media/codecs/amrnb/dec/src/ec_gains.cpp b/media/module/codecs/amrnb/dec/src/ec_gains.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/ec_gains.cpp
rename to media/module/codecs/amrnb/dec/src/ec_gains.cpp
diff --git a/media/codecs/amrnb/dec/src/ec_gains.h b/media/module/codecs/amrnb/dec/src/ec_gains.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/ec_gains.h
rename to media/module/codecs/amrnb/dec/src/ec_gains.h
diff --git a/media/codecs/amrnb/dec/src/ex_ctrl.cpp b/media/module/codecs/amrnb/dec/src/ex_ctrl.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/ex_ctrl.cpp
rename to media/module/codecs/amrnb/dec/src/ex_ctrl.cpp
diff --git a/media/codecs/amrnb/dec/src/ex_ctrl.h b/media/module/codecs/amrnb/dec/src/ex_ctrl.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/ex_ctrl.h
rename to media/module/codecs/amrnb/dec/src/ex_ctrl.h
diff --git a/media/codecs/amrnb/dec/src/gsmamr_dec.h b/media/module/codecs/amrnb/dec/src/gsmamr_dec.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/gsmamr_dec.h
rename to media/module/codecs/amrnb/dec/src/gsmamr_dec.h
diff --git a/media/codecs/amrnb/dec/src/if2_to_ets.cpp b/media/module/codecs/amrnb/dec/src/if2_to_ets.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/if2_to_ets.cpp
rename to media/module/codecs/amrnb/dec/src/if2_to_ets.cpp
diff --git a/media/codecs/amrnb/dec/src/if2_to_ets.h b/media/module/codecs/amrnb/dec/src/if2_to_ets.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/if2_to_ets.h
rename to media/module/codecs/amrnb/dec/src/if2_to_ets.h
diff --git a/media/codecs/amrnb/dec/src/int_lsf.cpp b/media/module/codecs/amrnb/dec/src/int_lsf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/int_lsf.cpp
rename to media/module/codecs/amrnb/dec/src/int_lsf.cpp
diff --git a/media/codecs/amrnb/dec/src/lsp_avg.cpp b/media/module/codecs/amrnb/dec/src/lsp_avg.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/lsp_avg.cpp
rename to media/module/codecs/amrnb/dec/src/lsp_avg.cpp
diff --git a/media/codecs/amrnb/dec/src/lsp_avg.h b/media/module/codecs/amrnb/dec/src/lsp_avg.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/lsp_avg.h
rename to media/module/codecs/amrnb/dec/src/lsp_avg.h
diff --git a/media/codecs/amrnb/dec/src/ph_disp.cpp b/media/module/codecs/amrnb/dec/src/ph_disp.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/ph_disp.cpp
rename to media/module/codecs/amrnb/dec/src/ph_disp.cpp
diff --git a/media/codecs/amrnb/dec/src/ph_disp.h b/media/module/codecs/amrnb/dec/src/ph_disp.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/ph_disp.h
rename to media/module/codecs/amrnb/dec/src/ph_disp.h
diff --git a/media/codecs/amrnb/dec/src/post_pro.cpp b/media/module/codecs/amrnb/dec/src/post_pro.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/post_pro.cpp
rename to media/module/codecs/amrnb/dec/src/post_pro.cpp
diff --git a/media/codecs/amrnb/dec/src/post_pro.h b/media/module/codecs/amrnb/dec/src/post_pro.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/post_pro.h
rename to media/module/codecs/amrnb/dec/src/post_pro.h
diff --git a/media/codecs/amrnb/dec/src/preemph.cpp b/media/module/codecs/amrnb/dec/src/preemph.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/preemph.cpp
rename to media/module/codecs/amrnb/dec/src/preemph.cpp
diff --git a/media/codecs/amrnb/dec/src/preemph.h b/media/module/codecs/amrnb/dec/src/preemph.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/preemph.h
rename to media/module/codecs/amrnb/dec/src/preemph.h
diff --git a/media/codecs/amrnb/dec/src/pstfilt.cpp b/media/module/codecs/amrnb/dec/src/pstfilt.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/pstfilt.cpp
rename to media/module/codecs/amrnb/dec/src/pstfilt.cpp
diff --git a/media/codecs/amrnb/dec/src/pstfilt.h b/media/module/codecs/amrnb/dec/src/pstfilt.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/pstfilt.h
rename to media/module/codecs/amrnb/dec/src/pstfilt.h
diff --git a/media/codecs/amrnb/dec/src/qgain475_tab.cpp b/media/module/codecs/amrnb/dec/src/qgain475_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/qgain475_tab.cpp
rename to media/module/codecs/amrnb/dec/src/qgain475_tab.cpp
diff --git a/media/codecs/amrnb/dec/src/sp_dec.cpp b/media/module/codecs/amrnb/dec/src/sp_dec.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/sp_dec.cpp
rename to media/module/codecs/amrnb/dec/src/sp_dec.cpp
diff --git a/media/codecs/amrnb/dec/src/sp_dec.h b/media/module/codecs/amrnb/dec/src/sp_dec.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/sp_dec.h
rename to media/module/codecs/amrnb/dec/src/sp_dec.h
diff --git a/media/codecs/amrnb/dec/src/wmf_to_ets.cpp b/media/module/codecs/amrnb/dec/src/wmf_to_ets.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/wmf_to_ets.cpp
rename to media/module/codecs/amrnb/dec/src/wmf_to_ets.cpp
diff --git a/media/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h b/media/module/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h
similarity index 100%
rename from media/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h
rename to media/module/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h
diff --git a/media/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp b/media/module/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
rename to media/module/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
diff --git a/media/codecs/amrnb/dec/test/Android.bp b/media/module/codecs/amrnb/dec/test/Android.bp
similarity index 90%
rename from media/codecs/amrnb/dec/test/Android.bp
rename to media/module/codecs/amrnb/dec/test/Android.bp
index 74258e0..de69cfc 100644
--- a/media/codecs/amrnb/dec/test/Android.bp
+++ b/media/module/codecs/amrnb/dec/test/Android.bp
@@ -58,4 +58,7 @@
"signed-integer-overflow",
],
},
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.zip?unzip=true",
+ ],
}
diff --git a/media/codecs/amrnb/dec/test/AndroidTest.xml b/media/module/codecs/amrnb/dec/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/amrnb/dec/test/AndroidTest.xml
rename to media/module/codecs/amrnb/dec/test/AndroidTest.xml
diff --git a/media/codecs/amrnb/dec/test/README.md b/media/module/codecs/amrnb/dec/test/README.md
similarity index 100%
rename from media/codecs/amrnb/dec/test/README.md
rename to media/module/codecs/amrnb/dec/test/README.md
diff --git a/media/codecs/amrnb/dec/test/amrnbdec_test.cpp b/media/module/codecs/amrnb/dec/test/amrnbdec_test.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/test/amrnbdec_test.cpp
rename to media/module/codecs/amrnb/dec/test/amrnbdec_test.cpp
diff --git a/media/codecs/amrnb/enc/Android.bp b/media/module/codecs/amrnb/enc/Android.bp
similarity index 100%
rename from media/codecs/amrnb/enc/Android.bp
rename to media/module/codecs/amrnb/enc/Android.bp
diff --git a/media/codecs/amrnb/enc/MODULE_LICENSE_APACHE2 b/media/module/codecs/amrnb/enc/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/amrnb/enc/MODULE_LICENSE_APACHE2
rename to media/module/codecs/amrnb/enc/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/amrnb/enc/NOTICE b/media/module/codecs/amrnb/enc/NOTICE
similarity index 100%
rename from media/codecs/amrnb/enc/NOTICE
rename to media/module/codecs/amrnb/enc/NOTICE
diff --git a/media/codecs/amrnb/enc/fuzzer/Android.bp b/media/module/codecs/amrnb/enc/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/amrnb/enc/fuzzer/Android.bp
rename to media/module/codecs/amrnb/enc/fuzzer/Android.bp
diff --git a/media/codecs/amrnb/enc/fuzzer/README.md b/media/module/codecs/amrnb/enc/fuzzer/README.md
similarity index 100%
rename from media/codecs/amrnb/enc/fuzzer/README.md
rename to media/module/codecs/amrnb/enc/fuzzer/README.md
diff --git a/media/codecs/amrnb/enc/fuzzer/amrnb_enc_fuzzer.cpp b/media/module/codecs/amrnb/enc/fuzzer/amrnb_enc_fuzzer.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/fuzzer/amrnb_enc_fuzzer.cpp
rename to media/module/codecs/amrnb/enc/fuzzer/amrnb_enc_fuzzer.cpp
diff --git a/media/codecs/amrnb/enc/src/amrencode.cpp b/media/module/codecs/amrnb/enc/src/amrencode.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/amrencode.cpp
rename to media/module/codecs/amrnb/enc/src/amrencode.cpp
diff --git a/media/codecs/amrnb/enc/src/amrencode.h b/media/module/codecs/amrnb/enc/src/amrencode.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/amrencode.h
rename to media/module/codecs/amrnb/enc/src/amrencode.h
diff --git a/media/codecs/amrnb/enc/src/autocorr.cpp b/media/module/codecs/amrnb/enc/src/autocorr.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/autocorr.cpp
rename to media/module/codecs/amrnb/enc/src/autocorr.cpp
diff --git a/media/codecs/amrnb/enc/src/autocorr.h b/media/module/codecs/amrnb/enc/src/autocorr.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/autocorr.h
rename to media/module/codecs/amrnb/enc/src/autocorr.h
diff --git a/media/codecs/amrnb/enc/src/c1035pf.cpp b/media/module/codecs/amrnb/enc/src/c1035pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/c1035pf.cpp
rename to media/module/codecs/amrnb/enc/src/c1035pf.cpp
diff --git a/media/codecs/amrnb/enc/src/c1035pf.h b/media/module/codecs/amrnb/enc/src/c1035pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/c1035pf.h
rename to media/module/codecs/amrnb/enc/src/c1035pf.h
diff --git a/media/codecs/amrnb/enc/src/c2_11pf.cpp b/media/module/codecs/amrnb/enc/src/c2_11pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/c2_11pf.cpp
rename to media/module/codecs/amrnb/enc/src/c2_11pf.cpp
diff --git a/media/codecs/amrnb/enc/src/c2_11pf.h b/media/module/codecs/amrnb/enc/src/c2_11pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/c2_11pf.h
rename to media/module/codecs/amrnb/enc/src/c2_11pf.h
diff --git a/media/codecs/amrnb/enc/src/c2_9pf.cpp b/media/module/codecs/amrnb/enc/src/c2_9pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/c2_9pf.cpp
rename to media/module/codecs/amrnb/enc/src/c2_9pf.cpp
diff --git a/media/codecs/amrnb/enc/src/c2_9pf.h b/media/module/codecs/amrnb/enc/src/c2_9pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/c2_9pf.h
rename to media/module/codecs/amrnb/enc/src/c2_9pf.h
diff --git a/media/codecs/amrnb/enc/src/c3_14pf.cpp b/media/module/codecs/amrnb/enc/src/c3_14pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/c3_14pf.cpp
rename to media/module/codecs/amrnb/enc/src/c3_14pf.cpp
diff --git a/media/codecs/amrnb/enc/src/c3_14pf.h b/media/module/codecs/amrnb/enc/src/c3_14pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/c3_14pf.h
rename to media/module/codecs/amrnb/enc/src/c3_14pf.h
diff --git a/media/codecs/amrnb/enc/src/c4_17pf.cpp b/media/module/codecs/amrnb/enc/src/c4_17pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/c4_17pf.cpp
rename to media/module/codecs/amrnb/enc/src/c4_17pf.cpp
diff --git a/media/codecs/amrnb/enc/src/c4_17pf.h b/media/module/codecs/amrnb/enc/src/c4_17pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/c4_17pf.h
rename to media/module/codecs/amrnb/enc/src/c4_17pf.h
diff --git a/media/codecs/amrnb/enc/src/c8_31pf.cpp b/media/module/codecs/amrnb/enc/src/c8_31pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/c8_31pf.cpp
rename to media/module/codecs/amrnb/enc/src/c8_31pf.cpp
diff --git a/media/codecs/amrnb/enc/src/c8_31pf.h b/media/module/codecs/amrnb/enc/src/c8_31pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/c8_31pf.h
rename to media/module/codecs/amrnb/enc/src/c8_31pf.h
diff --git a/media/codecs/amrnb/enc/src/calc_cor.cpp b/media/module/codecs/amrnb/enc/src/calc_cor.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/calc_cor.cpp
rename to media/module/codecs/amrnb/enc/src/calc_cor.cpp
diff --git a/media/codecs/amrnb/enc/src/calc_cor.h b/media/module/codecs/amrnb/enc/src/calc_cor.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/calc_cor.h
rename to media/module/codecs/amrnb/enc/src/calc_cor.h
diff --git a/media/codecs/amrnb/enc/src/calc_en.cpp b/media/module/codecs/amrnb/enc/src/calc_en.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/calc_en.cpp
rename to media/module/codecs/amrnb/enc/src/calc_en.cpp
diff --git a/media/codecs/amrnb/enc/src/calc_en.h b/media/module/codecs/amrnb/enc/src/calc_en.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/calc_en.h
rename to media/module/codecs/amrnb/enc/src/calc_en.h
diff --git a/media/codecs/amrnb/enc/src/cbsearch.cpp b/media/module/codecs/amrnb/enc/src/cbsearch.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/cbsearch.cpp
rename to media/module/codecs/amrnb/enc/src/cbsearch.cpp
diff --git a/media/codecs/amrnb/enc/src/cbsearch.h b/media/module/codecs/amrnb/enc/src/cbsearch.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/cbsearch.h
rename to media/module/codecs/amrnb/enc/src/cbsearch.h
diff --git a/media/codecs/amrnb/enc/src/cl_ltp.cpp b/media/module/codecs/amrnb/enc/src/cl_ltp.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/cl_ltp.cpp
rename to media/module/codecs/amrnb/enc/src/cl_ltp.cpp
diff --git a/media/codecs/amrnb/enc/src/cl_ltp.h b/media/module/codecs/amrnb/enc/src/cl_ltp.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/cl_ltp.h
rename to media/module/codecs/amrnb/enc/src/cl_ltp.h
diff --git a/media/codecs/amrnb/enc/src/cod_amr.cpp b/media/module/codecs/amrnb/enc/src/cod_amr.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/cod_amr.cpp
rename to media/module/codecs/amrnb/enc/src/cod_amr.cpp
diff --git a/media/codecs/amrnb/enc/src/cod_amr.h b/media/module/codecs/amrnb/enc/src/cod_amr.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/cod_amr.h
rename to media/module/codecs/amrnb/enc/src/cod_amr.h
diff --git a/media/codecs/amrnb/enc/src/convolve.cpp b/media/module/codecs/amrnb/enc/src/convolve.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/convolve.cpp
rename to media/module/codecs/amrnb/enc/src/convolve.cpp
diff --git a/media/codecs/amrnb/enc/src/convolve.h b/media/module/codecs/amrnb/enc/src/convolve.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/convolve.h
rename to media/module/codecs/amrnb/enc/src/convolve.h
diff --git a/media/codecs/amrnb/enc/src/cor_h.cpp b/media/module/codecs/amrnb/enc/src/cor_h.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/cor_h.cpp
rename to media/module/codecs/amrnb/enc/src/cor_h.cpp
diff --git a/media/codecs/amrnb/enc/src/cor_h.h b/media/module/codecs/amrnb/enc/src/cor_h.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/cor_h.h
rename to media/module/codecs/amrnb/enc/src/cor_h.h
diff --git a/media/codecs/amrnb/enc/src/cor_h_x.cpp b/media/module/codecs/amrnb/enc/src/cor_h_x.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/cor_h_x.cpp
rename to media/module/codecs/amrnb/enc/src/cor_h_x.cpp
diff --git a/media/codecs/amrnb/enc/src/cor_h_x.h b/media/module/codecs/amrnb/enc/src/cor_h_x.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/cor_h_x.h
rename to media/module/codecs/amrnb/enc/src/cor_h_x.h
diff --git a/media/codecs/amrnb/enc/src/cor_h_x2.cpp b/media/module/codecs/amrnb/enc/src/cor_h_x2.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/cor_h_x2.cpp
rename to media/module/codecs/amrnb/enc/src/cor_h_x2.cpp
diff --git a/media/codecs/amrnb/enc/src/cor_h_x2.h b/media/module/codecs/amrnb/enc/src/cor_h_x2.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/cor_h_x2.h
rename to media/module/codecs/amrnb/enc/src/cor_h_x2.h
diff --git a/media/codecs/amrnb/enc/src/corrwght_tab.cpp b/media/module/codecs/amrnb/enc/src/corrwght_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/corrwght_tab.cpp
rename to media/module/codecs/amrnb/enc/src/corrwght_tab.cpp
diff --git a/media/codecs/amrnb/enc/src/dtx_enc.cpp b/media/module/codecs/amrnb/enc/src/dtx_enc.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/dtx_enc.cpp
rename to media/module/codecs/amrnb/enc/src/dtx_enc.cpp
diff --git a/media/codecs/amrnb/enc/src/dtx_enc.h b/media/module/codecs/amrnb/enc/src/dtx_enc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/dtx_enc.h
rename to media/module/codecs/amrnb/enc/src/dtx_enc.h
diff --git a/media/codecs/amrnb/enc/src/enc_lag3.cpp b/media/module/codecs/amrnb/enc/src/enc_lag3.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/enc_lag3.cpp
rename to media/module/codecs/amrnb/enc/src/enc_lag3.cpp
diff --git a/media/codecs/amrnb/enc/src/enc_lag3.h b/media/module/codecs/amrnb/enc/src/enc_lag3.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/enc_lag3.h
rename to media/module/codecs/amrnb/enc/src/enc_lag3.h
diff --git a/media/codecs/amrnb/enc/src/enc_lag6.cpp b/media/module/codecs/amrnb/enc/src/enc_lag6.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/enc_lag6.cpp
rename to media/module/codecs/amrnb/enc/src/enc_lag6.cpp
diff --git a/media/codecs/amrnb/enc/src/enc_lag6.h b/media/module/codecs/amrnb/enc/src/enc_lag6.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/enc_lag6.h
rename to media/module/codecs/amrnb/enc/src/enc_lag6.h
diff --git a/media/codecs/amrnb/enc/src/enc_output_format_tab.cpp b/media/module/codecs/amrnb/enc/src/enc_output_format_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/enc_output_format_tab.cpp
rename to media/module/codecs/amrnb/enc/src/enc_output_format_tab.cpp
diff --git a/media/codecs/amrnb/enc/src/ets_to_if2.cpp b/media/module/codecs/amrnb/enc/src/ets_to_if2.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/ets_to_if2.cpp
rename to media/module/codecs/amrnb/enc/src/ets_to_if2.cpp
diff --git a/media/codecs/amrnb/enc/src/ets_to_if2.h b/media/module/codecs/amrnb/enc/src/ets_to_if2.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/ets_to_if2.h
rename to media/module/codecs/amrnb/enc/src/ets_to_if2.h
diff --git a/media/codecs/amrnb/enc/src/ets_to_wmf.cpp b/media/module/codecs/amrnb/enc/src/ets_to_wmf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/ets_to_wmf.cpp
rename to media/module/codecs/amrnb/enc/src/ets_to_wmf.cpp
diff --git a/media/codecs/amrnb/enc/src/ets_to_wmf.h b/media/module/codecs/amrnb/enc/src/ets_to_wmf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/ets_to_wmf.h
rename to media/module/codecs/amrnb/enc/src/ets_to_wmf.h
diff --git a/media/codecs/amrnb/enc/src/g_adapt.cpp b/media/module/codecs/amrnb/enc/src/g_adapt.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/g_adapt.cpp
rename to media/module/codecs/amrnb/enc/src/g_adapt.cpp
diff --git a/media/codecs/amrnb/enc/src/g_adapt.h b/media/module/codecs/amrnb/enc/src/g_adapt.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/g_adapt.h
rename to media/module/codecs/amrnb/enc/src/g_adapt.h
diff --git a/media/codecs/amrnb/enc/src/g_code.cpp b/media/module/codecs/amrnb/enc/src/g_code.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/g_code.cpp
rename to media/module/codecs/amrnb/enc/src/g_code.cpp
diff --git a/media/codecs/amrnb/enc/src/g_code.h b/media/module/codecs/amrnb/enc/src/g_code.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/g_code.h
rename to media/module/codecs/amrnb/enc/src/g_code.h
diff --git a/media/codecs/amrnb/enc/src/g_pitch.cpp b/media/module/codecs/amrnb/enc/src/g_pitch.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/g_pitch.cpp
rename to media/module/codecs/amrnb/enc/src/g_pitch.cpp
diff --git a/media/codecs/amrnb/enc/src/g_pitch.h b/media/module/codecs/amrnb/enc/src/g_pitch.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/g_pitch.h
rename to media/module/codecs/amrnb/enc/src/g_pitch.h
diff --git a/media/codecs/amrnb/enc/src/gain_q.cpp b/media/module/codecs/amrnb/enc/src/gain_q.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/gain_q.cpp
rename to media/module/codecs/amrnb/enc/src/gain_q.cpp
diff --git a/media/codecs/amrnb/enc/src/gain_q.h b/media/module/codecs/amrnb/enc/src/gain_q.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/gain_q.h
rename to media/module/codecs/amrnb/enc/src/gain_q.h
diff --git a/media/codecs/amrnb/enc/src/gsmamr_enc.h b/media/module/codecs/amrnb/enc/src/gsmamr_enc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/gsmamr_enc.h
rename to media/module/codecs/amrnb/enc/src/gsmamr_enc.h
diff --git a/media/codecs/amrnb/enc/src/hp_max.cpp b/media/module/codecs/amrnb/enc/src/hp_max.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/hp_max.cpp
rename to media/module/codecs/amrnb/enc/src/hp_max.cpp
diff --git a/media/codecs/amrnb/enc/src/hp_max.h b/media/module/codecs/amrnb/enc/src/hp_max.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/hp_max.h
rename to media/module/codecs/amrnb/enc/src/hp_max.h
diff --git a/media/codecs/amrnb/enc/src/inter_36.cpp b/media/module/codecs/amrnb/enc/src/inter_36.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/inter_36.cpp
rename to media/module/codecs/amrnb/enc/src/inter_36.cpp
diff --git a/media/codecs/amrnb/enc/src/inter_36.h b/media/module/codecs/amrnb/enc/src/inter_36.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/inter_36.h
rename to media/module/codecs/amrnb/enc/src/inter_36.h
diff --git a/media/codecs/amrnb/enc/src/inter_36_tab.cpp b/media/module/codecs/amrnb/enc/src/inter_36_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/inter_36_tab.cpp
rename to media/module/codecs/amrnb/enc/src/inter_36_tab.cpp
diff --git a/media/codecs/amrnb/enc/src/inter_36_tab.h b/media/module/codecs/amrnb/enc/src/inter_36_tab.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/inter_36_tab.h
rename to media/module/codecs/amrnb/enc/src/inter_36_tab.h
diff --git a/media/codecs/amrnb/enc/src/l_comp.cpp b/media/module/codecs/amrnb/enc/src/l_comp.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/l_comp.cpp
rename to media/module/codecs/amrnb/enc/src/l_comp.cpp
diff --git a/media/codecs/amrnb/enc/src/l_extract.cpp b/media/module/codecs/amrnb/enc/src/l_extract.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/l_extract.cpp
rename to media/module/codecs/amrnb/enc/src/l_extract.cpp
diff --git a/media/codecs/amrnb/enc/src/l_negate.cpp b/media/module/codecs/amrnb/enc/src/l_negate.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/l_negate.cpp
rename to media/module/codecs/amrnb/enc/src/l_negate.cpp
diff --git a/media/codecs/amrnb/enc/src/lag_wind.cpp b/media/module/codecs/amrnb/enc/src/lag_wind.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/lag_wind.cpp
rename to media/module/codecs/amrnb/enc/src/lag_wind.cpp
diff --git a/media/codecs/amrnb/enc/src/lag_wind.h b/media/module/codecs/amrnb/enc/src/lag_wind.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/lag_wind.h
rename to media/module/codecs/amrnb/enc/src/lag_wind.h
diff --git a/media/codecs/amrnb/enc/src/lag_wind_tab.cpp b/media/module/codecs/amrnb/enc/src/lag_wind_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/lag_wind_tab.cpp
rename to media/module/codecs/amrnb/enc/src/lag_wind_tab.cpp
diff --git a/media/codecs/amrnb/enc/src/lag_wind_tab.h b/media/module/codecs/amrnb/enc/src/lag_wind_tab.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/lag_wind_tab.h
rename to media/module/codecs/amrnb/enc/src/lag_wind_tab.h
diff --git a/media/codecs/amrnb/enc/src/levinson.cpp b/media/module/codecs/amrnb/enc/src/levinson.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/levinson.cpp
rename to media/module/codecs/amrnb/enc/src/levinson.cpp
diff --git a/media/codecs/amrnb/enc/src/levinson.h b/media/module/codecs/amrnb/enc/src/levinson.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/levinson.h
rename to media/module/codecs/amrnb/enc/src/levinson.h
diff --git a/media/codecs/amrnb/enc/src/lpc.cpp b/media/module/codecs/amrnb/enc/src/lpc.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/lpc.cpp
rename to media/module/codecs/amrnb/enc/src/lpc.cpp
diff --git a/media/codecs/amrnb/enc/src/lpc.h b/media/module/codecs/amrnb/enc/src/lpc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/lpc.h
rename to media/module/codecs/amrnb/enc/src/lpc.h
diff --git a/media/codecs/amrnb/enc/src/ol_ltp.cpp b/media/module/codecs/amrnb/enc/src/ol_ltp.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/ol_ltp.cpp
rename to media/module/codecs/amrnb/enc/src/ol_ltp.cpp
diff --git a/media/codecs/amrnb/enc/src/ol_ltp.h b/media/module/codecs/amrnb/enc/src/ol_ltp.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/ol_ltp.h
rename to media/module/codecs/amrnb/enc/src/ol_ltp.h
diff --git a/media/codecs/amrnb/enc/src/p_ol_wgh.cpp b/media/module/codecs/amrnb/enc/src/p_ol_wgh.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/p_ol_wgh.cpp
rename to media/module/codecs/amrnb/enc/src/p_ol_wgh.cpp
diff --git a/media/codecs/amrnb/enc/src/pitch_fr.cpp b/media/module/codecs/amrnb/enc/src/pitch_fr.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/pitch_fr.cpp
rename to media/module/codecs/amrnb/enc/src/pitch_fr.cpp
diff --git a/media/codecs/amrnb/enc/src/pitch_fr.h b/media/module/codecs/amrnb/enc/src/pitch_fr.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/pitch_fr.h
rename to media/module/codecs/amrnb/enc/src/pitch_fr.h
diff --git a/media/codecs/amrnb/enc/src/pitch_ol.cpp b/media/module/codecs/amrnb/enc/src/pitch_ol.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/pitch_ol.cpp
rename to media/module/codecs/amrnb/enc/src/pitch_ol.cpp
diff --git a/media/codecs/amrnb/enc/src/pitch_ol.h b/media/module/codecs/amrnb/enc/src/pitch_ol.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/pitch_ol.h
rename to media/module/codecs/amrnb/enc/src/pitch_ol.h
diff --git a/media/codecs/amrnb/enc/src/pre_big.cpp b/media/module/codecs/amrnb/enc/src/pre_big.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/pre_big.cpp
rename to media/module/codecs/amrnb/enc/src/pre_big.cpp
diff --git a/media/codecs/amrnb/enc/src/pre_big.h b/media/module/codecs/amrnb/enc/src/pre_big.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/pre_big.h
rename to media/module/codecs/amrnb/enc/src/pre_big.h
diff --git a/media/codecs/amrnb/enc/src/pre_proc.cpp b/media/module/codecs/amrnb/enc/src/pre_proc.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/pre_proc.cpp
rename to media/module/codecs/amrnb/enc/src/pre_proc.cpp
diff --git a/media/codecs/amrnb/enc/src/pre_proc.h b/media/module/codecs/amrnb/enc/src/pre_proc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/pre_proc.h
rename to media/module/codecs/amrnb/enc/src/pre_proc.h
diff --git a/media/codecs/amrnb/enc/src/prm2bits.cpp b/media/module/codecs/amrnb/enc/src/prm2bits.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/prm2bits.cpp
rename to media/module/codecs/amrnb/enc/src/prm2bits.cpp
diff --git a/media/codecs/amrnb/enc/src/prm2bits.h b/media/module/codecs/amrnb/enc/src/prm2bits.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/prm2bits.h
rename to media/module/codecs/amrnb/enc/src/prm2bits.h
diff --git a/media/codecs/amrnb/enc/src/q_gain_c.cpp b/media/module/codecs/amrnb/enc/src/q_gain_c.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/q_gain_c.cpp
rename to media/module/codecs/amrnb/enc/src/q_gain_c.cpp
diff --git a/media/codecs/amrnb/enc/src/q_gain_c.h b/media/module/codecs/amrnb/enc/src/q_gain_c.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/q_gain_c.h
rename to media/module/codecs/amrnb/enc/src/q_gain_c.h
diff --git a/media/codecs/amrnb/enc/src/q_gain_p.cpp b/media/module/codecs/amrnb/enc/src/q_gain_p.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/q_gain_p.cpp
rename to media/module/codecs/amrnb/enc/src/q_gain_p.cpp
diff --git a/media/codecs/amrnb/enc/src/q_gain_p.h b/media/module/codecs/amrnb/enc/src/q_gain_p.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/q_gain_p.h
rename to media/module/codecs/amrnb/enc/src/q_gain_p.h
diff --git a/media/codecs/amrnb/enc/src/qgain475.cpp b/media/module/codecs/amrnb/enc/src/qgain475.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/qgain475.cpp
rename to media/module/codecs/amrnb/enc/src/qgain475.cpp
diff --git a/media/codecs/amrnb/enc/src/qgain475.h b/media/module/codecs/amrnb/enc/src/qgain475.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/qgain475.h
rename to media/module/codecs/amrnb/enc/src/qgain475.h
diff --git a/media/codecs/amrnb/enc/src/qgain795.cpp b/media/module/codecs/amrnb/enc/src/qgain795.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/qgain795.cpp
rename to media/module/codecs/amrnb/enc/src/qgain795.cpp
diff --git a/media/codecs/amrnb/enc/src/qgain795.h b/media/module/codecs/amrnb/enc/src/qgain795.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/qgain795.h
rename to media/module/codecs/amrnb/enc/src/qgain795.h
diff --git a/media/codecs/amrnb/enc/src/qua_gain.cpp b/media/module/codecs/amrnb/enc/src/qua_gain.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/qua_gain.cpp
rename to media/module/codecs/amrnb/enc/src/qua_gain.cpp
diff --git a/media/codecs/amrnb/enc/src/s10_8pf.cpp b/media/module/codecs/amrnb/enc/src/s10_8pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/s10_8pf.cpp
rename to media/module/codecs/amrnb/enc/src/s10_8pf.cpp
diff --git a/media/codecs/amrnb/enc/src/s10_8pf.h b/media/module/codecs/amrnb/enc/src/s10_8pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/s10_8pf.h
rename to media/module/codecs/amrnb/enc/src/s10_8pf.h
diff --git a/media/codecs/amrnb/enc/src/set_sign.cpp b/media/module/codecs/amrnb/enc/src/set_sign.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/set_sign.cpp
rename to media/module/codecs/amrnb/enc/src/set_sign.cpp
diff --git a/media/codecs/amrnb/enc/src/set_sign.h b/media/module/codecs/amrnb/enc/src/set_sign.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/set_sign.h
rename to media/module/codecs/amrnb/enc/src/set_sign.h
diff --git a/media/codecs/amrnb/enc/src/sid_sync.cpp b/media/module/codecs/amrnb/enc/src/sid_sync.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/sid_sync.cpp
rename to media/module/codecs/amrnb/enc/src/sid_sync.cpp
diff --git a/media/codecs/amrnb/enc/src/sid_sync.h b/media/module/codecs/amrnb/enc/src/sid_sync.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/sid_sync.h
rename to media/module/codecs/amrnb/enc/src/sid_sync.h
diff --git a/media/codecs/amrnb/enc/src/sp_enc.cpp b/media/module/codecs/amrnb/enc/src/sp_enc.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/sp_enc.cpp
rename to media/module/codecs/amrnb/enc/src/sp_enc.cpp
diff --git a/media/codecs/amrnb/enc/src/sp_enc.h b/media/module/codecs/amrnb/enc/src/sp_enc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/sp_enc.h
rename to media/module/codecs/amrnb/enc/src/sp_enc.h
diff --git a/media/codecs/amrnb/enc/src/spreproc.cpp b/media/module/codecs/amrnb/enc/src/spreproc.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/spreproc.cpp
rename to media/module/codecs/amrnb/enc/src/spreproc.cpp
diff --git a/media/codecs/amrnb/enc/src/spreproc.h b/media/module/codecs/amrnb/enc/src/spreproc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/spreproc.h
rename to media/module/codecs/amrnb/enc/src/spreproc.h
diff --git a/media/codecs/amrnb/enc/src/spstproc.cpp b/media/module/codecs/amrnb/enc/src/spstproc.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/spstproc.cpp
rename to media/module/codecs/amrnb/enc/src/spstproc.cpp
diff --git a/media/codecs/amrnb/enc/src/spstproc.h b/media/module/codecs/amrnb/enc/src/spstproc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/spstproc.h
rename to media/module/codecs/amrnb/enc/src/spstproc.h
diff --git a/media/codecs/amrnb/enc/src/ton_stab.cpp b/media/module/codecs/amrnb/enc/src/ton_stab.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/ton_stab.cpp
rename to media/module/codecs/amrnb/enc/src/ton_stab.cpp
diff --git a/media/codecs/amrnb/enc/src/ton_stab.h b/media/module/codecs/amrnb/enc/src/ton_stab.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/ton_stab.h
rename to media/module/codecs/amrnb/enc/src/ton_stab.h
diff --git a/media/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h b/media/module/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h
similarity index 100%
rename from media/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h
rename to media/module/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h
diff --git a/media/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp b/media/module/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
rename to media/module/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
diff --git a/media/codecs/amrnb/enc/test/Android.bp b/media/module/codecs/amrnb/enc/test/Android.bp
similarity index 90%
rename from media/codecs/amrnb/enc/test/Android.bp
rename to media/module/codecs/amrnb/enc/test/Android.bp
index 7e393e3..5871486 100644
--- a/media/codecs/amrnb/enc/test/Android.bp
+++ b/media/module/codecs/amrnb/enc/test/Android.bp
@@ -58,4 +58,7 @@
"signed-integer-overflow",
],
},
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.zip?unzip=true",
+ ],
}
diff --git a/media/codecs/amrnb/enc/test/AndroidTest.xml b/media/module/codecs/amrnb/enc/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/amrnb/enc/test/AndroidTest.xml
rename to media/module/codecs/amrnb/enc/test/AndroidTest.xml
diff --git a/media/codecs/amrnb/enc/test/README.md b/media/module/codecs/amrnb/enc/test/README.md
similarity index 100%
rename from media/codecs/amrnb/enc/test/README.md
rename to media/module/codecs/amrnb/enc/test/README.md
diff --git a/media/codecs/amrnb/enc/test/amrnb_enc_test.cpp b/media/module/codecs/amrnb/enc/test/amrnb_enc_test.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/test/amrnb_enc_test.cpp
rename to media/module/codecs/amrnb/enc/test/amrnb_enc_test.cpp
diff --git a/media/codecs/amrnb/fuzzer/Android.bp b/media/module/codecs/amrnb/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/amrnb/fuzzer/Android.bp
rename to media/module/codecs/amrnb/fuzzer/Android.bp
diff --git a/media/codecs/amrnb/fuzzer/README.md b/media/module/codecs/amrnb/fuzzer/README.md
similarity index 100%
rename from media/codecs/amrnb/fuzzer/README.md
rename to media/module/codecs/amrnb/fuzzer/README.md
diff --git a/media/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp b/media/module/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp
similarity index 100%
rename from media/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp
rename to media/module/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp
diff --git a/media/codecs/amrnb/patent_disclaimer.txt b/media/module/codecs/amrnb/patent_disclaimer.txt
similarity index 100%
rename from media/codecs/amrnb/patent_disclaimer.txt
rename to media/module/codecs/amrnb/patent_disclaimer.txt
diff --git a/media/codecs/amrwb/dec/Android.bp b/media/module/codecs/amrwb/dec/Android.bp
similarity index 100%
rename from media/codecs/amrwb/dec/Android.bp
rename to media/module/codecs/amrwb/dec/Android.bp
diff --git a/media/codecs/amrwb/dec/MODULE_LICENSE_APACHE2 b/media/module/codecs/amrwb/dec/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/amrwb/dec/MODULE_LICENSE_APACHE2
rename to media/module/codecs/amrwb/dec/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/amrwb/dec/NOTICE b/media/module/codecs/amrwb/dec/NOTICE
similarity index 100%
rename from media/codecs/amrwb/dec/NOTICE
rename to media/module/codecs/amrwb/dec/NOTICE
diff --git a/media/codecs/amrwb/dec/TEST_MAPPING b/media/module/codecs/amrwb/dec/TEST_MAPPING
similarity index 100%
rename from media/codecs/amrwb/dec/TEST_MAPPING
rename to media/module/codecs/amrwb/dec/TEST_MAPPING
diff --git a/media/codecs/amrwb/dec/fuzzer/Android.bp b/media/module/codecs/amrwb/dec/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/amrwb/dec/fuzzer/Android.bp
rename to media/module/codecs/amrwb/dec/fuzzer/Android.bp
diff --git a/media/codecs/amrwb/dec/fuzzer/README.md b/media/module/codecs/amrwb/dec/fuzzer/README.md
similarity index 100%
rename from media/codecs/amrwb/dec/fuzzer/README.md
rename to media/module/codecs/amrwb/dec/fuzzer/README.md
diff --git a/media/codecs/amrwb/dec/fuzzer/amrwb_dec_fuzzer.cpp b/media/module/codecs/amrwb/dec/fuzzer/amrwb_dec_fuzzer.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/fuzzer/amrwb_dec_fuzzer.cpp
rename to media/module/codecs/amrwb/dec/fuzzer/amrwb_dec_fuzzer.cpp
diff --git a/media/codecs/amrwb/dec/include/pvamrwbdecoder_api.h b/media/module/codecs/amrwb/dec/include/pvamrwbdecoder_api.h
similarity index 100%
rename from media/codecs/amrwb/dec/include/pvamrwbdecoder_api.h
rename to media/module/codecs/amrwb/dec/include/pvamrwbdecoder_api.h
diff --git a/media/codecs/amrwb/dec/patent_disclaimer.txt b/media/module/codecs/amrwb/dec/patent_disclaimer.txt
similarity index 100%
rename from media/codecs/amrwb/dec/patent_disclaimer.txt
rename to media/module/codecs/amrwb/dec/patent_disclaimer.txt
diff --git a/media/codecs/amrwb/dec/src/agc2_amr_wb.cpp b/media/module/codecs/amrwb/dec/src/agc2_amr_wb.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/agc2_amr_wb.cpp
rename to media/module/codecs/amrwb/dec/src/agc2_amr_wb.cpp
diff --git a/media/codecs/amrwb/dec/src/band_pass_6k_7k.cpp b/media/module/codecs/amrwb/dec/src/band_pass_6k_7k.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/band_pass_6k_7k.cpp
rename to media/module/codecs/amrwb/dec/src/band_pass_6k_7k.cpp
diff --git a/media/codecs/amrwb/dec/src/dec_acelp_2p_in_64.cpp b/media/module/codecs/amrwb/dec/src/dec_acelp_2p_in_64.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/dec_acelp_2p_in_64.cpp
rename to media/module/codecs/amrwb/dec/src/dec_acelp_2p_in_64.cpp
diff --git a/media/codecs/amrwb/dec/src/dec_acelp_4p_in_64.cpp b/media/module/codecs/amrwb/dec/src/dec_acelp_4p_in_64.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/dec_acelp_4p_in_64.cpp
rename to media/module/codecs/amrwb/dec/src/dec_acelp_4p_in_64.cpp
diff --git a/media/codecs/amrwb/dec/src/dec_alg_codebook.cpp b/media/module/codecs/amrwb/dec/src/dec_alg_codebook.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/dec_alg_codebook.cpp
rename to media/module/codecs/amrwb/dec/src/dec_alg_codebook.cpp
diff --git a/media/codecs/amrwb/dec/src/dec_gain2_amr_wb.cpp b/media/module/codecs/amrwb/dec/src/dec_gain2_amr_wb.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/dec_gain2_amr_wb.cpp
rename to media/module/codecs/amrwb/dec/src/dec_gain2_amr_wb.cpp
diff --git a/media/codecs/amrwb/dec/src/deemphasis_32.cpp b/media/module/codecs/amrwb/dec/src/deemphasis_32.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/deemphasis_32.cpp
rename to media/module/codecs/amrwb/dec/src/deemphasis_32.cpp
diff --git a/media/codecs/amrwb/dec/src/dtx.h b/media/module/codecs/amrwb/dec/src/dtx.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/dtx.h
rename to media/module/codecs/amrwb/dec/src/dtx.h
diff --git a/media/codecs/amrwb/dec/src/dtx_decoder_amr_wb.cpp b/media/module/codecs/amrwb/dec/src/dtx_decoder_amr_wb.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/dtx_decoder_amr_wb.cpp
rename to media/module/codecs/amrwb/dec/src/dtx_decoder_amr_wb.cpp
diff --git a/media/codecs/amrwb/dec/src/e_pv_amrwbdec.h b/media/module/codecs/amrwb/dec/src/e_pv_amrwbdec.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/e_pv_amrwbdec.h
rename to media/module/codecs/amrwb/dec/src/e_pv_amrwbdec.h
diff --git a/media/codecs/amrwb/dec/src/get_amr_wb_bits.cpp b/media/module/codecs/amrwb/dec/src/get_amr_wb_bits.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/get_amr_wb_bits.cpp
rename to media/module/codecs/amrwb/dec/src/get_amr_wb_bits.cpp
diff --git a/media/codecs/amrwb/dec/src/get_amr_wb_bits.h b/media/module/codecs/amrwb/dec/src/get_amr_wb_bits.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/get_amr_wb_bits.h
rename to media/module/codecs/amrwb/dec/src/get_amr_wb_bits.h
diff --git a/media/codecs/amrwb/dec/src/highpass_400hz_at_12k8.cpp b/media/module/codecs/amrwb/dec/src/highpass_400hz_at_12k8.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/highpass_400hz_at_12k8.cpp
rename to media/module/codecs/amrwb/dec/src/highpass_400hz_at_12k8.cpp
diff --git a/media/codecs/amrwb/dec/src/highpass_50hz_at_12k8.cpp b/media/module/codecs/amrwb/dec/src/highpass_50hz_at_12k8.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/highpass_50hz_at_12k8.cpp
rename to media/module/codecs/amrwb/dec/src/highpass_50hz_at_12k8.cpp
diff --git a/media/codecs/amrwb/dec/src/homing_amr_wb_dec.cpp b/media/module/codecs/amrwb/dec/src/homing_amr_wb_dec.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/homing_amr_wb_dec.cpp
rename to media/module/codecs/amrwb/dec/src/homing_amr_wb_dec.cpp
diff --git a/media/codecs/amrwb/dec/src/interpolate_isp.cpp b/media/module/codecs/amrwb/dec/src/interpolate_isp.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/interpolate_isp.cpp
rename to media/module/codecs/amrwb/dec/src/interpolate_isp.cpp
diff --git a/media/codecs/amrwb/dec/src/isf_extrapolation.cpp b/media/module/codecs/amrwb/dec/src/isf_extrapolation.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/isf_extrapolation.cpp
rename to media/module/codecs/amrwb/dec/src/isf_extrapolation.cpp
diff --git a/media/codecs/amrwb/dec/src/isp_az.cpp b/media/module/codecs/amrwb/dec/src/isp_az.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/isp_az.cpp
rename to media/module/codecs/amrwb/dec/src/isp_az.cpp
diff --git a/media/codecs/amrwb/dec/src/isp_isf.cpp b/media/module/codecs/amrwb/dec/src/isp_isf.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/isp_isf.cpp
rename to media/module/codecs/amrwb/dec/src/isp_isf.cpp
diff --git a/media/codecs/amrwb/dec/src/lagconceal.cpp b/media/module/codecs/amrwb/dec/src/lagconceal.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/lagconceal.cpp
rename to media/module/codecs/amrwb/dec/src/lagconceal.cpp
diff --git a/media/codecs/amrwb/dec/src/low_pass_filt_7k.cpp b/media/module/codecs/amrwb/dec/src/low_pass_filt_7k.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/low_pass_filt_7k.cpp
rename to media/module/codecs/amrwb/dec/src/low_pass_filt_7k.cpp
diff --git a/media/codecs/amrwb/dec/src/median5.cpp b/media/module/codecs/amrwb/dec/src/median5.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/median5.cpp
rename to media/module/codecs/amrwb/dec/src/median5.cpp
diff --git a/media/codecs/amrwb/dec/src/mime_io.cpp b/media/module/codecs/amrwb/dec/src/mime_io.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/mime_io.cpp
rename to media/module/codecs/amrwb/dec/src/mime_io.cpp
diff --git a/media/codecs/amrwb/dec/src/mime_io.h b/media/module/codecs/amrwb/dec/src/mime_io.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/mime_io.h
rename to media/module/codecs/amrwb/dec/src/mime_io.h
diff --git a/media/codecs/amrwb/dec/src/noise_gen_amrwb.cpp b/media/module/codecs/amrwb/dec/src/noise_gen_amrwb.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/noise_gen_amrwb.cpp
rename to media/module/codecs/amrwb/dec/src/noise_gen_amrwb.cpp
diff --git a/media/codecs/amrwb/dec/src/normalize_amr_wb.cpp b/media/module/codecs/amrwb/dec/src/normalize_amr_wb.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/normalize_amr_wb.cpp
rename to media/module/codecs/amrwb/dec/src/normalize_amr_wb.cpp
diff --git a/media/codecs/amrwb/dec/src/normalize_amr_wb.h b/media/module/codecs/amrwb/dec/src/normalize_amr_wb.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/normalize_amr_wb.h
rename to media/module/codecs/amrwb/dec/src/normalize_amr_wb.h
diff --git a/media/codecs/amrwb/dec/src/oversamp_12k8_to_16k.cpp b/media/module/codecs/amrwb/dec/src/oversamp_12k8_to_16k.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/oversamp_12k8_to_16k.cpp
rename to media/module/codecs/amrwb/dec/src/oversamp_12k8_to_16k.cpp
diff --git a/media/codecs/amrwb/dec/src/phase_dispersion.cpp b/media/module/codecs/amrwb/dec/src/phase_dispersion.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/phase_dispersion.cpp
rename to media/module/codecs/amrwb/dec/src/phase_dispersion.cpp
diff --git a/media/codecs/amrwb/dec/src/pit_shrp.cpp b/media/module/codecs/amrwb/dec/src/pit_shrp.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/pit_shrp.cpp
rename to media/module/codecs/amrwb/dec/src/pit_shrp.cpp
diff --git a/media/codecs/amrwb/dec/src/pred_lt4.cpp b/media/module/codecs/amrwb/dec/src/pred_lt4.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/pred_lt4.cpp
rename to media/module/codecs/amrwb/dec/src/pred_lt4.cpp
diff --git a/media/codecs/amrwb/dec/src/preemph_amrwb_dec.cpp b/media/module/codecs/amrwb/dec/src/preemph_amrwb_dec.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/preemph_amrwb_dec.cpp
rename to media/module/codecs/amrwb/dec/src/preemph_amrwb_dec.cpp
diff --git a/media/codecs/amrwb/dec/src/pv_amr_wb_type_defs.h b/media/module/codecs/amrwb/dec/src/pv_amr_wb_type_defs.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pv_amr_wb_type_defs.h
rename to media/module/codecs/amrwb/dec/src/pv_amr_wb_type_defs.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwb_math_op.cpp b/media/module/codecs/amrwb/dec/src/pvamrwb_math_op.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwb_math_op.cpp
rename to media/module/codecs/amrwb/dec/src/pvamrwb_math_op.cpp
diff --git a/media/codecs/amrwb/dec/src/pvamrwb_math_op.h b/media/module/codecs/amrwb/dec/src/pvamrwb_math_op.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwb_math_op.h
rename to media/module/codecs/amrwb/dec/src/pvamrwb_math_op.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder.cpp b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder.cpp
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder.cpp
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_acelp.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_acelp.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_acelp.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_acelp.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_armv5.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_armv5.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_armv5.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_armv5.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_cequivalent.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_cequivalent.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_cequivalent.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_cequivalent.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_gcc_armv5.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_gcc_armv5.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_gcc_armv5.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_gcc_armv5.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_cnst.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_cnst.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_cnst.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_cnst.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_mem_funcs.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_mem_funcs.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_mem_funcs.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_mem_funcs.h
diff --git a/media/codecs/amrwb/dec/src/q_gain2_tab.cpp b/media/module/codecs/amrwb/dec/src/q_gain2_tab.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/q_gain2_tab.cpp
rename to media/module/codecs/amrwb/dec/src/q_gain2_tab.cpp
diff --git a/media/codecs/amrwb/dec/src/q_pulse.h b/media/module/codecs/amrwb/dec/src/q_pulse.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/q_pulse.h
rename to media/module/codecs/amrwb/dec/src/q_pulse.h
diff --git a/media/codecs/amrwb/dec/src/qisf_ns.cpp b/media/module/codecs/amrwb/dec/src/qisf_ns.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/qisf_ns.cpp
rename to media/module/codecs/amrwb/dec/src/qisf_ns.cpp
diff --git a/media/codecs/amrwb/dec/src/qisf_ns.h b/media/module/codecs/amrwb/dec/src/qisf_ns.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/qisf_ns.h
rename to media/module/codecs/amrwb/dec/src/qisf_ns.h
diff --git a/media/codecs/amrwb/dec/src/qisf_ns_tab.cpp b/media/module/codecs/amrwb/dec/src/qisf_ns_tab.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/qisf_ns_tab.cpp
rename to media/module/codecs/amrwb/dec/src/qisf_ns_tab.cpp
diff --git a/media/codecs/amrwb/dec/src/qpisf_2s.cpp b/media/module/codecs/amrwb/dec/src/qpisf_2s.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/qpisf_2s.cpp
rename to media/module/codecs/amrwb/dec/src/qpisf_2s.cpp
diff --git a/media/codecs/amrwb/dec/src/qpisf_2s.h b/media/module/codecs/amrwb/dec/src/qpisf_2s.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/qpisf_2s.h
rename to media/module/codecs/amrwb/dec/src/qpisf_2s.h
diff --git a/media/codecs/amrwb/dec/src/qpisf_2s_tab.cpp b/media/module/codecs/amrwb/dec/src/qpisf_2s_tab.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/qpisf_2s_tab.cpp
rename to media/module/codecs/amrwb/dec/src/qpisf_2s_tab.cpp
diff --git a/media/codecs/amrwb/dec/src/scale_signal.cpp b/media/module/codecs/amrwb/dec/src/scale_signal.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/scale_signal.cpp
rename to media/module/codecs/amrwb/dec/src/scale_signal.cpp
diff --git a/media/codecs/amrwb/dec/src/synthesis_amr_wb.cpp b/media/module/codecs/amrwb/dec/src/synthesis_amr_wb.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/synthesis_amr_wb.cpp
rename to media/module/codecs/amrwb/dec/src/synthesis_amr_wb.cpp
diff --git a/media/codecs/amrwb/dec/src/synthesis_amr_wb.h b/media/module/codecs/amrwb/dec/src/synthesis_amr_wb.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/synthesis_amr_wb.h
rename to media/module/codecs/amrwb/dec/src/synthesis_amr_wb.h
diff --git a/media/codecs/amrwb/dec/src/voice_factor.cpp b/media/module/codecs/amrwb/dec/src/voice_factor.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/voice_factor.cpp
rename to media/module/codecs/amrwb/dec/src/voice_factor.cpp
diff --git a/media/codecs/amrwb/dec/src/wb_syn_filt.cpp b/media/module/codecs/amrwb/dec/src/wb_syn_filt.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/wb_syn_filt.cpp
rename to media/module/codecs/amrwb/dec/src/wb_syn_filt.cpp
diff --git a/media/codecs/amrwb/dec/src/weight_amrwb_lpc.cpp b/media/module/codecs/amrwb/dec/src/weight_amrwb_lpc.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/weight_amrwb_lpc.cpp
rename to media/module/codecs/amrwb/dec/src/weight_amrwb_lpc.cpp
diff --git a/media/codecs/amrwb/dec/test/AmrwbDecTestEnvironment.h b/media/module/codecs/amrwb/dec/test/AmrwbDecTestEnvironment.h
similarity index 100%
rename from media/codecs/amrwb/dec/test/AmrwbDecTestEnvironment.h
rename to media/module/codecs/amrwb/dec/test/AmrwbDecTestEnvironment.h
diff --git a/media/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp b/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
similarity index 89%
rename from media/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
rename to media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
index 7221b92..2cc88ce 100644
--- a/media/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
+++ b/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
@@ -21,6 +21,7 @@
#include <utils/Log.h>
#include <audio_utils/sndfile.h>
+#include <memory>
#include <stdio.h>
#include "pvamrwbdecoder.h"
@@ -121,7 +122,7 @@
TEST_F(AmrwbDecoderTest, MultiCreateAmrwbDecoderTest) {
uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
- void *decoderBuf = malloc(memRequirements);
+ std::unique_ptr<char[]> decoderBuf(new char[memRequirements]);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
@@ -129,25 +130,21 @@
void *amrHandle = nullptr;
int16_t *decoderCookie;
for (int count = 0; count < kMaxCount; count++) {
- pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+ pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
ALOGV("Decoder created successfully");
}
- if (decoderBuf) {
- free(decoderBuf);
- decoderBuf = nullptr;
- }
}
TEST_P(AmrwbDecoderTest, DecodeTest) {
uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
- void *decoderBuf = malloc(memRequirements);
+ std::unique_ptr<char[]> decoderBuf(new char[memRequirements]);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
void *amrHandle = nullptr;
int16_t *decoderCookie;
- pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+ pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
string inputFile = gEnv->getRes() + GetParam();
@@ -159,25 +156,21 @@
SNDFILE *outFileHandle = openOutputFile(&sfInfo);
ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
- int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
+ int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf.get(), outFileHandle);
ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
sf_close(outFileHandle);
- if (decoderBuf) {
- free(decoderBuf);
- decoderBuf = nullptr;
- }
}
TEST_P(AmrwbDecoderTest, ResetDecoderTest) {
uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
- void *decoderBuf = malloc(memRequirements);
+ std::unique_ptr<char[]> decoderBuf(new char[memRequirements]);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
void *amrHandle = nullptr;
int16_t *decoderCookie;
- pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+ pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
string inputFile = gEnv->getRes() + GetParam();
@@ -190,20 +183,18 @@
ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
// Decode 150 frames first
- int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle, kNumFrameReset);
+ int32_t decoderErr =
+ DecodeFrames(decoderCookie, decoderBuf.get(), outFileHandle, kNumFrameReset);
ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
// Reset Decoder
- pvDecoder_AmrWb_Reset(decoderBuf, 1);
+ pvDecoder_AmrWb_Reset(decoderBuf.get(), 1);
// Start decoding again
- decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
+ decoderErr = DecodeFrames(decoderCookie, decoderBuf.get(), outFileHandle);
ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
sf_close(outFileHandle);
- if (decoderBuf) {
- free(decoderBuf);
- }
}
INSTANTIATE_TEST_SUITE_P(AmrwbDecoderTestAll, AmrwbDecoderTest,
diff --git a/media/codecs/amrwb/dec/test/Android.bp b/media/module/codecs/amrwb/dec/test/Android.bp
similarity index 90%
rename from media/codecs/amrwb/dec/test/Android.bp
rename to media/module/codecs/amrwb/dec/test/Android.bp
index 7d0c964..7ea39ef 100644
--- a/media/codecs/amrwb/dec/test/Android.bp
+++ b/media/module/codecs/amrwb/dec/test/Android.bp
@@ -57,4 +57,7 @@
"signed-integer-overflow",
],
},
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.zip?unzip=true",
+ ],
}
diff --git a/media/codecs/amrwb/dec/test/AndroidTest.xml b/media/module/codecs/amrwb/dec/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/amrwb/dec/test/AndroidTest.xml
rename to media/module/codecs/amrwb/dec/test/AndroidTest.xml
diff --git a/media/codecs/amrwb/dec/test/README.md b/media/module/codecs/amrwb/dec/test/README.md
similarity index 100%
rename from media/codecs/amrwb/dec/test/README.md
rename to media/module/codecs/amrwb/dec/test/README.md
diff --git a/media/codecs/amrwb/dec/test/amrwbdec_test.cpp b/media/module/codecs/amrwb/dec/test/amrwbdec_test.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/test/amrwbdec_test.cpp
rename to media/module/codecs/amrwb/dec/test/amrwbdec_test.cpp
diff --git a/media/codecs/amrwb/enc/Android.bp b/media/module/codecs/amrwb/enc/Android.bp
similarity index 100%
rename from media/codecs/amrwb/enc/Android.bp
rename to media/module/codecs/amrwb/enc/Android.bp
diff --git a/media/codecs/amrwb/enc/MODULE_LICENSE_APACHE2 b/media/module/codecs/amrwb/enc/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/amrwb/enc/MODULE_LICENSE_APACHE2
rename to media/module/codecs/amrwb/enc/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/amrwb/enc/NOTICE b/media/module/codecs/amrwb/enc/NOTICE
similarity index 100%
rename from media/codecs/amrwb/enc/NOTICE
rename to media/module/codecs/amrwb/enc/NOTICE
diff --git a/media/codecs/amrwb/enc/SampleCode/AMRWB_E_SAMPLE.c b/media/module/codecs/amrwb/enc/SampleCode/AMRWB_E_SAMPLE.c
similarity index 100%
rename from media/codecs/amrwb/enc/SampleCode/AMRWB_E_SAMPLE.c
rename to media/module/codecs/amrwb/enc/SampleCode/AMRWB_E_SAMPLE.c
diff --git a/media/codecs/amrwb/enc/SampleCode/Android.bp b/media/module/codecs/amrwb/enc/SampleCode/Android.bp
similarity index 100%
rename from media/codecs/amrwb/enc/SampleCode/Android.bp
rename to media/module/codecs/amrwb/enc/SampleCode/Android.bp
diff --git a/media/codecs/amrwb/enc/SampleCode/MODULE_LICENSE_APACHE2 b/media/module/codecs/amrwb/enc/SampleCode/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/amrwb/enc/SampleCode/MODULE_LICENSE_APACHE2
rename to media/module/codecs/amrwb/enc/SampleCode/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/amrwb/enc/SampleCode/NOTICE b/media/module/codecs/amrwb/enc/SampleCode/NOTICE
similarity index 100%
rename from media/codecs/amrwb/enc/SampleCode/NOTICE
rename to media/module/codecs/amrwb/enc/SampleCode/NOTICE
diff --git a/media/codecs/amrwb/enc/TEST_MAPPING b/media/module/codecs/amrwb/enc/TEST_MAPPING
similarity index 100%
rename from media/codecs/amrwb/enc/TEST_MAPPING
rename to media/module/codecs/amrwb/enc/TEST_MAPPING
diff --git a/media/codecs/amrwb/enc/doc/voAMRWBEncoderSDK.pdf b/media/module/codecs/amrwb/enc/doc/voAMRWBEncoderSDK.pdf
similarity index 100%
rename from media/codecs/amrwb/enc/doc/voAMRWBEncoderSDK.pdf
rename to media/module/codecs/amrwb/enc/doc/voAMRWBEncoderSDK.pdf
Binary files differ
diff --git a/media/codecs/amrwb/enc/fuzzer/Android.bp b/media/module/codecs/amrwb/enc/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/amrwb/enc/fuzzer/Android.bp
rename to media/module/codecs/amrwb/enc/fuzzer/Android.bp
diff --git a/media/codecs/amrwb/enc/fuzzer/README.md b/media/module/codecs/amrwb/enc/fuzzer/README.md
similarity index 100%
rename from media/codecs/amrwb/enc/fuzzer/README.md
rename to media/module/codecs/amrwb/enc/fuzzer/README.md
diff --git a/media/codecs/amrwb/enc/fuzzer/amrwb_enc_fuzzer.cpp b/media/module/codecs/amrwb/enc/fuzzer/amrwb_enc_fuzzer.cpp
similarity index 100%
rename from media/codecs/amrwb/enc/fuzzer/amrwb_enc_fuzzer.cpp
rename to media/module/codecs/amrwb/enc/fuzzer/amrwb_enc_fuzzer.cpp
diff --git a/media/codecs/amrwb/enc/inc/acelp.h b/media/module/codecs/amrwb/enc/inc/acelp.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/acelp.h
rename to media/module/codecs/amrwb/enc/inc/acelp.h
diff --git a/media/codecs/amrwb/enc/inc/basic_op.h b/media/module/codecs/amrwb/enc/inc/basic_op.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/basic_op.h
rename to media/module/codecs/amrwb/enc/inc/basic_op.h
diff --git a/media/codecs/amrwb/enc/inc/bits.h b/media/module/codecs/amrwb/enc/inc/bits.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/bits.h
rename to media/module/codecs/amrwb/enc/inc/bits.h
diff --git a/media/codecs/amrwb/enc/inc/cnst.h b/media/module/codecs/amrwb/enc/inc/cnst.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/cnst.h
rename to media/module/codecs/amrwb/enc/inc/cnst.h
diff --git a/media/codecs/amrwb/enc/inc/cod_main.h b/media/module/codecs/amrwb/enc/inc/cod_main.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/cod_main.h
rename to media/module/codecs/amrwb/enc/inc/cod_main.h
diff --git a/media/codecs/amrwb/enc/inc/dtx.h b/media/module/codecs/amrwb/enc/inc/dtx.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/dtx.h
rename to media/module/codecs/amrwb/enc/inc/dtx.h
diff --git a/media/codecs/amrwb/enc/inc/grid100.tab b/media/module/codecs/amrwb/enc/inc/grid100.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/grid100.tab
rename to media/module/codecs/amrwb/enc/inc/grid100.tab
diff --git a/media/codecs/amrwb/enc/inc/ham_wind.tab b/media/module/codecs/amrwb/enc/inc/ham_wind.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/ham_wind.tab
rename to media/module/codecs/amrwb/enc/inc/ham_wind.tab
diff --git a/media/codecs/amrwb/enc/inc/homing.tab b/media/module/codecs/amrwb/enc/inc/homing.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/homing.tab
rename to media/module/codecs/amrwb/enc/inc/homing.tab
diff --git a/media/codecs/amrwb/enc/inc/isp_isf.tab b/media/module/codecs/amrwb/enc/inc/isp_isf.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/isp_isf.tab
rename to media/module/codecs/amrwb/enc/inc/isp_isf.tab
diff --git a/media/codecs/amrwb/enc/inc/lag_wind.tab b/media/module/codecs/amrwb/enc/inc/lag_wind.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/lag_wind.tab
rename to media/module/codecs/amrwb/enc/inc/lag_wind.tab
diff --git a/media/codecs/amrwb/enc/inc/log2.h b/media/module/codecs/amrwb/enc/inc/log2.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/log2.h
rename to media/module/codecs/amrwb/enc/inc/log2.h
diff --git a/media/codecs/amrwb/enc/inc/log2_tab.h b/media/module/codecs/amrwb/enc/inc/log2_tab.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/log2_tab.h
rename to media/module/codecs/amrwb/enc/inc/log2_tab.h
diff --git a/media/codecs/amrwb/enc/inc/main.h b/media/module/codecs/amrwb/enc/inc/main.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/main.h
rename to media/module/codecs/amrwb/enc/inc/main.h
diff --git a/media/codecs/amrwb/enc/inc/math_op.h b/media/module/codecs/amrwb/enc/inc/math_op.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/math_op.h
rename to media/module/codecs/amrwb/enc/inc/math_op.h
diff --git a/media/codecs/amrwb/enc/inc/mem_align.h b/media/module/codecs/amrwb/enc/inc/mem_align.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/mem_align.h
rename to media/module/codecs/amrwb/enc/inc/mem_align.h
diff --git a/media/codecs/amrwb/enc/inc/mime_io.tab b/media/module/codecs/amrwb/enc/inc/mime_io.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/mime_io.tab
rename to media/module/codecs/amrwb/enc/inc/mime_io.tab
diff --git a/media/codecs/amrwb/enc/inc/oper_32b.h b/media/module/codecs/amrwb/enc/inc/oper_32b.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/oper_32b.h
rename to media/module/codecs/amrwb/enc/inc/oper_32b.h
diff --git a/media/codecs/amrwb/enc/inc/p_med_o.h b/media/module/codecs/amrwb/enc/inc/p_med_o.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/p_med_o.h
rename to media/module/codecs/amrwb/enc/inc/p_med_o.h
diff --git a/media/codecs/amrwb/enc/inc/p_med_ol.tab b/media/module/codecs/amrwb/enc/inc/p_med_ol.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/p_med_ol.tab
rename to media/module/codecs/amrwb/enc/inc/p_med_ol.tab
diff --git a/media/codecs/amrwb/enc/inc/q_gain2.tab b/media/module/codecs/amrwb/enc/inc/q_gain2.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/q_gain2.tab
rename to media/module/codecs/amrwb/enc/inc/q_gain2.tab
diff --git a/media/codecs/amrwb/enc/inc/q_pulse.h b/media/module/codecs/amrwb/enc/inc/q_pulse.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/q_pulse.h
rename to media/module/codecs/amrwb/enc/inc/q_pulse.h
diff --git a/media/codecs/amrwb/enc/inc/qisf_ns.tab b/media/module/codecs/amrwb/enc/inc/qisf_ns.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/qisf_ns.tab
rename to media/module/codecs/amrwb/enc/inc/qisf_ns.tab
diff --git a/media/codecs/amrwb/enc/inc/qpisf_2s.tab b/media/module/codecs/amrwb/enc/inc/qpisf_2s.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/qpisf_2s.tab
rename to media/module/codecs/amrwb/enc/inc/qpisf_2s.tab
diff --git a/media/codecs/amrwb/enc/inc/stream.h b/media/module/codecs/amrwb/enc/inc/stream.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/stream.h
rename to media/module/codecs/amrwb/enc/inc/stream.h
diff --git a/media/codecs/amrwb/enc/inc/typedef.h b/media/module/codecs/amrwb/enc/inc/typedef.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/typedef.h
rename to media/module/codecs/amrwb/enc/inc/typedef.h
diff --git a/media/codecs/amrwb/enc/inc/typedefs.h b/media/module/codecs/amrwb/enc/inc/typedefs.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/typedefs.h
rename to media/module/codecs/amrwb/enc/inc/typedefs.h
diff --git a/media/codecs/amrwb/enc/inc/wb_vad.h b/media/module/codecs/amrwb/enc/inc/wb_vad.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/wb_vad.h
rename to media/module/codecs/amrwb/enc/inc/wb_vad.h
diff --git a/media/codecs/amrwb/enc/inc/wb_vad_c.h b/media/module/codecs/amrwb/enc/inc/wb_vad_c.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/wb_vad_c.h
rename to media/module/codecs/amrwb/enc/inc/wb_vad_c.h
diff --git a/media/codecs/amrwb/enc/patent_disclaimer.txt b/media/module/codecs/amrwb/enc/patent_disclaimer.txt
similarity index 100%
rename from media/codecs/amrwb/enc/patent_disclaimer.txt
rename to media/module/codecs/amrwb/enc/patent_disclaimer.txt
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/Deemph_32_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/Deemph_32_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/Deemph_32_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/Deemph_32_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/Dot_p_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/Dot_p_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/Dot_p_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/Dot_p_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/Filt_6k_7k_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/Filt_6k_7k_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/Filt_6k_7k_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/Filt_6k_7k_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/Norm_Corr_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/Norm_Corr_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/Norm_Corr_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/Norm_Corr_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/Syn_filt_32_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/Syn_filt_32_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/Syn_filt_32_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/Syn_filt_32_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/convolve_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/convolve_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/convolve_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/convolve_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/cor_h_vec_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/cor_h_vec_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/cor_h_vec_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/cor_h_vec_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/pred_lt4_1_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/pred_lt4_1_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/pred_lt4_1_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/pred_lt4_1_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/residu_asm_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/residu_asm_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/residu_asm_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/residu_asm_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/scale_sig_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/scale_sig_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/scale_sig_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/scale_sig_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/syn_filt_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/syn_filt_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/syn_filt_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/syn_filt_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/Deemph_32_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/Deemph_32_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/Deemph_32_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/Deemph_32_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/Dot_p_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/Dot_p_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/Dot_p_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/Dot_p_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/Filt_6k_7k_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/Filt_6k_7k_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/Filt_6k_7k_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/Filt_6k_7k_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/Norm_Corr_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/Norm_Corr_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/Norm_Corr_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/Norm_Corr_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/Syn_filt_32_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/Syn_filt_32_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/Syn_filt_32_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/Syn_filt_32_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/convolve_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/convolve_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/convolve_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/convolve_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/cor_h_vec_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/cor_h_vec_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/cor_h_vec_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/cor_h_vec_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/pred_lt4_1_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/pred_lt4_1_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/pred_lt4_1_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/pred_lt4_1_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/residu_asm_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/residu_asm_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/residu_asm_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/residu_asm_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/scale_sig_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/scale_sig_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/scale_sig_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/scale_sig_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/syn_filt_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/syn_filt_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/syn_filt_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/syn_filt_neon.s
diff --git a/media/codecs/amrwb/enc/src/autocorr.c b/media/module/codecs/amrwb/enc/src/autocorr.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/autocorr.c
rename to media/module/codecs/amrwb/enc/src/autocorr.c
diff --git a/media/codecs/amrwb/enc/src/az_isp.c b/media/module/codecs/amrwb/enc/src/az_isp.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/az_isp.c
rename to media/module/codecs/amrwb/enc/src/az_isp.c
diff --git a/media/codecs/amrwb/enc/src/bits.c b/media/module/codecs/amrwb/enc/src/bits.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/bits.c
rename to media/module/codecs/amrwb/enc/src/bits.c
diff --git a/media/codecs/amrwb/enc/src/c2t64fx.c b/media/module/codecs/amrwb/enc/src/c2t64fx.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/c2t64fx.c
rename to media/module/codecs/amrwb/enc/src/c2t64fx.c
diff --git a/media/codecs/amrwb/enc/src/c4t64fx.c b/media/module/codecs/amrwb/enc/src/c4t64fx.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/c4t64fx.c
rename to media/module/codecs/amrwb/enc/src/c4t64fx.c
diff --git a/media/codecs/amrwb/enc/src/convolve.c b/media/module/codecs/amrwb/enc/src/convolve.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/convolve.c
rename to media/module/codecs/amrwb/enc/src/convolve.c
diff --git a/media/codecs/amrwb/enc/src/cor_h_x.c b/media/module/codecs/amrwb/enc/src/cor_h_x.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/cor_h_x.c
rename to media/module/codecs/amrwb/enc/src/cor_h_x.c
diff --git a/media/codecs/amrwb/enc/src/decim54.c b/media/module/codecs/amrwb/enc/src/decim54.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/decim54.c
rename to media/module/codecs/amrwb/enc/src/decim54.c
diff --git a/media/codecs/amrwb/enc/src/deemph.c b/media/module/codecs/amrwb/enc/src/deemph.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/deemph.c
rename to media/module/codecs/amrwb/enc/src/deemph.c
diff --git a/media/codecs/amrwb/enc/src/dtx.c b/media/module/codecs/amrwb/enc/src/dtx.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/dtx.c
rename to media/module/codecs/amrwb/enc/src/dtx.c
diff --git a/media/codecs/amrwb/enc/src/g_pitch.c b/media/module/codecs/amrwb/enc/src/g_pitch.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/g_pitch.c
rename to media/module/codecs/amrwb/enc/src/g_pitch.c
diff --git a/media/codecs/amrwb/enc/src/gpclip.c b/media/module/codecs/amrwb/enc/src/gpclip.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/gpclip.c
rename to media/module/codecs/amrwb/enc/src/gpclip.c
diff --git a/media/codecs/amrwb/enc/src/homing.c b/media/module/codecs/amrwb/enc/src/homing.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/homing.c
rename to media/module/codecs/amrwb/enc/src/homing.c
diff --git a/media/codecs/amrwb/enc/src/hp400.c b/media/module/codecs/amrwb/enc/src/hp400.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/hp400.c
rename to media/module/codecs/amrwb/enc/src/hp400.c
diff --git a/media/codecs/amrwb/enc/src/hp50.c b/media/module/codecs/amrwb/enc/src/hp50.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/hp50.c
rename to media/module/codecs/amrwb/enc/src/hp50.c
diff --git a/media/codecs/amrwb/enc/src/hp6k.c b/media/module/codecs/amrwb/enc/src/hp6k.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/hp6k.c
rename to media/module/codecs/amrwb/enc/src/hp6k.c
diff --git a/media/codecs/amrwb/enc/src/hp_wsp.c b/media/module/codecs/amrwb/enc/src/hp_wsp.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/hp_wsp.c
rename to media/module/codecs/amrwb/enc/src/hp_wsp.c
diff --git a/media/codecs/amrwb/enc/src/int_lpc.c b/media/module/codecs/amrwb/enc/src/int_lpc.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/int_lpc.c
rename to media/module/codecs/amrwb/enc/src/int_lpc.c
diff --git a/media/codecs/amrwb/enc/src/isp_az.c b/media/module/codecs/amrwb/enc/src/isp_az.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/isp_az.c
rename to media/module/codecs/amrwb/enc/src/isp_az.c
diff --git a/media/codecs/amrwb/enc/src/isp_isf.c b/media/module/codecs/amrwb/enc/src/isp_isf.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/isp_isf.c
rename to media/module/codecs/amrwb/enc/src/isp_isf.c
diff --git a/media/codecs/amrwb/enc/src/lag_wind.c b/media/module/codecs/amrwb/enc/src/lag_wind.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/lag_wind.c
rename to media/module/codecs/amrwb/enc/src/lag_wind.c
diff --git a/media/codecs/amrwb/enc/src/levinson.c b/media/module/codecs/amrwb/enc/src/levinson.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/levinson.c
rename to media/module/codecs/amrwb/enc/src/levinson.c
diff --git a/media/codecs/amrwb/enc/src/log2.c b/media/module/codecs/amrwb/enc/src/log2.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/log2.c
rename to media/module/codecs/amrwb/enc/src/log2.c
diff --git a/media/codecs/amrwb/enc/src/lp_dec2.c b/media/module/codecs/amrwb/enc/src/lp_dec2.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/lp_dec2.c
rename to media/module/codecs/amrwb/enc/src/lp_dec2.c
diff --git a/media/codecs/amrwb/enc/src/math_op.c b/media/module/codecs/amrwb/enc/src/math_op.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/math_op.c
rename to media/module/codecs/amrwb/enc/src/math_op.c
diff --git a/media/codecs/amrwb/enc/src/mem_align.c b/media/module/codecs/amrwb/enc/src/mem_align.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/mem_align.c
rename to media/module/codecs/amrwb/enc/src/mem_align.c
diff --git a/media/codecs/amrwb/enc/src/oper_32b.c b/media/module/codecs/amrwb/enc/src/oper_32b.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/oper_32b.c
rename to media/module/codecs/amrwb/enc/src/oper_32b.c
diff --git a/media/codecs/amrwb/enc/src/p_med_ol.c b/media/module/codecs/amrwb/enc/src/p_med_ol.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/p_med_ol.c
rename to media/module/codecs/amrwb/enc/src/p_med_ol.c
diff --git a/media/codecs/amrwb/enc/src/pit_shrp.c b/media/module/codecs/amrwb/enc/src/pit_shrp.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/pit_shrp.c
rename to media/module/codecs/amrwb/enc/src/pit_shrp.c
diff --git a/media/codecs/amrwb/enc/src/pitch_f4.c b/media/module/codecs/amrwb/enc/src/pitch_f4.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/pitch_f4.c
rename to media/module/codecs/amrwb/enc/src/pitch_f4.c
diff --git a/media/codecs/amrwb/enc/src/pred_lt4.c b/media/module/codecs/amrwb/enc/src/pred_lt4.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/pred_lt4.c
rename to media/module/codecs/amrwb/enc/src/pred_lt4.c
diff --git a/media/codecs/amrwb/enc/src/preemph.c b/media/module/codecs/amrwb/enc/src/preemph.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/preemph.c
rename to media/module/codecs/amrwb/enc/src/preemph.c
diff --git a/media/codecs/amrwb/enc/src/q_gain2.c b/media/module/codecs/amrwb/enc/src/q_gain2.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/q_gain2.c
rename to media/module/codecs/amrwb/enc/src/q_gain2.c
diff --git a/media/codecs/amrwb/enc/src/q_pulse.c b/media/module/codecs/amrwb/enc/src/q_pulse.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/q_pulse.c
rename to media/module/codecs/amrwb/enc/src/q_pulse.c
diff --git a/media/codecs/amrwb/enc/src/qisf_ns.c b/media/module/codecs/amrwb/enc/src/qisf_ns.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/qisf_ns.c
rename to media/module/codecs/amrwb/enc/src/qisf_ns.c
diff --git a/media/codecs/amrwb/enc/src/qpisf_2s.c b/media/module/codecs/amrwb/enc/src/qpisf_2s.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/qpisf_2s.c
rename to media/module/codecs/amrwb/enc/src/qpisf_2s.c
diff --git a/media/codecs/amrwb/enc/src/random.c b/media/module/codecs/amrwb/enc/src/random.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/random.c
rename to media/module/codecs/amrwb/enc/src/random.c
diff --git a/media/codecs/amrwb/enc/src/residu.c b/media/module/codecs/amrwb/enc/src/residu.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/residu.c
rename to media/module/codecs/amrwb/enc/src/residu.c
diff --git a/media/codecs/amrwb/enc/src/scale.c b/media/module/codecs/amrwb/enc/src/scale.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/scale.c
rename to media/module/codecs/amrwb/enc/src/scale.c
diff --git a/media/codecs/amrwb/enc/src/stream.c b/media/module/codecs/amrwb/enc/src/stream.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/stream.c
rename to media/module/codecs/amrwb/enc/src/stream.c
diff --git a/media/codecs/amrwb/enc/src/syn_filt.c b/media/module/codecs/amrwb/enc/src/syn_filt.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/syn_filt.c
rename to media/module/codecs/amrwb/enc/src/syn_filt.c
diff --git a/media/codecs/amrwb/enc/src/updt_tar.c b/media/module/codecs/amrwb/enc/src/updt_tar.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/updt_tar.c
rename to media/module/codecs/amrwb/enc/src/updt_tar.c
diff --git a/media/codecs/amrwb/enc/src/util.c b/media/module/codecs/amrwb/enc/src/util.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/util.c
rename to media/module/codecs/amrwb/enc/src/util.c
diff --git a/media/codecs/amrwb/enc/src/voAMRWBEnc.c b/media/module/codecs/amrwb/enc/src/voAMRWBEnc.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/voAMRWBEnc.c
rename to media/module/codecs/amrwb/enc/src/voAMRWBEnc.c
diff --git a/media/codecs/amrwb/enc/src/voicefac.c b/media/module/codecs/amrwb/enc/src/voicefac.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/voicefac.c
rename to media/module/codecs/amrwb/enc/src/voicefac.c
diff --git a/media/codecs/amrwb/enc/src/wb_vad.c b/media/module/codecs/amrwb/enc/src/wb_vad.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/wb_vad.c
rename to media/module/codecs/amrwb/enc/src/wb_vad.c
diff --git a/media/codecs/amrwb/enc/src/weight_a.c b/media/module/codecs/amrwb/enc/src/weight_a.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/weight_a.c
rename to media/module/codecs/amrwb/enc/src/weight_a.c
diff --git a/media/codecs/amrwb/enc/test/AmrwbEncTestEnvironment.h b/media/module/codecs/amrwb/enc/test/AmrwbEncTestEnvironment.h
similarity index 100%
rename from media/codecs/amrwb/enc/test/AmrwbEncTestEnvironment.h
rename to media/module/codecs/amrwb/enc/test/AmrwbEncTestEnvironment.h
diff --git a/media/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp b/media/module/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp
similarity index 100%
rename from media/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp
rename to media/module/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp
diff --git a/media/codecs/amrwb/enc/test/Android.bp b/media/module/codecs/amrwb/enc/test/Android.bp
similarity index 90%
rename from media/codecs/amrwb/enc/test/Android.bp
rename to media/module/codecs/amrwb/enc/test/Android.bp
index 942f6c9..f095d62 100644
--- a/media/codecs/amrwb/enc/test/Android.bp
+++ b/media/module/codecs/amrwb/enc/test/Android.bp
@@ -57,4 +57,7 @@
"signed-integer-overflow",
],
},
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.zip?unzip=true",
+ ],
}
diff --git a/media/codecs/amrwb/enc/test/AndroidTest.xml b/media/module/codecs/amrwb/enc/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/amrwb/enc/test/AndroidTest.xml
rename to media/module/codecs/amrwb/enc/test/AndroidTest.xml
diff --git a/media/codecs/amrwb/enc/test/README.md b/media/module/codecs/amrwb/enc/test/README.md
similarity index 100%
rename from media/codecs/amrwb/enc/test/README.md
rename to media/module/codecs/amrwb/enc/test/README.md
diff --git a/media/libstagefright/codecs/common/Android.bp b/media/module/codecs/common/Android.bp
similarity index 100%
rename from media/libstagefright/codecs/common/Android.bp
rename to media/module/codecs/common/Android.bp
diff --git a/media/libstagefright/codecs/common/MODULE_LICENSE_APACHE2 b/media/module/codecs/common/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/codecs/common/MODULE_LICENSE_APACHE2
rename to media/module/codecs/common/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/common/NOTICE b/media/module/codecs/common/NOTICE
similarity index 100%
rename from media/libstagefright/codecs/common/NOTICE
rename to media/module/codecs/common/NOTICE
diff --git a/media/libstagefright/codecs/common/cmnMemory.c b/media/module/codecs/common/cmnMemory.c
similarity index 100%
rename from media/libstagefright/codecs/common/cmnMemory.c
rename to media/module/codecs/common/cmnMemory.c
diff --git a/media/libstagefright/codecs/common/include/cmnMemory.h b/media/module/codecs/common/include/cmnMemory.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/cmnMemory.h
rename to media/module/codecs/common/include/cmnMemory.h
diff --git a/media/libstagefright/codecs/common/include/voAAC.h b/media/module/codecs/common/include/voAAC.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/voAAC.h
rename to media/module/codecs/common/include/voAAC.h
diff --git a/media/libstagefright/codecs/common/include/voAMRWB.h b/media/module/codecs/common/include/voAMRWB.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/voAMRWB.h
rename to media/module/codecs/common/include/voAMRWB.h
diff --git a/media/libstagefright/codecs/common/include/voAudio.h b/media/module/codecs/common/include/voAudio.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/voAudio.h
rename to media/module/codecs/common/include/voAudio.h
diff --git a/media/libstagefright/codecs/common/include/voIndex.h b/media/module/codecs/common/include/voIndex.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/voIndex.h
rename to media/module/codecs/common/include/voIndex.h
diff --git a/media/libstagefright/codecs/common/include/voMem.h b/media/module/codecs/common/include/voMem.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/voMem.h
rename to media/module/codecs/common/include/voMem.h
diff --git a/media/libstagefright/codecs/common/include/voType.h b/media/module/codecs/common/include/voType.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/voType.h
rename to media/module/codecs/common/include/voType.h
diff --git a/media/libstagefright/flac/dec/Android.bp b/media/module/codecs/flac/dec/Android.bp
similarity index 100%
rename from media/libstagefright/flac/dec/Android.bp
rename to media/module/codecs/flac/dec/Android.bp
diff --git a/media/libstagefright/flac/dec/FLACDecoder.cpp b/media/module/codecs/flac/dec/FLACDecoder.cpp
similarity index 100%
rename from media/libstagefright/flac/dec/FLACDecoder.cpp
rename to media/module/codecs/flac/dec/FLACDecoder.cpp
diff --git a/media/libstagefright/flac/dec/FLACDecoder.h b/media/module/codecs/flac/dec/FLACDecoder.h
similarity index 100%
rename from media/libstagefright/flac/dec/FLACDecoder.h
rename to media/module/codecs/flac/dec/FLACDecoder.h
diff --git a/media/libstagefright/flac/dec/MODULE_LICENSE_APACHE2 b/media/module/codecs/flac/dec/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/flac/dec/MODULE_LICENSE_APACHE2
rename to media/module/codecs/flac/dec/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/flac/dec/NOTICE b/media/module/codecs/flac/dec/NOTICE
similarity index 100%
rename from media/libstagefright/flac/dec/NOTICE
rename to media/module/codecs/flac/dec/NOTICE
diff --git a/media/libstagefright/flac/dec/test/Android.bp b/media/module/codecs/flac/dec/test/Android.bp
similarity index 100%
rename from media/libstagefright/flac/dec/test/Android.bp
rename to media/module/codecs/flac/dec/test/Android.bp
diff --git a/media/libstagefright/flac/dec/test/AndroidTest.xml b/media/module/codecs/flac/dec/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/flac/dec/test/AndroidTest.xml
rename to media/module/codecs/flac/dec/test/AndroidTest.xml
diff --git a/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp b/media/module/codecs/flac/dec/test/FlacDecoderTest.cpp
similarity index 100%
rename from media/libstagefright/flac/dec/test/FlacDecoderTest.cpp
rename to media/module/codecs/flac/dec/test/FlacDecoderTest.cpp
diff --git a/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h b/media/module/codecs/flac/dec/test/FlacDecoderTestEnvironment.h
similarity index 100%
rename from media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h
rename to media/module/codecs/flac/dec/test/FlacDecoderTestEnvironment.h
diff --git a/media/libstagefright/flac/dec/test/README.md b/media/module/codecs/flac/dec/test/README.md
similarity index 100%
rename from media/libstagefright/flac/dec/test/README.md
rename to media/module/codecs/flac/dec/test/README.md
diff --git a/media/codecs/g711/decoder/Android.bp b/media/module/codecs/g711/decoder/Android.bp
similarity index 100%
rename from media/codecs/g711/decoder/Android.bp
rename to media/module/codecs/g711/decoder/Android.bp
diff --git a/media/codecs/g711/decoder/g711Dec.h b/media/module/codecs/g711/decoder/g711Dec.h
similarity index 100%
rename from media/codecs/g711/decoder/g711Dec.h
rename to media/module/codecs/g711/decoder/g711Dec.h
diff --git a/media/codecs/g711/decoder/g711DecAlaw.cpp b/media/module/codecs/g711/decoder/g711DecAlaw.cpp
similarity index 100%
rename from media/codecs/g711/decoder/g711DecAlaw.cpp
rename to media/module/codecs/g711/decoder/g711DecAlaw.cpp
diff --git a/media/codecs/g711/decoder/g711DecMlaw.cpp b/media/module/codecs/g711/decoder/g711DecMlaw.cpp
similarity index 100%
rename from media/codecs/g711/decoder/g711DecMlaw.cpp
rename to media/module/codecs/g711/decoder/g711DecMlaw.cpp
diff --git a/media/codecs/g711/fuzzer/Android.bp b/media/module/codecs/g711/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/g711/fuzzer/Android.bp
rename to media/module/codecs/g711/fuzzer/Android.bp
diff --git a/media/codecs/g711/fuzzer/README.md b/media/module/codecs/g711/fuzzer/README.md
similarity index 100%
rename from media/codecs/g711/fuzzer/README.md
rename to media/module/codecs/g711/fuzzer/README.md
diff --git a/media/codecs/g711/fuzzer/g711_dec_fuzzer.cpp b/media/module/codecs/g711/fuzzer/g711_dec_fuzzer.cpp
similarity index 100%
rename from media/codecs/g711/fuzzer/g711_dec_fuzzer.cpp
rename to media/module/codecs/g711/fuzzer/g711_dec_fuzzer.cpp
diff --git a/media/codecs/m4v_h263/TEST_MAPPING b/media/module/codecs/m4v_h263/TEST_MAPPING
similarity index 100%
rename from media/codecs/m4v_h263/TEST_MAPPING
rename to media/module/codecs/m4v_h263/TEST_MAPPING
diff --git a/media/codecs/m4v_h263/dec/Android.bp b/media/module/codecs/m4v_h263/dec/Android.bp
similarity index 100%
rename from media/codecs/m4v_h263/dec/Android.bp
rename to media/module/codecs/m4v_h263/dec/Android.bp
diff --git a/media/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2 b/media/module/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2
rename to media/module/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/m4v_h263/dec/NOTICE b/media/module/codecs/m4v_h263/dec/NOTICE
similarity index 100%
rename from media/codecs/m4v_h263/dec/NOTICE
rename to media/module/codecs/m4v_h263/dec/NOTICE
diff --git a/media/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h b/media/module/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h
rename to media/module/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h
diff --git a/media/codecs/m4v_h263/dec/include/mp4dec_api.h b/media/module/codecs/m4v_h263/dec/include/mp4dec_api.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/include/mp4dec_api.h
rename to media/module/codecs/m4v_h263/dec/include/mp4dec_api.h
diff --git a/media/codecs/m4v_h263/dec/include/visual_header.h b/media/module/codecs/m4v_h263/dec/include/visual_header.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/include/visual_header.h
rename to media/module/codecs/m4v_h263/dec/include/visual_header.h
diff --git a/media/codecs/m4v_h263/dec/src/bitstream.cpp b/media/module/codecs/m4v_h263/dec/src/bitstream.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/bitstream.cpp
rename to media/module/codecs/m4v_h263/dec/src/bitstream.cpp
diff --git a/media/codecs/m4v_h263/dec/src/bitstream.h b/media/module/codecs/m4v_h263/dec/src/bitstream.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/bitstream.h
rename to media/module/codecs/m4v_h263/dec/src/bitstream.h
diff --git a/media/codecs/m4v_h263/dec/src/block_idct.cpp b/media/module/codecs/m4v_h263/dec/src/block_idct.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/block_idct.cpp
rename to media/module/codecs/m4v_h263/dec/src/block_idct.cpp
diff --git a/media/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp b/media/module/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp
rename to media/module/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp
diff --git a/media/codecs/m4v_h263/dec/src/combined_decode.cpp b/media/module/codecs/m4v_h263/dec/src/combined_decode.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/combined_decode.cpp
rename to media/module/codecs/m4v_h263/dec/src/combined_decode.cpp
diff --git a/media/codecs/m4v_h263/dec/src/conceal.cpp b/media/module/codecs/m4v_h263/dec/src/conceal.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/conceal.cpp
rename to media/module/codecs/m4v_h263/dec/src/conceal.cpp
diff --git a/media/codecs/m4v_h263/dec/src/datapart_decode.cpp b/media/module/codecs/m4v_h263/dec/src/datapart_decode.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/datapart_decode.cpp
rename to media/module/codecs/m4v_h263/dec/src/datapart_decode.cpp
diff --git a/media/codecs/m4v_h263/dec/src/dcac_prediction.cpp b/media/module/codecs/m4v_h263/dec/src/dcac_prediction.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/dcac_prediction.cpp
rename to media/module/codecs/m4v_h263/dec/src/dcac_prediction.cpp
diff --git a/media/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp b/media/module/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp
rename to media/module/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp
diff --git a/media/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp b/media/module/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp
rename to media/module/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp
diff --git a/media/codecs/m4v_h263/dec/src/get_pred_outside.cpp b/media/module/codecs/m4v_h263/dec/src/get_pred_outside.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/get_pred_outside.cpp
rename to media/module/codecs/m4v_h263/dec/src/get_pred_outside.cpp
diff --git a/media/codecs/m4v_h263/dec/src/idct.cpp b/media/module/codecs/m4v_h263/dec/src/idct.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/idct.cpp
rename to media/module/codecs/m4v_h263/dec/src/idct.cpp
diff --git a/media/codecs/m4v_h263/dec/src/idct.h b/media/module/codecs/m4v_h263/dec/src/idct.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/idct.h
rename to media/module/codecs/m4v_h263/dec/src/idct.h
diff --git a/media/codecs/m4v_h263/dec/src/idct_vca.cpp b/media/module/codecs/m4v_h263/dec/src/idct_vca.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/idct_vca.cpp
rename to media/module/codecs/m4v_h263/dec/src/idct_vca.cpp
diff --git a/media/codecs/m4v_h263/dec/src/max_level.h b/media/module/codecs/m4v_h263/dec/src/max_level.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/max_level.h
rename to media/module/codecs/m4v_h263/dec/src/max_level.h
diff --git a/media/codecs/m4v_h263/dec/src/mb_motion_comp.cpp b/media/module/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
rename to media/module/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
diff --git a/media/codecs/m4v_h263/dec/src/mb_utils.cpp b/media/module/codecs/m4v_h263/dec/src/mb_utils.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/mb_utils.cpp
rename to media/module/codecs/m4v_h263/dec/src/mb_utils.cpp
diff --git a/media/codecs/m4v_h263/dec/src/mbtype_mode.h b/media/module/codecs/m4v_h263/dec/src/mbtype_mode.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/mbtype_mode.h
rename to media/module/codecs/m4v_h263/dec/src/mbtype_mode.h
diff --git a/media/codecs/m4v_h263/dec/src/motion_comp.h b/media/module/codecs/m4v_h263/dec/src/motion_comp.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/motion_comp.h
rename to media/module/codecs/m4v_h263/dec/src/motion_comp.h
diff --git a/media/codecs/m4v_h263/dec/src/mp4dec_lib.h b/media/module/codecs/m4v_h263/dec/src/mp4dec_lib.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/mp4dec_lib.h
rename to media/module/codecs/m4v_h263/dec/src/mp4dec_lib.h
diff --git a/media/codecs/m4v_h263/dec/src/mp4def.h b/media/module/codecs/m4v_h263/dec/src/mp4def.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/mp4def.h
rename to media/module/codecs/m4v_h263/dec/src/mp4def.h
diff --git a/media/codecs/m4v_h263/dec/src/mp4lib_int.h b/media/module/codecs/m4v_h263/dec/src/mp4lib_int.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/mp4lib_int.h
rename to media/module/codecs/m4v_h263/dec/src/mp4lib_int.h
diff --git a/media/codecs/m4v_h263/dec/src/packet_util.cpp b/media/module/codecs/m4v_h263/dec/src/packet_util.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/packet_util.cpp
rename to media/module/codecs/m4v_h263/dec/src/packet_util.cpp
diff --git a/media/codecs/m4v_h263/dec/src/post_filter.cpp b/media/module/codecs/m4v_h263/dec/src/post_filter.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/post_filter.cpp
rename to media/module/codecs/m4v_h263/dec/src/post_filter.cpp
diff --git a/media/codecs/m4v_h263/dec/src/post_proc.h b/media/module/codecs/m4v_h263/dec/src/post_proc.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/post_proc.h
rename to media/module/codecs/m4v_h263/dec/src/post_proc.h
diff --git a/media/codecs/m4v_h263/dec/src/pvdec_api.cpp b/media/module/codecs/m4v_h263/dec/src/pvdec_api.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/pvdec_api.cpp
rename to media/module/codecs/m4v_h263/dec/src/pvdec_api.cpp
diff --git a/media/codecs/m4v_h263/dec/src/scaling.h b/media/module/codecs/m4v_h263/dec/src/scaling.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/scaling.h
rename to media/module/codecs/m4v_h263/dec/src/scaling.h
diff --git a/media/codecs/m4v_h263/dec/src/scaling_tab.cpp b/media/module/codecs/m4v_h263/dec/src/scaling_tab.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/scaling_tab.cpp
rename to media/module/codecs/m4v_h263/dec/src/scaling_tab.cpp
diff --git a/media/codecs/m4v_h263/dec/src/vlc_dec_tab.h b/media/module/codecs/m4v_h263/dec/src/vlc_dec_tab.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/vlc_dec_tab.h
rename to media/module/codecs/m4v_h263/dec/src/vlc_dec_tab.h
diff --git a/media/codecs/m4v_h263/dec/src/vlc_decode.cpp b/media/module/codecs/m4v_h263/dec/src/vlc_decode.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/vlc_decode.cpp
rename to media/module/codecs/m4v_h263/dec/src/vlc_decode.cpp
diff --git a/media/codecs/m4v_h263/dec/src/vlc_decode.h b/media/module/codecs/m4v_h263/dec/src/vlc_decode.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/vlc_decode.h
rename to media/module/codecs/m4v_h263/dec/src/vlc_decode.h
diff --git a/media/codecs/m4v_h263/dec/src/vlc_dequant.cpp b/media/module/codecs/m4v_h263/dec/src/vlc_dequant.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/vlc_dequant.cpp
rename to media/module/codecs/m4v_h263/dec/src/vlc_dequant.cpp
diff --git a/media/codecs/m4v_h263/dec/src/vlc_tab.cpp b/media/module/codecs/m4v_h263/dec/src/vlc_tab.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/vlc_tab.cpp
rename to media/module/codecs/m4v_h263/dec/src/vlc_tab.cpp
diff --git a/media/codecs/m4v_h263/dec/src/vop.cpp b/media/module/codecs/m4v_h263/dec/src/vop.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/vop.cpp
rename to media/module/codecs/m4v_h263/dec/src/vop.cpp
diff --git a/media/codecs/m4v_h263/dec/src/zigzag.h b/media/module/codecs/m4v_h263/dec/src/zigzag.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/zigzag.h
rename to media/module/codecs/m4v_h263/dec/src/zigzag.h
diff --git a/media/codecs/m4v_h263/dec/src/zigzag_tab.cpp b/media/module/codecs/m4v_h263/dec/src/zigzag_tab.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/zigzag_tab.cpp
rename to media/module/codecs/m4v_h263/dec/src/zigzag_tab.cpp
diff --git a/media/codecs/m4v_h263/dec/test/Android.bp b/media/module/codecs/m4v_h263/dec/test/Android.bp
similarity index 92%
rename from media/codecs/m4v_h263/dec/test/Android.bp
rename to media/module/codecs/m4v_h263/dec/test/Android.bp
index d8de569..9dc756c 100644
--- a/media/codecs/m4v_h263/dec/test/Android.bp
+++ b/media/module/codecs/m4v_h263/dec/test/Android.bp
@@ -76,4 +76,7 @@
],
cfi: true,
},
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder-1.1.zip?unzip=true",
+ ],
}
diff --git a/media/codecs/m4v_h263/dec/test/AndroidTest.xml b/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/m4v_h263/dec/test/AndroidTest.xml
rename to media/module/codecs/m4v_h263/dec/test/AndroidTest.xml
diff --git a/media/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp b/media/module/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp
rename to media/module/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp
diff --git a/media/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h b/media/module/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h
rename to media/module/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h
diff --git a/media/codecs/m4v_h263/dec/test/README.md b/media/module/codecs/m4v_h263/dec/test/README.md
similarity index 100%
rename from media/codecs/m4v_h263/dec/test/README.md
rename to media/module/codecs/m4v_h263/dec/test/README.md
diff --git a/media/codecs/m4v_h263/enc/Android.bp b/media/module/codecs/m4v_h263/enc/Android.bp
similarity index 100%
rename from media/codecs/m4v_h263/enc/Android.bp
rename to media/module/codecs/m4v_h263/enc/Android.bp
diff --git a/media/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2 b/media/module/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2
rename to media/module/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/m4v_h263/enc/NOTICE b/media/module/codecs/m4v_h263/enc/NOTICE
similarity index 100%
rename from media/codecs/m4v_h263/enc/NOTICE
rename to media/module/codecs/m4v_h263/enc/NOTICE
diff --git a/media/codecs/m4v_h263/enc/include/cvei.h b/media/module/codecs/m4v_h263/enc/include/cvei.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/include/cvei.h
rename to media/module/codecs/m4v_h263/enc/include/cvei.h
diff --git a/media/codecs/m4v_h263/enc/include/mp4enc_api.h b/media/module/codecs/m4v_h263/enc/include/mp4enc_api.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/include/mp4enc_api.h
rename to media/module/codecs/m4v_h263/enc/include/mp4enc_api.h
diff --git a/media/codecs/m4v_h263/enc/src/bitstream_io.cpp b/media/module/codecs/m4v_h263/enc/src/bitstream_io.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/bitstream_io.cpp
rename to media/module/codecs/m4v_h263/enc/src/bitstream_io.cpp
diff --git a/media/codecs/m4v_h263/enc/src/bitstream_io.h b/media/module/codecs/m4v_h263/enc/src/bitstream_io.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/bitstream_io.h
rename to media/module/codecs/m4v_h263/enc/src/bitstream_io.h
diff --git a/media/codecs/m4v_h263/enc/src/combined_encode.cpp b/media/module/codecs/m4v_h263/enc/src/combined_encode.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/combined_encode.cpp
rename to media/module/codecs/m4v_h263/enc/src/combined_encode.cpp
diff --git a/media/codecs/m4v_h263/enc/src/datapart_encode.cpp b/media/module/codecs/m4v_h263/enc/src/datapart_encode.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/datapart_encode.cpp
rename to media/module/codecs/m4v_h263/enc/src/datapart_encode.cpp
diff --git a/media/codecs/m4v_h263/enc/src/dct.cpp b/media/module/codecs/m4v_h263/enc/src/dct.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/dct.cpp
rename to media/module/codecs/m4v_h263/enc/src/dct.cpp
diff --git a/media/codecs/m4v_h263/enc/src/dct.h b/media/module/codecs/m4v_h263/enc/src/dct.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/dct.h
rename to media/module/codecs/m4v_h263/enc/src/dct.h
diff --git a/media/codecs/m4v_h263/enc/src/dct_inline.h b/media/module/codecs/m4v_h263/enc/src/dct_inline.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/dct_inline.h
rename to media/module/codecs/m4v_h263/enc/src/dct_inline.h
diff --git a/media/codecs/m4v_h263/enc/src/fastcodemb.cpp b/media/module/codecs/m4v_h263/enc/src/fastcodemb.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/fastcodemb.cpp
rename to media/module/codecs/m4v_h263/enc/src/fastcodemb.cpp
diff --git a/media/codecs/m4v_h263/enc/src/fastcodemb.h b/media/module/codecs/m4v_h263/enc/src/fastcodemb.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/fastcodemb.h
rename to media/module/codecs/m4v_h263/enc/src/fastcodemb.h
diff --git a/media/codecs/m4v_h263/enc/src/fastidct.cpp b/media/module/codecs/m4v_h263/enc/src/fastidct.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/fastidct.cpp
rename to media/module/codecs/m4v_h263/enc/src/fastidct.cpp
diff --git a/media/codecs/m4v_h263/enc/src/fastquant.cpp b/media/module/codecs/m4v_h263/enc/src/fastquant.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/fastquant.cpp
rename to media/module/codecs/m4v_h263/enc/src/fastquant.cpp
diff --git a/media/codecs/m4v_h263/enc/src/fastquant_inline.h b/media/module/codecs/m4v_h263/enc/src/fastquant_inline.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/fastquant_inline.h
rename to media/module/codecs/m4v_h263/enc/src/fastquant_inline.h
diff --git a/media/codecs/m4v_h263/enc/src/findhalfpel.cpp b/media/module/codecs/m4v_h263/enc/src/findhalfpel.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/findhalfpel.cpp
rename to media/module/codecs/m4v_h263/enc/src/findhalfpel.cpp
diff --git a/media/codecs/m4v_h263/enc/src/m4venc_oscl.h b/media/module/codecs/m4v_h263/enc/src/m4venc_oscl.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/m4venc_oscl.h
rename to media/module/codecs/m4v_h263/enc/src/m4venc_oscl.h
diff --git a/media/codecs/m4v_h263/enc/src/me_utils.cpp b/media/module/codecs/m4v_h263/enc/src/me_utils.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/me_utils.cpp
rename to media/module/codecs/m4v_h263/enc/src/me_utils.cpp
diff --git a/media/codecs/m4v_h263/enc/src/motion_comp.cpp b/media/module/codecs/m4v_h263/enc/src/motion_comp.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/motion_comp.cpp
rename to media/module/codecs/m4v_h263/enc/src/motion_comp.cpp
diff --git a/media/codecs/m4v_h263/enc/src/motion_est.cpp b/media/module/codecs/m4v_h263/enc/src/motion_est.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/motion_est.cpp
rename to media/module/codecs/m4v_h263/enc/src/motion_est.cpp
diff --git a/media/codecs/m4v_h263/enc/src/mp4def.h b/media/module/codecs/m4v_h263/enc/src/mp4def.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/mp4def.h
rename to media/module/codecs/m4v_h263/enc/src/mp4def.h
diff --git a/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/module/codecs/m4v_h263/enc/src/mp4enc_api.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
rename to media/module/codecs/m4v_h263/enc/src/mp4enc_api.cpp
diff --git a/media/codecs/m4v_h263/enc/src/mp4enc_lib.h b/media/module/codecs/m4v_h263/enc/src/mp4enc_lib.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/mp4enc_lib.h
rename to media/module/codecs/m4v_h263/enc/src/mp4enc_lib.h
diff --git a/media/codecs/m4v_h263/enc/src/mp4lib_int.h b/media/module/codecs/m4v_h263/enc/src/mp4lib_int.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/mp4lib_int.h
rename to media/module/codecs/m4v_h263/enc/src/mp4lib_int.h
diff --git a/media/codecs/m4v_h263/enc/src/rate_control.cpp b/media/module/codecs/m4v_h263/enc/src/rate_control.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/rate_control.cpp
rename to media/module/codecs/m4v_h263/enc/src/rate_control.cpp
diff --git a/media/codecs/m4v_h263/enc/src/rate_control.h b/media/module/codecs/m4v_h263/enc/src/rate_control.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/rate_control.h
rename to media/module/codecs/m4v_h263/enc/src/rate_control.h
diff --git a/media/codecs/m4v_h263/enc/src/sad.cpp b/media/module/codecs/m4v_h263/enc/src/sad.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/sad.cpp
rename to media/module/codecs/m4v_h263/enc/src/sad.cpp
diff --git a/media/codecs/m4v_h263/enc/src/sad_halfpel.cpp b/media/module/codecs/m4v_h263/enc/src/sad_halfpel.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/sad_halfpel.cpp
rename to media/module/codecs/m4v_h263/enc/src/sad_halfpel.cpp
diff --git a/media/codecs/m4v_h263/enc/src/sad_halfpel_inline.h b/media/module/codecs/m4v_h263/enc/src/sad_halfpel_inline.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/sad_halfpel_inline.h
rename to media/module/codecs/m4v_h263/enc/src/sad_halfpel_inline.h
diff --git a/media/codecs/m4v_h263/enc/src/sad_inline.h b/media/module/codecs/m4v_h263/enc/src/sad_inline.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/sad_inline.h
rename to media/module/codecs/m4v_h263/enc/src/sad_inline.h
diff --git a/media/codecs/m4v_h263/enc/src/sad_mb_offset.h b/media/module/codecs/m4v_h263/enc/src/sad_mb_offset.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/sad_mb_offset.h
rename to media/module/codecs/m4v_h263/enc/src/sad_mb_offset.h
diff --git a/media/codecs/m4v_h263/enc/src/vlc_enc_tab.h b/media/module/codecs/m4v_h263/enc/src/vlc_enc_tab.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/vlc_enc_tab.h
rename to media/module/codecs/m4v_h263/enc/src/vlc_enc_tab.h
diff --git a/media/codecs/m4v_h263/enc/src/vlc_encode.cpp b/media/module/codecs/m4v_h263/enc/src/vlc_encode.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/vlc_encode.cpp
rename to media/module/codecs/m4v_h263/enc/src/vlc_encode.cpp
diff --git a/media/codecs/m4v_h263/enc/src/vlc_encode.h b/media/module/codecs/m4v_h263/enc/src/vlc_encode.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/vlc_encode.h
rename to media/module/codecs/m4v_h263/enc/src/vlc_encode.h
diff --git a/media/codecs/m4v_h263/enc/src/vlc_encode_inline.h b/media/module/codecs/m4v_h263/enc/src/vlc_encode_inline.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/vlc_encode_inline.h
rename to media/module/codecs/m4v_h263/enc/src/vlc_encode_inline.h
diff --git a/media/codecs/m4v_h263/enc/src/vop.cpp b/media/module/codecs/m4v_h263/enc/src/vop.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/vop.cpp
rename to media/module/codecs/m4v_h263/enc/src/vop.cpp
diff --git a/media/codecs/m4v_h263/enc/test/Android.bp b/media/module/codecs/m4v_h263/enc/test/Android.bp
similarity index 90%
rename from media/codecs/m4v_h263/enc/test/Android.bp
rename to media/module/codecs/m4v_h263/enc/test/Android.bp
index 2b5e49c..d75e2d1 100644
--- a/media/codecs/m4v_h263/enc/test/Android.bp
+++ b/media/module/codecs/m4v_h263/enc/test/Android.bp
@@ -55,4 +55,7 @@
],
cfi: true,
},
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip?unzip=true",
+ ],
}
diff --git a/media/codecs/m4v_h263/enc/test/AndroidTest.xml b/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/m4v_h263/enc/test/AndroidTest.xml
rename to media/module/codecs/m4v_h263/enc/test/AndroidTest.xml
diff --git a/media/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp b/media/module/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
rename to media/module/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
diff --git a/media/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h b/media/module/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
rename to media/module/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
diff --git a/media/codecs/m4v_h263/enc/test/README.md b/media/module/codecs/m4v_h263/enc/test/README.md
similarity index 100%
rename from media/codecs/m4v_h263/enc/test/README.md
rename to media/module/codecs/m4v_h263/enc/test/README.md
diff --git a/media/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp b/media/module/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp
rename to media/module/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp
diff --git a/media/codecs/m4v_h263/fuzzer/Android.bp b/media/module/codecs/m4v_h263/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/m4v_h263/fuzzer/Android.bp
rename to media/module/codecs/m4v_h263/fuzzer/Android.bp
diff --git a/media/codecs/m4v_h263/fuzzer/README.md b/media/module/codecs/m4v_h263/fuzzer/README.md
similarity index 100%
rename from media/codecs/m4v_h263/fuzzer/README.md
rename to media/module/codecs/m4v_h263/fuzzer/README.md
diff --git a/media/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict b/media/module/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict
similarity index 100%
rename from media/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict
rename to media/module/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict
diff --git a/media/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict b/media/module/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict
similarity index 100%
rename from media/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict
rename to media/module/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict
diff --git a/media/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp b/media/module/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp
similarity index 100%
rename from media/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp
rename to media/module/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp
diff --git a/media/codecs/m4v_h263/fuzzer/mpeg4_h263_enc_fuzzer.cpp b/media/module/codecs/m4v_h263/fuzzer/mpeg4_h263_enc_fuzzer.cpp
similarity index 100%
rename from media/codecs/m4v_h263/fuzzer/mpeg4_h263_enc_fuzzer.cpp
rename to media/module/codecs/m4v_h263/fuzzer/mpeg4_h263_enc_fuzzer.cpp
diff --git a/media/codecs/m4v_h263/patent_disclaimer.txt b/media/module/codecs/m4v_h263/patent_disclaimer.txt
similarity index 100%
rename from media/codecs/m4v_h263/patent_disclaimer.txt
rename to media/module/codecs/m4v_h263/patent_disclaimer.txt
diff --git a/media/codecs/mp3dec/Android.bp b/media/module/codecs/mp3dec/Android.bp
similarity index 100%
rename from media/codecs/mp3dec/Android.bp
rename to media/module/codecs/mp3dec/Android.bp
diff --git a/media/codecs/mp3dec/MODULE_LICENSE_APACHE2 b/media/module/codecs/mp3dec/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/mp3dec/MODULE_LICENSE_APACHE2
rename to media/module/codecs/mp3dec/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/mp3dec/NOTICE b/media/module/codecs/mp3dec/NOTICE
similarity index 100%
rename from media/codecs/mp3dec/NOTICE
rename to media/module/codecs/mp3dec/NOTICE
diff --git a/media/codecs/mp3dec/TEST_MAPPING b/media/module/codecs/mp3dec/TEST_MAPPING
similarity index 100%
rename from media/codecs/mp3dec/TEST_MAPPING
rename to media/module/codecs/mp3dec/TEST_MAPPING
diff --git a/media/codecs/mp3dec/fuzzer/Android.bp b/media/module/codecs/mp3dec/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/mp3dec/fuzzer/Android.bp
rename to media/module/codecs/mp3dec/fuzzer/Android.bp
diff --git a/media/codecs/mp3dec/fuzzer/README.md b/media/module/codecs/mp3dec/fuzzer/README.md
similarity index 100%
rename from media/codecs/mp3dec/fuzzer/README.md
rename to media/module/codecs/mp3dec/fuzzer/README.md
diff --git a/media/codecs/mp3dec/fuzzer/mp3_dec_fuzzer.cpp b/media/module/codecs/mp3dec/fuzzer/mp3_dec_fuzzer.cpp
similarity index 100%
rename from media/codecs/mp3dec/fuzzer/mp3_dec_fuzzer.cpp
rename to media/module/codecs/mp3dec/fuzzer/mp3_dec_fuzzer.cpp
diff --git a/media/codecs/mp3dec/include/mp3_decoder_selection.h b/media/module/codecs/mp3dec/include/mp3_decoder_selection.h
similarity index 100%
rename from media/codecs/mp3dec/include/mp3_decoder_selection.h
rename to media/module/codecs/mp3dec/include/mp3_decoder_selection.h
diff --git a/media/codecs/mp3dec/include/pvmp3_audio_type_defs.h b/media/module/codecs/mp3dec/include/pvmp3_audio_type_defs.h
similarity index 100%
rename from media/codecs/mp3dec/include/pvmp3_audio_type_defs.h
rename to media/module/codecs/mp3dec/include/pvmp3_audio_type_defs.h
diff --git a/media/codecs/mp3dec/include/pvmp3decoder_api.h b/media/module/codecs/mp3dec/include/pvmp3decoder_api.h
similarity index 100%
rename from media/codecs/mp3dec/include/pvmp3decoder_api.h
rename to media/module/codecs/mp3dec/include/pvmp3decoder_api.h
diff --git a/media/codecs/mp3dec/patent_disclaimer.txt b/media/module/codecs/mp3dec/patent_disclaimer.txt
similarity index 100%
rename from media/codecs/mp3dec/patent_disclaimer.txt
rename to media/module/codecs/mp3dec/patent_disclaimer.txt
diff --git a/media/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s b/media/module/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s
similarity index 100%
rename from media/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s
rename to media/module/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s
diff --git a/media/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s b/media/module/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s
similarity index 100%
rename from media/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s
rename to media/module/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s
diff --git a/media/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s b/media/module/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s
similarity index 100%
rename from media/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s
rename to media/module/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s
diff --git a/media/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s b/media/module/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
similarity index 100%
rename from media/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
rename to media/module/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
diff --git a/media/codecs/mp3dec/src/mp3_mem_funcs.h b/media/module/codecs/mp3dec/src/mp3_mem_funcs.h
similarity index 100%
rename from media/codecs/mp3dec/src/mp3_mem_funcs.h
rename to media/module/codecs/mp3dec/src/mp3_mem_funcs.h
diff --git a/media/codecs/mp3dec/src/pv_mp3_huffman.h b/media/module/codecs/mp3dec/src/pv_mp3_huffman.h
similarity index 100%
rename from media/codecs/mp3dec/src/pv_mp3_huffman.h
rename to media/module/codecs/mp3dec/src/pv_mp3_huffman.h
diff --git a/media/codecs/mp3dec/src/pv_mp3dec_fxd_op.h b/media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op.h
similarity index 100%
rename from media/codecs/mp3dec/src/pv_mp3dec_fxd_op.h
rename to media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op.h
diff --git a/media/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h b/media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h
similarity index 100%
rename from media/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h
rename to media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h
diff --git a/media/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h b/media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h
similarity index 100%
rename from media/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h
rename to media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h
diff --git a/media/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h b/media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
similarity index 100%
rename from media/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
rename to media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
diff --git a/media/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h b/media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h
similarity index 100%
rename from media/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h
rename to media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h
diff --git a/media/codecs/mp3dec/src/pvmp3_alias_reduction.cpp b/media/module/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_alias_reduction.h b/media/module/codecs/mp3dec/src/pvmp3_alias_reduction.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_alias_reduction.h
rename to media/module/codecs/mp3dec/src/pvmp3_alias_reduction.h
diff --git a/media/codecs/mp3dec/src/pvmp3_crc.cpp b/media/module/codecs/mp3dec/src/pvmp3_crc.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_crc.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_crc.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_crc.h b/media/module/codecs/mp3dec/src/pvmp3_crc.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_crc.h
rename to media/module/codecs/mp3dec/src/pvmp3_crc.h
diff --git a/media/codecs/mp3dec/src/pvmp3_dct_16.cpp b/media/module/codecs/mp3dec/src/pvmp3_dct_16.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dct_16.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_dct_16.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_dct_16.h b/media/module/codecs/mp3dec/src/pvmp3_dct_16.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dct_16.h
rename to media/module/codecs/mp3dec/src/pvmp3_dct_16.h
diff --git a/media/codecs/mp3dec/src/pvmp3_dct_6.cpp b/media/module/codecs/mp3dec/src/pvmp3_dct_6.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dct_6.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_dct_6.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_dct_9.cpp b/media/module/codecs/mp3dec/src/pvmp3_dct_9.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dct_9.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_dct_9.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_dec_defs.h b/media/module/codecs/mp3dec/src/pvmp3_dec_defs.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dec_defs.h
rename to media/module/codecs/mp3dec/src/pvmp3_dec_defs.h
diff --git a/media/codecs/mp3dec/src/pvmp3_decode_header.cpp b/media/module/codecs/mp3dec/src/pvmp3_decode_header.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_decode_header.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_decode_header.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_decode_header.h b/media/module/codecs/mp3dec/src/pvmp3_decode_header.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_decode_header.h
rename to media/module/codecs/mp3dec/src/pvmp3_decode_header.h
diff --git a/media/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp b/media/module/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_decode_huff_cw.h b/media/module/codecs/mp3dec/src/pvmp3_decode_huff_cw.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_decode_huff_cw.h
rename to media/module/codecs/mp3dec/src/pvmp3_decode_huff_cw.h
diff --git a/media/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp b/media/module/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_dequantize_sample.h b/media/module/codecs/mp3dec/src/pvmp3_dequantize_sample.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dequantize_sample.h
rename to media/module/codecs/mp3dec/src/pvmp3_dequantize_sample.h
diff --git a/media/codecs/mp3dec/src/pvmp3_equalizer.cpp b/media/module/codecs/mp3dec/src/pvmp3_equalizer.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_equalizer.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_equalizer.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_equalizer.h b/media/module/codecs/mp3dec/src/pvmp3_equalizer.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_equalizer.h
rename to media/module/codecs/mp3dec/src/pvmp3_equalizer.h
diff --git a/media/codecs/mp3dec/src/pvmp3_framedecoder.cpp b/media/module/codecs/mp3dec/src/pvmp3_framedecoder.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_framedecoder.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_framedecoder.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_framedecoder.h b/media/module/codecs/mp3dec/src/pvmp3_framedecoder.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_framedecoder.h
rename to media/module/codecs/mp3dec/src/pvmp3_framedecoder.h
diff --git a/media/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp b/media/module/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_get_main_data_size.h b/media/module/codecs/mp3dec/src/pvmp3_get_main_data_size.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_get_main_data_size.h
rename to media/module/codecs/mp3dec/src/pvmp3_get_main_data_size.h
diff --git a/media/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp b/media/module/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_get_scale_factors.h b/media/module/codecs/mp3dec/src/pvmp3_get_scale_factors.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_get_scale_factors.h
rename to media/module/codecs/mp3dec/src/pvmp3_get_scale_factors.h
diff --git a/media/codecs/mp3dec/src/pvmp3_get_side_info.cpp b/media/module/codecs/mp3dec/src/pvmp3_get_side_info.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_get_side_info.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_get_side_info.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_get_side_info.h b/media/module/codecs/mp3dec/src/pvmp3_get_side_info.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_get_side_info.h
rename to media/module/codecs/mp3dec/src/pvmp3_get_side_info.h
diff --git a/media/codecs/mp3dec/src/pvmp3_getbits.cpp b/media/module/codecs/mp3dec/src/pvmp3_getbits.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_getbits.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_getbits.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_getbits.h b/media/module/codecs/mp3dec/src/pvmp3_getbits.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_getbits.h
rename to media/module/codecs/mp3dec/src/pvmp3_getbits.h
diff --git a/media/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp b/media/module/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp b/media/module/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_imdct_synth.cpp b/media/module/codecs/mp3dec/src/pvmp3_imdct_synth.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_imdct_synth.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_imdct_synth.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_imdct_synth.h b/media/module/codecs/mp3dec/src/pvmp3_imdct_synth.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_imdct_synth.h
rename to media/module/codecs/mp3dec/src/pvmp3_imdct_synth.h
diff --git a/media/codecs/mp3dec/src/pvmp3_mdct_18.cpp b/media/module/codecs/mp3dec/src/pvmp3_mdct_18.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mdct_18.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_mdct_18.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_mdct_18.h b/media/module/codecs/mp3dec/src/pvmp3_mdct_18.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mdct_18.h
rename to media/module/codecs/mp3dec/src/pvmp3_mdct_18.h
diff --git a/media/codecs/mp3dec/src/pvmp3_mdct_6.cpp b/media/module/codecs/mp3dec/src/pvmp3_mdct_6.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mdct_6.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_mdct_6.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_mdct_6.h b/media/module/codecs/mp3dec/src/pvmp3_mdct_6.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mdct_6.h
rename to media/module/codecs/mp3dec/src/pvmp3_mdct_6.h
diff --git a/media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp b/media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h b/media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h
rename to media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h
diff --git a/media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp b/media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h b/media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h
rename to media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h
diff --git a/media/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp b/media/module/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h b/media/module/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h
rename to media/module/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h
diff --git a/media/codecs/mp3dec/src/pvmp3_normalize.cpp b/media/module/codecs/mp3dec/src/pvmp3_normalize.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_normalize.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_normalize.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_normalize.h b/media/module/codecs/mp3dec/src/pvmp3_normalize.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_normalize.h
rename to media/module/codecs/mp3dec/src/pvmp3_normalize.h
diff --git a/media/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp b/media/module/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h b/media/module/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h
rename to media/module/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h
diff --git a/media/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp b/media/module/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h b/media/module/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h
rename to media/module/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h
diff --git a/media/codecs/mp3dec/src/pvmp3_reorder.cpp b/media/module/codecs/mp3dec/src/pvmp3_reorder.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_reorder.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_reorder.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_reorder.h b/media/module/codecs/mp3dec/src/pvmp3_reorder.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_reorder.h
rename to media/module/codecs/mp3dec/src/pvmp3_reorder.h
diff --git a/media/codecs/mp3dec/src/pvmp3_seek_synch.cpp b/media/module/codecs/mp3dec/src/pvmp3_seek_synch.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_seek_synch.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_seek_synch.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_seek_synch.h b/media/module/codecs/mp3dec/src/pvmp3_seek_synch.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_seek_synch.h
rename to media/module/codecs/mp3dec/src/pvmp3_seek_synch.h
diff --git a/media/codecs/mp3dec/src/pvmp3_stereo_proc.cpp b/media/module/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_stereo_proc.h b/media/module/codecs/mp3dec/src/pvmp3_stereo_proc.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_stereo_proc.h
rename to media/module/codecs/mp3dec/src/pvmp3_stereo_proc.h
diff --git a/media/codecs/mp3dec/src/pvmp3_tables.cpp b/media/module/codecs/mp3dec/src/pvmp3_tables.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_tables.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_tables.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_tables.h b/media/module/codecs/mp3dec/src/pvmp3_tables.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_tables.h
rename to media/module/codecs/mp3dec/src/pvmp3_tables.h
diff --git a/media/codecs/mp3dec/src/s_huffcodetab.h b/media/module/codecs/mp3dec/src/s_huffcodetab.h
similarity index 100%
rename from media/codecs/mp3dec/src/s_huffcodetab.h
rename to media/module/codecs/mp3dec/src/s_huffcodetab.h
diff --git a/media/codecs/mp3dec/src/s_mp3bits.h b/media/module/codecs/mp3dec/src/s_mp3bits.h
similarity index 100%
rename from media/codecs/mp3dec/src/s_mp3bits.h
rename to media/module/codecs/mp3dec/src/s_mp3bits.h
diff --git a/media/codecs/mp3dec/src/s_tmp3dec_chan.h b/media/module/codecs/mp3dec/src/s_tmp3dec_chan.h
similarity index 100%
rename from media/codecs/mp3dec/src/s_tmp3dec_chan.h
rename to media/module/codecs/mp3dec/src/s_tmp3dec_chan.h
diff --git a/media/codecs/mp3dec/src/s_tmp3dec_file.h b/media/module/codecs/mp3dec/src/s_tmp3dec_file.h
similarity index 100%
rename from media/codecs/mp3dec/src/s_tmp3dec_file.h
rename to media/module/codecs/mp3dec/src/s_tmp3dec_file.h
diff --git a/media/codecs/mp3dec/test/Android.bp b/media/module/codecs/mp3dec/test/Android.bp
similarity index 90%
rename from media/codecs/mp3dec/test/Android.bp
rename to media/module/codecs/mp3dec/test/Android.bp
index f10b6ae..dd06bdc 100644
--- a/media/codecs/mp3dec/test/Android.bp
+++ b/media/module/codecs/mp3dec/test/Android.bp
@@ -56,4 +56,7 @@
"signed-integer-overflow",
],
},
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest-1.2.zip?unzip=true",
+ ],
}
diff --git a/media/codecs/mp3dec/test/AndroidTest.xml b/media/module/codecs/mp3dec/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/mp3dec/test/AndroidTest.xml
rename to media/module/codecs/mp3dec/test/AndroidTest.xml
diff --git a/media/codecs/mp3dec/test/Mp3DecoderTest.cpp b/media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp
similarity index 89%
rename from media/codecs/mp3dec/test/Mp3DecoderTest.cpp
rename to media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp
index 91326a8..88e9eae 100644
--- a/media/codecs/mp3dec/test/Mp3DecoderTest.cpp
+++ b/media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp
@@ -20,6 +20,7 @@
#include <utils/Log.h>
#include <audio_utils/sndfile.h>
+#include <memory>
#include <stdio.h>
#include "mp3reader.h"
@@ -99,27 +100,23 @@
TEST_F(Mp3DecoderTest, MultiCreateMp3DecoderTest) {
size_t memRequirements = pvmp3_decoderMemRequirements();
ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
- void *decoderBuf = malloc(memRequirements);
+ unique_ptr<char[]> decoderBuf(new char[memRequirements]);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
for (int count = 0; count < kMaxCount; count++) {
- pvmp3_InitDecoder(mConfig, decoderBuf);
+ pvmp3_InitDecoder(mConfig, (void*)decoderBuf.get());
ALOGV("Decoder created successfully");
}
- if (decoderBuf) {
- free(decoderBuf);
- decoderBuf = nullptr;
- }
}
TEST_P(Mp3DecoderTest, DecodeTest) {
size_t memRequirements = pvmp3_decoderMemRequirements();
ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
- void *decoderBuf = malloc(memRequirements);
+ unique_ptr<char[]> decoderBuf(new char[memRequirements]);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
- pvmp3_InitDecoder(mConfig, decoderBuf);
+ pvmp3_InitDecoder(mConfig, (void*)decoderBuf.get());
ALOGV("Decoder created successfully");
string inputFile = gEnv->getRes() + GetParam();
bool status = mMp3Reader.init(inputFile.c_str());
@@ -130,27 +127,23 @@
SNDFILE *outFileHandle = openOutputFile(&sfInfo);
ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
- ERROR_CODE decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo);
+ ERROR_CODE decoderErr = DecodeFrames((void*)decoderBuf.get(), outFileHandle, sfInfo);
ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
mMp3Reader.close();
sf_close(outFileHandle);
- if (decoderBuf) {
- free(decoderBuf);
- decoderBuf = nullptr;
- }
}
TEST_P(Mp3DecoderTest, ResetDecoderTest) {
size_t memRequirements = pvmp3_decoderMemRequirements();
ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
- void *decoderBuf = malloc(memRequirements);
+ unique_ptr<char[]> decoderBuf(new char[memRequirements]);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
- pvmp3_InitDecoder(mConfig, decoderBuf);
+ pvmp3_InitDecoder(mConfig, (void*)decoderBuf.get());
ALOGV("Decoder created successfully.");
string inputFile = gEnv->getRes() + GetParam();
bool status = mMp3Reader.init(inputFile.c_str());
@@ -162,24 +155,20 @@
ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
ERROR_CODE decoderErr;
- decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo, kNumFrameReset);
+ decoderErr = DecodeFrames((void*)decoderBuf.get(), outFileHandle, sfInfo, kNumFrameReset);
ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
- pvmp3_resetDecoder(decoderBuf);
+ pvmp3_resetDecoder((void*)decoderBuf.get());
// Decode the same file.
- decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo);
+ decoderErr = DecodeFrames((void*)decoderBuf.get(), outFileHandle, sfInfo);
ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
mMp3Reader.close();
sf_close(outFileHandle);
- if (decoderBuf) {
- free(decoderBuf);
- decoderBuf = nullptr;
- }
}
INSTANTIATE_TEST_SUITE_P(Mp3DecoderTestAll, Mp3DecoderTest,
diff --git a/media/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h b/media/module/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h
similarity index 100%
rename from media/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h
rename to media/module/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h
diff --git a/media/codecs/mp3dec/test/README.md b/media/module/codecs/mp3dec/test/README.md
similarity index 100%
rename from media/codecs/mp3dec/test/README.md
rename to media/module/codecs/mp3dec/test/README.md
diff --git a/media/codecs/mp3dec/test/mp3dec_test.cpp b/media/module/codecs/mp3dec/test/mp3dec_test.cpp
similarity index 100%
rename from media/codecs/mp3dec/test/mp3dec_test.cpp
rename to media/module/codecs/mp3dec/test/mp3dec_test.cpp
diff --git a/media/codecs/mp3dec/test/mp3reader.cpp b/media/module/codecs/mp3dec/test/mp3reader.cpp
similarity index 100%
rename from media/codecs/mp3dec/test/mp3reader.cpp
rename to media/module/codecs/mp3dec/test/mp3reader.cpp
diff --git a/media/codecs/mp3dec/test/mp3reader.h b/media/module/codecs/mp3dec/test/mp3reader.h
similarity index 100%
rename from media/codecs/mp3dec/test/mp3reader.h
rename to media/module/codecs/mp3dec/test/mp3reader.h
diff --git a/services/mediacodec/registrant/Android.bp b/media/module/codecserviceregistrant/Android.bp
similarity index 95%
rename from services/mediacodec/registrant/Android.bp
rename to media/module/codecserviceregistrant/Android.bp
index 12cc32a..5637b37 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/media/module/codecserviceregistrant/Android.bp
@@ -4,7 +4,6 @@
// all of the 'license_kinds' from "frameworks_av_services_mediacodec_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_av_services_mediacodec_license"],
}
cc_library {
diff --git a/services/mediacodec/registrant/CodecServiceRegistrant.cpp b/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
similarity index 100%
rename from services/mediacodec/registrant/CodecServiceRegistrant.cpp
rename to media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
diff --git a/services/mediacodec/registrant/fuzzer/Android.bp b/media/module/codecserviceregistrant/fuzzer/Android.bp
similarity index 94%
rename from services/mediacodec/registrant/fuzzer/Android.bp
rename to media/module/codecserviceregistrant/fuzzer/Android.bp
index 43afbf1..0b9affd 100644
--- a/services/mediacodec/registrant/fuzzer/Android.bp
+++ b/media/module/codecserviceregistrant/fuzzer/Android.bp
@@ -20,7 +20,6 @@
// all of the 'license_kinds' from "frameworks_av_services_mediacodec_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_av_services_mediacodec_license"],
}
cc_fuzz {
diff --git a/services/mediacodec/registrant/fuzzer/README.md b/media/module/codecserviceregistrant/fuzzer/README.md
similarity index 100%
rename from services/mediacodec/registrant/fuzzer/README.md
rename to media/module/codecserviceregistrant/fuzzer/README.md
diff --git a/services/mediacodec/registrant/fuzzer/codecServiceRegistrant_fuzzer.cpp b/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
similarity index 100%
rename from services/mediacodec/registrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
rename to media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
diff --git a/media/module/esds/Android.bp b/media/module/esds/Android.bp
new file mode 100644
index 0000000..272d4d7
--- /dev/null
+++ b/media/module/esds/Android.bp
@@ -0,0 +1,44 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library_static {
+ name: "libstagefright_esds",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media",
+ ],
+ min_sdk_version: "29",
+
+ export_include_dirs: ["include"],
+
+ local_include_dirs: ["include"],
+
+ srcs: ["ESDS.cpp"],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ ],
+ cfi: true,
+ },
+ shared_libs: [
+ "libstagefright_foundation",
+ "libutils"
+ ],
+ host_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
diff --git a/media/libstagefright/ESDS.cpp b/media/module/esds/ESDS.cpp
similarity index 99%
rename from media/libstagefright/ESDS.cpp
rename to media/module/esds/ESDS.cpp
index ea059e8..906250b 100644
--- a/media/libstagefright/ESDS.cpp
+++ b/media/module/esds/ESDS.cpp
@@ -20,7 +20,7 @@
#include <media/stagefright/foundation/ByteUtils.h>
-#include "include/ESDS.h"
+#include <media/esds/ESDS.h>
#include <string.h>
diff --git a/media/module/esds/TEST_MAPPING b/media/module/esds/TEST_MAPPING
new file mode 100644
index 0000000..9368b6d
--- /dev/null
+++ b/media/module/esds/TEST_MAPPING
@@ -0,0 +1,9 @@
+// mappings for frameworks/av/media/module/esds
+{
+ // tests which require dynamic content
+ // invoke with: atest -- --enable-module-dynamic-download=true
+ // TODO(b/148094059): unit tests not allowed to download content
+ "dynamic-presubmit": [
+ { "name": "ESDSTest" }
+ ]
+}
diff --git a/media/libstagefright/include/ESDS.h b/media/module/esds/include/media/esds/ESDS.h
similarity index 100%
rename from media/libstagefright/include/ESDS.h
rename to media/module/esds/include/media/esds/ESDS.h
diff --git a/media/libstagefright/tests/ESDS/Android.bp b/media/module/esds/tests/Android.bp
similarity index 93%
rename from media/libstagefright/tests/ESDS/Android.bp
rename to media/module/esds/tests/Android.bp
index 04e9b29..aea611e 100644
--- a/media/libstagefright/tests/ESDS/Android.bp
+++ b/media/module/esds/tests/Android.bp
@@ -20,9 +20,6 @@
// all of the 'license_kinds' from "frameworks_av_media_libstagefright_tests_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: [
- "frameworks_av_media_libstagefright_tests_license",
- ],
}
cc_test {
diff --git a/media/libstagefright/tests/ESDS/AndroidTest.xml b/media/module/esds/tests/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/tests/ESDS/AndroidTest.xml
rename to media/module/esds/tests/AndroidTest.xml
diff --git a/media/libstagefright/tests/ESDS/ESDSTest.cpp b/media/module/esds/tests/ESDSTest.cpp
similarity index 96%
rename from media/libstagefright/tests/ESDS/ESDSTest.cpp
rename to media/module/esds/tests/ESDSTest.cpp
index 101e00c..33bdcac 100644
--- a/media/libstagefright/tests/ESDS/ESDSTest.cpp
+++ b/media/module/esds/tests/ESDSTest.cpp
@@ -21,8 +21,9 @@
#include <stdio.h>
#include <string.h>
#include <fstream>
+#include <memory>
-#include <ESDS.h>
+#include <media/esds/ESDS.h>
#include <binder/ProcessState.h>
#include <datasource/FileSource.h>
#include <media/stagefright/MediaExtractorFactory.h>
@@ -121,18 +122,16 @@
};
TEST_P(ESDSUnitTest, InvalidDataTest) {
- void *invalidData = calloc(mESDSSize, 1);
+ std::unique_ptr<char[]> invalidData(new char[mESDSSize]());
ASSERT_NE(invalidData, nullptr) << "Unable to allocate memory";
- ESDS esds(invalidData, mESDSSize);
- free(invalidData);
+ ESDS esds((void*)invalidData.get(), mESDSSize);
ASSERT_NE(esds.InitCheck(), OK) << "invalid ESDS data accepted";
}
TEST(ESDSSanityUnitTest, ConstructorSanityTest) {
- void *invalidData = malloc(1);
+ std::unique_ptr<char[]> invalidData(new char[1]());
ASSERT_NE(invalidData, nullptr) << "Unable to allocate memory";
- ESDS esds_zero(invalidData, 0);
- free(invalidData);
+ ESDS esds_zero((void*)invalidData.get(), 0);
ASSERT_NE(esds_zero.InitCheck(), OK) << "invalid ESDS data accepted";
ESDS esds_null(NULL, 0);
diff --git a/media/libstagefright/tests/ESDS/ESDSTestEnvironment.h b/media/module/esds/tests/ESDSTestEnvironment.h
similarity index 100%
rename from media/libstagefright/tests/ESDS/ESDSTestEnvironment.h
rename to media/module/esds/tests/ESDSTestEnvironment.h
diff --git a/media/libstagefright/tests/ESDS/README.md b/media/module/esds/tests/README.md
similarity index 100%
rename from media/libstagefright/tests/ESDS/README.md
rename to media/module/esds/tests/README.md
diff --git a/media/extractors/Android.bp b/media/module/extractors/Android.bp
similarity index 100%
rename from media/extractors/Android.bp
rename to media/module/extractors/Android.bp
diff --git a/media/extractors/TEST_MAPPING b/media/module/extractors/TEST_MAPPING
similarity index 100%
rename from media/extractors/TEST_MAPPING
rename to media/module/extractors/TEST_MAPPING
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/module/extractors/aac/AACExtractor.cpp
similarity index 98%
rename from media/extractors/aac/AACExtractor.cpp
rename to media/module/extractors/aac/AACExtractor.cpp
index 2fc4584..a44fb61 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/module/extractors/aac/AACExtractor.cpp
@@ -310,9 +310,9 @@
return AMEDIA_ERROR_END_OF_STREAM;
}
- MediaBufferHelper *buffer;
+ MediaBufferHelper *buffer = nullptr;
status_t err = mBufferGroup->acquire_buffer(&buffer);
- if (err != OK) {
+ if (err != OK || buffer == nullptr) {
return AMEDIA_ERROR_UNKNOWN;
}
diff --git a/media/extractors/aac/Android.bp b/media/module/extractors/aac/Android.bp
similarity index 100%
rename from media/extractors/aac/Android.bp
rename to media/module/extractors/aac/Android.bp
diff --git a/media/extractors/aac/MODULE_LICENSE_APACHE2 b/media/module/extractors/aac/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/aac/MODULE_LICENSE_APACHE2
rename to media/module/extractors/aac/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/aac/NOTICE b/media/module/extractors/aac/NOTICE
similarity index 100%
rename from media/extractors/aac/NOTICE
rename to media/module/extractors/aac/NOTICE
diff --git a/media/extractors/aac/exports.lds b/media/module/extractors/aac/exports.lds
similarity index 100%
rename from media/extractors/aac/exports.lds
rename to media/module/extractors/aac/exports.lds
diff --git a/media/extractors/aac/include/AACExtractor.h b/media/module/extractors/aac/include/AACExtractor.h
similarity index 100%
rename from media/extractors/aac/include/AACExtractor.h
rename to media/module/extractors/aac/include/AACExtractor.h
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/module/extractors/amr/AMRExtractor.cpp
similarity index 98%
rename from media/extractors/amr/AMRExtractor.cpp
rename to media/module/extractors/amr/AMRExtractor.cpp
index e26ff0a..b0f69ce 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/module/extractors/amr/AMRExtractor.cpp
@@ -341,9 +341,9 @@
return AMEDIA_ERROR_MALFORMED;
}
- MediaBufferHelper *buffer;
+ MediaBufferHelper *buffer = nullptr;
status_t err = mBufferGroup->acquire_buffer(&buffer);
- if (err != OK) {
+ if (err != OK || buffer == nullptr) {
return AMEDIA_ERROR_UNKNOWN;
}
diff --git a/media/extractors/amr/Android.bp b/media/module/extractors/amr/Android.bp
similarity index 100%
rename from media/extractors/amr/Android.bp
rename to media/module/extractors/amr/Android.bp
diff --git a/media/extractors/amr/MODULE_LICENSE_APACHE2 b/media/module/extractors/amr/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/amr/MODULE_LICENSE_APACHE2
rename to media/module/extractors/amr/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/amr/NOTICE b/media/module/extractors/amr/NOTICE
similarity index 100%
rename from media/extractors/amr/NOTICE
rename to media/module/extractors/amr/NOTICE
diff --git a/media/extractors/amr/exports.lds b/media/module/extractors/amr/exports.lds
similarity index 100%
rename from media/extractors/amr/exports.lds
rename to media/module/extractors/amr/exports.lds
diff --git a/media/extractors/amr/include/AMRExtractor.h b/media/module/extractors/amr/include/AMRExtractor.h
similarity index 100%
rename from media/extractors/amr/include/AMRExtractor.h
rename to media/module/extractors/amr/include/AMRExtractor.h
diff --git a/media/extractors/flac/Android.bp b/media/module/extractors/flac/Android.bp
similarity index 100%
rename from media/extractors/flac/Android.bp
rename to media/module/extractors/flac/Android.bp
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/module/extractors/flac/FLACExtractor.cpp
similarity index 99%
rename from media/extractors/flac/FLACExtractor.cpp
rename to media/module/extractors/flac/FLACExtractor.cpp
index ec7cb24..2434e41 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/module/extractors/flac/FLACExtractor.cpp
@@ -614,9 +614,9 @@
}
// acquire a media buffer
CHECK(mGroup != NULL);
- MediaBufferHelper *buffer;
+ MediaBufferHelper *buffer = nullptr;
status_t err = mGroup->acquire_buffer(&buffer);
- if (err != OK) {
+ if (err != OK || buffer == nullptr) {
return NULL;
}
const size_t bufferSize = blocksize * getChannels() * getOutputSampleSize();
diff --git a/media/extractors/flac/MODULE_LICENSE_APACHE2 b/media/module/extractors/flac/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/flac/MODULE_LICENSE_APACHE2
rename to media/module/extractors/flac/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/flac/NOTICE b/media/module/extractors/flac/NOTICE
similarity index 100%
rename from media/extractors/flac/NOTICE
rename to media/module/extractors/flac/NOTICE
diff --git a/media/extractors/flac/exports.lds b/media/module/extractors/flac/exports.lds
similarity index 100%
rename from media/extractors/flac/exports.lds
rename to media/module/extractors/flac/exports.lds
diff --git a/media/extractors/flac/include/FLACExtractor.h b/media/module/extractors/flac/include/FLACExtractor.h
similarity index 100%
rename from media/extractors/flac/include/FLACExtractor.h
rename to media/module/extractors/flac/include/FLACExtractor.h
diff --git a/media/extractors/fuzzers/Android.bp b/media/module/extractors/fuzzers/Android.bp
similarity index 99%
rename from media/extractors/fuzzers/Android.bp
rename to media/module/extractors/fuzzers/Android.bp
index 490e195..b3e34d2 100644
--- a/media/extractors/fuzzers/Android.bp
+++ b/media/module/extractors/fuzzers/Android.bp
@@ -173,7 +173,7 @@
],
static_libs: [
- "libwebm",
+ "libwebm_mkvparser",
"libstagefright_flacdec",
"libstagefright_metadatautils",
"libmkvextractor",
diff --git a/media/extractors/fuzzers/ExtractorFuzzerBase.cpp b/media/module/extractors/fuzzers/ExtractorFuzzerBase.cpp
similarity index 100%
rename from media/extractors/fuzzers/ExtractorFuzzerBase.cpp
rename to media/module/extractors/fuzzers/ExtractorFuzzerBase.cpp
diff --git a/media/extractors/fuzzers/README.md b/media/module/extractors/fuzzers/README.md
similarity index 100%
rename from media/extractors/fuzzers/README.md
rename to media/module/extractors/fuzzers/README.md
diff --git a/media/extractors/fuzzers/aac_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/aac_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/aac_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/aac_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/amr_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/amr_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/amr_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/amr_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/amr_extractor_fuzzer.dict b/media/module/extractors/fuzzers/amr_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/amr_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/amr_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/flac_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/flac_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/flac_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/flac_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/flac_extractor_fuzzer.dict b/media/module/extractors/fuzzers/flac_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/flac_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/flac_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/include/ExtractorFuzzerBase.h b/media/module/extractors/fuzzers/include/ExtractorFuzzerBase.h
similarity index 100%
rename from media/extractors/fuzzers/include/ExtractorFuzzerBase.h
rename to media/module/extractors/fuzzers/include/ExtractorFuzzerBase.h
diff --git a/media/extractors/fuzzers/midi_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/midi_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/midi_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/midi_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/midi_extractor_fuzzer.dict b/media/module/extractors/fuzzers/midi_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/midi_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/midi_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/mkv_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/mkv_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/mkv_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/mkv_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/mkv_extractor_fuzzer.dict b/media/module/extractors/fuzzers/mkv_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/mkv_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/mkv_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/mp3_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/mp3_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/mp3_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/mp3_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/mp4_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/mp4_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/mp4_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/mp4_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/mp4_extractor_fuzzer.dict b/media/module/extractors/fuzzers/mp4_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/mp4_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/mp4_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/mpeg2_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/mpeg2_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/mpeg2_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/mpeg2_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/mpeg2ps_extractor_fuzzer.dict b/media/module/extractors/fuzzers/mpeg2ps_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/mpeg2ps_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/mpeg2ps_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/mpeg2ts_extractor_fuzzer.dict b/media/module/extractors/fuzzers/mpeg2ts_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/mpeg2ts_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/mpeg2ts_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/ogg_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/ogg_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/ogg_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/ogg_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/ogg_extractor_fuzzer.dict b/media/module/extractors/fuzzers/ogg_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/ogg_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/ogg_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/wav_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/wav_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/wav_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/wav_extractor_fuzzer.cpp
diff --git a/media/extractors/midi/Android.bp b/media/module/extractors/midi/Android.bp
similarity index 100%
rename from media/extractors/midi/Android.bp
rename to media/module/extractors/midi/Android.bp
diff --git a/media/extractors/midi/MODULE_LICENSE_APACHE2 b/media/module/extractors/midi/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/midi/MODULE_LICENSE_APACHE2
rename to media/module/extractors/midi/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/module/extractors/midi/MidiExtractor.cpp
similarity index 98%
rename from media/extractors/midi/MidiExtractor.cpp
rename to media/module/extractors/midi/MidiExtractor.cpp
index d0efb2f..167cc40 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/module/extractors/midi/MidiExtractor.cpp
@@ -240,9 +240,9 @@
if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) {
return NULL;
}
- MediaBufferHelper *buffer;
+ MediaBufferHelper *buffer = nullptr;
status_t err = mGroup->acquire_buffer(&buffer);
- if (err != OK) {
+ if (err != OK || buffer == nullptr) {
ALOGE("readBuffer: no buffer");
return NULL;
}
diff --git a/media/extractors/midi/NOTICE b/media/module/extractors/midi/NOTICE
similarity index 100%
rename from media/extractors/midi/NOTICE
rename to media/module/extractors/midi/NOTICE
diff --git a/media/extractors/midi/exports.lds b/media/module/extractors/midi/exports.lds
similarity index 100%
rename from media/extractors/midi/exports.lds
rename to media/module/extractors/midi/exports.lds
diff --git a/media/extractors/midi/include/MidiExtractor.h b/media/module/extractors/midi/include/MidiExtractor.h
similarity index 100%
rename from media/extractors/midi/include/MidiExtractor.h
rename to media/module/extractors/midi/include/MidiExtractor.h
diff --git a/media/extractors/mkv/Android.bp b/media/module/extractors/mkv/Android.bp
similarity index 96%
rename from media/extractors/mkv/Android.bp
rename to media/module/extractors/mkv/Android.bp
index 98ce305..c4b67eb 100644
--- a/media/extractors/mkv/Android.bp
+++ b/media/module/extractors/mkv/Android.bp
@@ -33,7 +33,7 @@
"libstagefright_foundation_colorutils_ndk", // for mainline-safe ColorUtils
"libstagefright_foundation",
"libstagefright_metadatautils",
- "libwebm",
+ "libwebm_mkvparser",
"libutils",
],
diff --git a/media/extractors/mkv/MODULE_LICENSE_APACHE2 b/media/module/extractors/mkv/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/mkv/MODULE_LICENSE_APACHE2
rename to media/module/extractors/mkv/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/module/extractors/mkv/MatroskaExtractor.cpp
similarity index 99%
rename from media/extractors/mkv/MatroskaExtractor.cpp
rename to media/module/extractors/mkv/MatroskaExtractor.cpp
index 443e26c..2b72387 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/module/extractors/mkv/MatroskaExtractor.cpp
@@ -790,6 +790,7 @@
int64_t timeUs = mBlockIter.blockTimeUs();
for (int i = 0; i < block->GetFrameCount(); ++i) {
+ status_t err;
MatroskaExtractor::TrackInfo *trackInfo = &mExtractor->mTracks.editItemAt(mTrackIndex);
const mkvparser::Block::Frame &frame = block->GetFrame(i);
size_t len = frame.len;
@@ -798,8 +799,13 @@
}
len += trackInfo->mHeaderLen;
- MediaBufferHelper *mbuf;
- mBufferGroup->acquire_buffer(&mbuf, false /* nonblocking */, len /* requested size */);
+ MediaBufferHelper *mbuf = nullptr;
+ err = mBufferGroup->acquire_buffer(&mbuf, false /* nonblocking */,
+ len /* requested size */);
+ if (err != OK || mbuf == nullptr) {
+ ALOGE("readBlock: no buffer");
+ return AMEDIA_ERROR_UNKNOWN;
+ }
mbuf->set_range(0, len);
uint8_t *data = static_cast<uint8_t *>(mbuf->data());
if (trackInfo->mHeader) {
@@ -832,7 +838,7 @@
}
}
- status_t err = frame.Read(mExtractor->mReader, data + trackInfo->mHeaderLen);
+ err = frame.Read(mExtractor->mReader, data + trackInfo->mHeaderLen);
if (err == OK
&& mExtractor->mIsWebm
&& trackInfo->mEncrypted) {
diff --git a/media/extractors/mkv/NOTICE b/media/module/extractors/mkv/NOTICE
similarity index 100%
rename from media/extractors/mkv/NOTICE
rename to media/module/extractors/mkv/NOTICE
diff --git a/media/extractors/mkv/exports.lds b/media/module/extractors/mkv/exports.lds
similarity index 100%
rename from media/extractors/mkv/exports.lds
rename to media/module/extractors/mkv/exports.lds
diff --git a/media/extractors/mkv/include/MatroskaExtractor.h b/media/module/extractors/mkv/include/MatroskaExtractor.h
similarity index 100%
rename from media/extractors/mkv/include/MatroskaExtractor.h
rename to media/module/extractors/mkv/include/MatroskaExtractor.h
diff --git a/media/extractors/mp3/Android.bp b/media/module/extractors/mp3/Android.bp
similarity index 100%
rename from media/extractors/mp3/Android.bp
rename to media/module/extractors/mp3/Android.bp
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/module/extractors/mp3/MP3Extractor.cpp
similarity index 99%
rename from media/extractors/mp3/MP3Extractor.cpp
rename to media/module/extractors/mp3/MP3Extractor.cpp
index 248a39c..328b790 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/module/extractors/mp3/MP3Extractor.cpp
@@ -521,9 +521,9 @@
mSamplesRead = 0;
}
- MediaBufferHelper *buffer;
+ MediaBufferHelper *buffer = nullptr;
status_t err = mBufferGroup->acquire_buffer(&buffer);
- if (err != OK) {
+ if (err != OK || buffer == nullptr) {
return AMEDIA_ERROR_UNKNOWN;
}
diff --git a/media/extractors/mp3/VBRISeeker.cpp b/media/module/extractors/mp3/VBRISeeker.cpp
similarity index 100%
rename from media/extractors/mp3/VBRISeeker.cpp
rename to media/module/extractors/mp3/VBRISeeker.cpp
diff --git a/media/extractors/mp3/XINGSeeker.cpp b/media/module/extractors/mp3/XINGSeeker.cpp
similarity index 100%
rename from media/extractors/mp3/XINGSeeker.cpp
rename to media/module/extractors/mp3/XINGSeeker.cpp
diff --git a/media/extractors/mp3/exports.lds b/media/module/extractors/mp3/exports.lds
similarity index 100%
rename from media/extractors/mp3/exports.lds
rename to media/module/extractors/mp3/exports.lds
diff --git a/media/extractors/mp3/include/MP3Extractor.h b/media/module/extractors/mp3/include/MP3Extractor.h
similarity index 100%
rename from media/extractors/mp3/include/MP3Extractor.h
rename to media/module/extractors/mp3/include/MP3Extractor.h
diff --git a/media/extractors/mp3/include/MP3Seeker.h b/media/module/extractors/mp3/include/MP3Seeker.h
similarity index 100%
rename from media/extractors/mp3/include/MP3Seeker.h
rename to media/module/extractors/mp3/include/MP3Seeker.h
diff --git a/media/extractors/mp3/include/VBRISeeker.h b/media/module/extractors/mp3/include/VBRISeeker.h
similarity index 100%
rename from media/extractors/mp3/include/VBRISeeker.h
rename to media/module/extractors/mp3/include/VBRISeeker.h
diff --git a/media/extractors/mp3/include/XINGSeeker.h b/media/module/extractors/mp3/include/XINGSeeker.h
similarity index 100%
rename from media/extractors/mp3/include/XINGSeeker.h
rename to media/module/extractors/mp3/include/XINGSeeker.h
diff --git a/media/extractors/mp4/AC4Parser.cpp b/media/module/extractors/mp4/AC4Parser.cpp
similarity index 100%
rename from media/extractors/mp4/AC4Parser.cpp
rename to media/module/extractors/mp4/AC4Parser.cpp
diff --git a/media/extractors/mp4/Android.bp b/media/module/extractors/mp4/Android.bp
similarity index 100%
rename from media/extractors/mp4/Android.bp
rename to media/module/extractors/mp4/Android.bp
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/module/extractors/mp4/ItemTable.cpp
similarity index 100%
rename from media/extractors/mp4/ItemTable.cpp
rename to media/module/extractors/mp4/ItemTable.cpp
diff --git a/media/extractors/mp4/MODULE_LICENSE_APACHE2 b/media/module/extractors/mp4/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/mp4/MODULE_LICENSE_APACHE2
rename to media/module/extractors/mp4/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
similarity index 99%
rename from media/extractors/mp4/MPEG4Extractor.cpp
rename to media/module/extractors/mp4/MPEG4Extractor.cpp
index fb9dfb4..1d88785 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -34,7 +34,7 @@
#include "SampleTable.h"
#include "ItemTable.h"
-#include <ESDS.h>
+#include <media/esds/ESDS.h>
#include <ID3.h>
#include <media/stagefright/DataSourceBase.h>
#include <media/ExtractorUtils.h>
@@ -394,6 +394,15 @@
return MEDIA_MIMETYPE_AUDIO_MPEGH_MHA1;
case FOURCC("mhm1"):
return MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1;
+ case FOURCC("dtsc"):
+ return MEDIA_MIMETYPE_AUDIO_DTS;
+ case FOURCC("dtse"):
+ case FOURCC("dtsh"):
+ return MEDIA_MIMETYPE_AUDIO_DTS_HD;
+ case FOURCC("dtsl"):
+ return MEDIA_MIMETYPE_AUDIO_DTS_HD_MA;
+ case FOURCC("dtsx"):
+ return MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2;
default:
ALOGW("Unknown fourcc: %c%c%c%c",
(fourcc >> 24) & 0xff,
@@ -1804,6 +1813,11 @@
case 0x6D730055: // "ms U" mp3 audio
case FOURCC("mha1"):
case FOURCC("mhm1"):
+ case FOURCC("dtsc"):
+ case FOURCC("dtse"):
+ case FOURCC("dtsh"):
+ case FOURCC("dtsl"):
+ case FOURCC("dtsx"):
{
if (mIsQT && depth >= 1 && mPath[depth - 1] == FOURCC("wave")) {
@@ -1969,26 +1983,8 @@
}
if (chunk_type == FOURCC("fLaC")) {
-
- // From https://github.com/xiph/flac/blob/master/doc/isoflac.txt
- // 4 for mime, 4 for blockType and BlockLen, 34 for metadata
- uint8_t flacInfo[4 + 4 + 34];
- // skipping dFla, version
- data_offset += sizeof(buffer) + 12;
- size_t flacOffset = 4;
- // Add flaC header mime type to CSD
- strncpy((char *)flacInfo, "fLaC", 4);
- if (mDataSource->readAt(
- data_offset, flacInfo + flacOffset, sizeof(flacInfo) - flacOffset) <
- (ssize_t)sizeof(flacInfo) - flacOffset) {
- return ERROR_IO;
- }
- data_offset += sizeof(flacInfo) - flacOffset;
-
- AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0, flacInfo,
- sizeof(flacInfo));
+ data_offset += sizeof(buffer);
*offset = data_offset;
- CHECK_EQ(*offset, stop_offset);
}
while (*offset < stop_offset) {
@@ -2521,6 +2517,35 @@
break;
}
+ case FOURCC("dfLa"):
+ {
+ *offset += chunk_size;
+
+ // From https://github.com/xiph/flac/blob/master/doc/isoflac.txt
+ // 4 for mediaType, 4 for blockType and BlockLen, 34 for metadata
+ uint8_t flacInfo[4 + 4 + 34];
+
+ if (chunk_data_size != sizeof(flacInfo)) {
+ return ERROR_MALFORMED;
+ }
+
+ data_offset += 4;
+ size_t flacOffset = 4;
+ // Add flaC header mediaType to CSD
+ strncpy((char *)flacInfo, "fLaC", 4);
+
+ ssize_t bytesToRead = sizeof(flacInfo) - flacOffset;
+ if (mDataSource->readAt(
+ data_offset, flacInfo + flacOffset, bytesToRead) < bytesToRead) {
+ return ERROR_IO;
+ }
+
+ data_offset += bytesToRead;
+ AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0, flacInfo,
+ sizeof(flacInfo));
+ break;
+ }
+
case FOURCC("avcC"):
{
*offset += chunk_size;
@@ -6312,7 +6337,7 @@
err = mBufferGroup->acquire_buffer(&mBuffer);
- if (err != OK) {
+ if (err != OK || mBuffer == nullptr) {
CHECK(mBuffer == NULL);
return AMEDIA_ERROR_UNKNOWN;
}
@@ -6712,7 +6737,7 @@
const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
offset = smpl->offset;
size = smpl->size;
- cts = mCurrentTime + smpl->compositionOffset;
+ cts = (int64_t)mCurrentTime + (int64_t)smpl->compositionOffset;
if (mElstInitialEmptyEditTicks > 0) {
cts += mElstInitialEmptyEditTicks;
diff --git a/media/extractors/mp4/NOTICE b/media/module/extractors/mp4/NOTICE
similarity index 100%
rename from media/extractors/mp4/NOTICE
rename to media/module/extractors/mp4/NOTICE
diff --git a/media/extractors/mp4/SampleIterator.cpp b/media/module/extractors/mp4/SampleIterator.cpp
similarity index 100%
rename from media/extractors/mp4/SampleIterator.cpp
rename to media/module/extractors/mp4/SampleIterator.cpp
diff --git a/media/extractors/mp4/SampleTable.cpp b/media/module/extractors/mp4/SampleTable.cpp
similarity index 100%
rename from media/extractors/mp4/SampleTable.cpp
rename to media/module/extractors/mp4/SampleTable.cpp
diff --git a/media/extractors/mp4/exports.lds b/media/module/extractors/mp4/exports.lds
similarity index 100%
rename from media/extractors/mp4/exports.lds
rename to media/module/extractors/mp4/exports.lds
diff --git a/media/extractors/mp4/include/AC4Parser.h b/media/module/extractors/mp4/include/AC4Parser.h
similarity index 100%
rename from media/extractors/mp4/include/AC4Parser.h
rename to media/module/extractors/mp4/include/AC4Parser.h
diff --git a/media/extractors/mp4/include/ItemTable.h b/media/module/extractors/mp4/include/ItemTable.h
similarity index 100%
rename from media/extractors/mp4/include/ItemTable.h
rename to media/module/extractors/mp4/include/ItemTable.h
diff --git a/media/extractors/mp4/include/MPEG4Extractor.h b/media/module/extractors/mp4/include/MPEG4Extractor.h
similarity index 100%
rename from media/extractors/mp4/include/MPEG4Extractor.h
rename to media/module/extractors/mp4/include/MPEG4Extractor.h
diff --git a/media/extractors/mp4/include/SampleIterator.h b/media/module/extractors/mp4/include/SampleIterator.h
similarity index 100%
rename from media/extractors/mp4/include/SampleIterator.h
rename to media/module/extractors/mp4/include/SampleIterator.h
diff --git a/media/extractors/mp4/include/SampleTable.h b/media/module/extractors/mp4/include/SampleTable.h
similarity index 100%
rename from media/extractors/mp4/include/SampleTable.h
rename to media/module/extractors/mp4/include/SampleTable.h
diff --git a/media/extractors/mpeg2/Android.bp b/media/module/extractors/mpeg2/Android.bp
similarity index 100%
rename from media/extractors/mpeg2/Android.bp
rename to media/module/extractors/mpeg2/Android.bp
diff --git a/media/extractors/mpeg2/ExtractorBundle.cpp b/media/module/extractors/mpeg2/ExtractorBundle.cpp
similarity index 100%
rename from media/extractors/mpeg2/ExtractorBundle.cpp
rename to media/module/extractors/mpeg2/ExtractorBundle.cpp
diff --git a/media/extractors/mpeg2/MODULE_LICENSE_APACHE2 b/media/module/extractors/mpeg2/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/mpeg2/MODULE_LICENSE_APACHE2
rename to media/module/extractors/mpeg2/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/module/extractors/mpeg2/MPEG2PSExtractor.cpp
similarity index 97%
rename from media/extractors/mpeg2/MPEG2PSExtractor.cpp
rename to media/module/extractors/mpeg2/MPEG2PSExtractor.cpp
index afd28ef..44c8937 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/module/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -699,11 +699,26 @@
}
}
- MediaBufferBase *mbuf;
- mSource->read(&mbuf, (MediaTrack::ReadOptions*) options);
+ MediaBufferBase *mbuf = nullptr;
+ status_t err_read = mSource->read(&mbuf, (MediaTrack::ReadOptions*) options);
+ if (mbuf == nullptr) {
+ ALOGE("Track::read: null buffer read from source");
+ return AMEDIA_ERROR_UNKNOWN;
+ }
+ if (err_read != OK) {
+ ALOGE("Track::read: no buffer read from source");
+ mbuf->release();
+ return AMEDIA_ERROR_UNKNOWN;
+ }
+
size_t length = mbuf->range_length();
- MediaBufferHelper *outbuf;
- mBufferGroup->acquire_buffer(&outbuf, false, length);
+ MediaBufferHelper *outbuf = nullptr;
+ status_t err = mBufferGroup->acquire_buffer(&outbuf, false, length);
+ if (err != OK || outbuf == nullptr) {
+ ALOGE("Track::read: no buffer");
+ mbuf->release();
+ return AMEDIA_ERROR_UNKNOWN;
+ }
memcpy(outbuf->data(), mbuf->data(), length);
outbuf->set_range(0, length);
*buffer = outbuf;
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/module/extractors/mpeg2/MPEG2TSExtractor.cpp
similarity index 97%
rename from media/extractors/mpeg2/MPEG2TSExtractor.cpp
rename to media/module/extractors/mpeg2/MPEG2TSExtractor.cpp
index 9a3cd92..736b817 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/module/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -182,11 +182,26 @@
return AMEDIA_ERROR_END_OF_STREAM;
}
- MediaBufferBase *mbuf;
- mImpl->read(&mbuf, (MediaTrack::ReadOptions*) options);
+ MediaBufferBase *mbuf = nullptr;
+ status_t err_read = mImpl->read(&mbuf, (MediaTrack::ReadOptions*) options);
+ if (mbuf == nullptr) {
+ ALOGE("Track::read: null buffer read from source");
+ return AMEDIA_ERROR_UNKNOWN;
+ }
+ if (err_read != OK) {
+ ALOGE("Track::read: no buffer read from source");
+ mbuf->release();
+ return AMEDIA_ERROR_UNKNOWN;
+ }
+
size_t length = mbuf->range_length();
- MediaBufferHelper *outbuf;
- mBufferGroup->acquire_buffer(&outbuf, false, length);
+ MediaBufferHelper *outbuf = nullptr;
+ status_t err = mBufferGroup->acquire_buffer(&outbuf, false, length);
+ if (err != OK || outbuf == nullptr) {
+ ALOGE("read: no buffer");
+ mbuf->release();
+ return AMEDIA_ERROR_UNKNOWN;
+ }
memcpy(outbuf->data(), mbuf->data(), length);
outbuf->set_range(0, length);
*out = outbuf;
diff --git a/media/extractors/mpeg2/NOTICE b/media/module/extractors/mpeg2/NOTICE
similarity index 100%
rename from media/extractors/mpeg2/NOTICE
rename to media/module/extractors/mpeg2/NOTICE
diff --git a/media/extractors/mpeg2/exports.lds b/media/module/extractors/mpeg2/exports.lds
similarity index 100%
rename from media/extractors/mpeg2/exports.lds
rename to media/module/extractors/mpeg2/exports.lds
diff --git a/media/extractors/mpeg2/include/MPEG2PSExtractor.h b/media/module/extractors/mpeg2/include/MPEG2PSExtractor.h
similarity index 100%
rename from media/extractors/mpeg2/include/MPEG2PSExtractor.h
rename to media/module/extractors/mpeg2/include/MPEG2PSExtractor.h
diff --git a/media/extractors/mpeg2/include/MPEG2TSExtractor.h b/media/module/extractors/mpeg2/include/MPEG2TSExtractor.h
similarity index 100%
rename from media/extractors/mpeg2/include/MPEG2TSExtractor.h
rename to media/module/extractors/mpeg2/include/MPEG2TSExtractor.h
diff --git a/media/extractors/ogg/Android.bp b/media/module/extractors/ogg/Android.bp
similarity index 100%
rename from media/extractors/ogg/Android.bp
rename to media/module/extractors/ogg/Android.bp
diff --git a/media/extractors/ogg/MODULE_LICENSE_APACHE2 b/media/module/extractors/ogg/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/ogg/MODULE_LICENSE_APACHE2
rename to media/module/extractors/ogg/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/ogg/NOTICE b/media/module/extractors/ogg/NOTICE
similarity index 100%
rename from media/extractors/ogg/NOTICE
rename to media/module/extractors/ogg/NOTICE
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/module/extractors/ogg/OggExtractor.cpp
similarity index 90%
rename from media/extractors/ogg/OggExtractor.cpp
rename to media/module/extractors/ogg/OggExtractor.cpp
index eb2246d..4c106b2 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/module/extractors/ogg/OggExtractor.cpp
@@ -34,6 +34,9 @@
#include <system/audio.h>
#include <utils/String8.h>
+#include <inttypes.h>
+#include <stdint.h>
+
extern "C" {
#include <Tremolo/codec_internal.h>
@@ -346,66 +349,118 @@
off64_t startOffset, off64_t *pageOffset) {
*pageOffset = startOffset;
- for (;;) {
- char signature[4];
- ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
+ // balance between larger reads and reducing how much we over-read.
+ const int FIND_BUF_SIZE = 2048;
+ const int lenOggS = strlen("OggS");
+ while(1) {
- if (n < 4) {
+ // work with big buffers to amortize readAt() costs
+ char signatureBuffer[FIND_BUF_SIZE];
+ ssize_t n = mSource->readAt(*pageOffset, &signatureBuffer, sizeof(signatureBuffer));
+
+ if (n < lenOggS) {
*pageOffset = 0;
-
return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
}
- if (!memcmp(signature, "OggS", 4)) {
- if (*pageOffset > startOffset) {
- ALOGV("skipped %lld bytes of junk to reach next frame",
- (long long)(*pageOffset - startOffset));
- }
-
- return OK;
- }
-
- // see how far ahead to skip; avoid some fruitless comparisons
- unsigned int i;
- for (i = 1; i < 4 ; i++) {
- if (signature[i] == 'O')
+ for(int i = 0; i < n - (lenOggS - 1) ; i++) {
+ // fast scan for 1st character in a signature
+ char *p = (char *)memchr(&signatureBuffer[i], 'O', n - (lenOggS - 1) - i);
+ if (p == NULL) {
+ // no signature start in the rest of this buffer.
break;
+ }
+ int jump = (p-&signatureBuffer[i]);
+ i += jump;
+ if (memcmp("OggS", &signatureBuffer[i], lenOggS) == 0) {
+ *pageOffset += i;
+ if (*pageOffset > startOffset) {
+ ALOGD("skipped %" PRIu64 " bytes of junk to reach next frame",
+ (*pageOffset - startOffset));
+ }
+ return OK;
+ }
}
- *pageOffset += i;
+
+ // on to next block. buffer didn't end with "OggS", but could end with "Ogg".
+ // overlap enough to detect this. n >= lenOggS, so this always advances.
+ *pageOffset += n - (lenOggS - 1);
}
+ return (status_t)ERROR_END_OF_STREAM;
}
// Given the offset of the "current" page, find the page immediately preceding
// it (if any) and return its granule position.
// To do this we back up from the "current" page's offset until we find any
// page preceding it and then scan forward to just before the current page.
+//
status_t MyOggExtractor::findPrevGranulePosition(
off64_t pageOffset, uint64_t *granulePos) {
*granulePos = 0;
- off64_t prevPageOffset = 0;
- off64_t prevGuess = pageOffset;
- for (;;) {
- if (prevGuess >= 5000) {
- prevGuess -= 5000;
+ const int FIND_BUF_SIZE = 2048;
+ const int lenOggS = strlen("OggS");
+
+ if (pageOffset == 0) {
+ ALOGV("no page before the first page");
+ return UNKNOWN_ERROR;
+ }
+
+ off64_t prevPageOffset = pageOffset;
+
+ // we start our search on the byte immediately in front of pageOffset
+ // which could mean "O" immediately before and "ggS" starting at pageOffset
+ //
+ // if there was an "OggS" at pageOffset, we'll have scanned a few extra bytes
+ // but if pageOffset was chosen by a seek operation, we don't know that it
+ // reflects the beginning of a page. By choosing to scan 3 possibly unneeded
+ // bytes at the start we cover both cases.
+ //
+ off64_t firstAfter = pageOffset + lenOggS - 1; // NOT within our buffer
+ off64_t nextOffset = pageOffset;
+
+ while(prevPageOffset == pageOffset) {
+ // work with big buffers to amortize readAt() costs
+ char signatureBuffer[FIND_BUF_SIZE];
+
+ ssize_t desired = sizeof(signatureBuffer);
+ if (firstAfter >= desired) {
+ nextOffset = firstAfter - desired;
} else {
- prevGuess = 0;
+ nextOffset = 0;
+ desired = firstAfter;
}
+ ssize_t n = mSource->readAt(nextOffset, &signatureBuffer, desired);
- ALOGV("backing up %lld bytes", (long long)(pageOffset - prevGuess));
-
- status_t err = findNextPage(prevGuess, &prevPageOffset);
- if (err == ERROR_END_OF_STREAM) {
- // We are at the last page and didn't back off enough;
- // back off 5000 bytes more and try again.
- continue;
- } else if (err != OK) {
- return err;
- }
-
- if (prevPageOffset < pageOffset || prevGuess == 0) {
+ if (n < lenOggS) {
+ ALOGD("short read, get out");
break;
}
+
+ // work backwards
+ // loop control ok for n >= 0
+ for(int i = n - lenOggS; i >= 0 ; i--) {
+ // fast scan for 1st character in the signature
+ char *p = (char *)memrchr(&signatureBuffer[0], 'O', i);
+ if (p == NULL) {
+ // no signature start in the rest of this buffer.
+ break;
+ }
+ i = (p-&signatureBuffer[0]);
+ // loop start chosen to ensure we will always have lenOggS bytes
+ if (memcmp("OggS", &signatureBuffer[i], lenOggS) == 0) {
+ prevPageOffset = nextOffset + i;
+ break;
+ }
+ }
+
+ // back up for next read; make sure we catch overlaps
+ if (nextOffset == 0) {
+ // can't back up any further
+ break;
+ }
+ // current buffer might start with "ggS", include those bytes in the next iteration
+ firstAfter = nextOffset + lenOggS - 1;
}
if (prevPageOffset == pageOffset) {
@@ -413,8 +468,8 @@
return UNKNOWN_ERROR;
}
- ALOGV("prevPageOffset at %lld, pageOffset at %lld",
- (long long)prevPageOffset, (long long)pageOffset);
+ ALOGV("prevPageOffset at %" PRIu64 ", pageOffset at %" PRIu64,
+ prevPageOffset, pageOffset);
uint8_t flag = 0;
for (;;) {
Page prevPage;
@@ -790,7 +845,8 @@
}
MediaBufferHelper *tmp;
if (mBufferGroup) {
- mBufferGroup->acquire_buffer(&tmp, false, fullSize);
+ // ignore return code here. instead, check tmp below.
+ (void) mBufferGroup->acquire_buffer(&tmp, false, fullSize);
ALOGV("acquired buffer %p from group", tmp);
} else {
tmp = new StandAloneMediaBuffer(fullSize);
@@ -924,13 +980,16 @@
status_t MyOggExtractor::init() {
AMediaFormat_setString(mMeta, AMEDIAFORMAT_KEY_MIME, mMimeType);
- media_status_t err;
- MediaBufferHelper *packet;
for (size_t i = 0; i < mNumHeaders; ++i) {
+ media_status_t err;
+ MediaBufferHelper *packet = nullptr;
// ignore timestamp for configuration packets
if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != AMEDIA_OK) {
return err;
}
+ if (packet == nullptr) {
+ return AMEDIA_ERROR_UNKNOWN;
+ }
ALOGV("read packet of size %zu\n", packet->range_length());
err = verifyHeader(packet, /* type = */ i * 2 + 1);
packet->release();
@@ -989,16 +1048,21 @@
size_t numerator = mTableOfContents.size();
if (numerator > kMaxNumTOCEntries) {
- size_t denom = numerator - kMaxNumTOCEntries;
+ Vector<TOCEntry> maxTOC;
+ maxTOC.setCapacity(kMaxNumTOCEntries);
+ size_t denom = numerator - kMaxNumTOCEntries;
size_t accum = 0;
- for (ssize_t i = mTableOfContents.size(); i > 0; --i) {
+ for (ssize_t i = 0; i < mTableOfContents.size(); i++) {
accum += denom;
if (accum >= numerator) {
- mTableOfContents.removeAt(i);
accum -= numerator;
+ } else {
+ maxTOC.push(mTableOfContents.itemAt(i));
}
}
+
+ mTableOfContents = maxTOC;
}
}
diff --git a/media/extractors/ogg/exports.lds b/media/module/extractors/ogg/exports.lds
similarity index 100%
rename from media/extractors/ogg/exports.lds
rename to media/module/extractors/ogg/exports.lds
diff --git a/media/extractors/ogg/include/OggExtractor.h b/media/module/extractors/ogg/include/OggExtractor.h
similarity index 100%
rename from media/extractors/ogg/include/OggExtractor.h
rename to media/module/extractors/ogg/include/OggExtractor.h
diff --git a/media/extractors/tests/Android.bp b/media/module/extractors/tests/Android.bp
similarity index 93%
rename from media/extractors/tests/Android.bp
rename to media/module/extractors/tests/Android.bp
index 3c3bbdc..f5eadbd 100644
--- a/media/extractors/tests/Android.bp
+++ b/media/module/extractors/tests/Android.bp
@@ -55,7 +55,7 @@
"libmedia_midiiowrapper",
"libsonivoxwithoutjet",
"libvorbisidec",
- "libwebm",
+ "libwebm_mkvparser",
"libFLAC",
],
@@ -100,4 +100,7 @@
"signed-integer-overflow",
],
},
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.4.zip?unzip=true",
+ ],
}
diff --git a/media/extractors/tests/AndroidTest.xml b/media/module/extractors/tests/AndroidTest.xml
similarity index 100%
rename from media/extractors/tests/AndroidTest.xml
rename to media/module/extractors/tests/AndroidTest.xml
diff --git a/media/extractors/tests/ExtractorUnitTest.cpp b/media/module/extractors/tests/ExtractorUnitTest.cpp
similarity index 100%
rename from media/extractors/tests/ExtractorUnitTest.cpp
rename to media/module/extractors/tests/ExtractorUnitTest.cpp
diff --git a/media/extractors/tests/ExtractorUnitTestEnvironment.h b/media/module/extractors/tests/ExtractorUnitTestEnvironment.h
similarity index 100%
rename from media/extractors/tests/ExtractorUnitTestEnvironment.h
rename to media/module/extractors/tests/ExtractorUnitTestEnvironment.h
diff --git a/media/extractors/tests/README.md b/media/module/extractors/tests/README.md
similarity index 100%
rename from media/extractors/tests/README.md
rename to media/module/extractors/tests/README.md
diff --git a/media/extractors/wav/Android.bp b/media/module/extractors/wav/Android.bp
similarity index 100%
rename from media/extractors/wav/Android.bp
rename to media/module/extractors/wav/Android.bp
diff --git a/media/extractors/wav/MODULE_LICENSE_APACHE2 b/media/module/extractors/wav/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/wav/MODULE_LICENSE_APACHE2
rename to media/module/extractors/wav/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/wav/NOTICE b/media/module/extractors/wav/NOTICE
similarity index 100%
rename from media/extractors/wav/NOTICE
rename to media/module/extractors/wav/NOTICE
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/module/extractors/wav/WAVExtractor.cpp
similarity index 98%
rename from media/extractors/wav/WAVExtractor.cpp
rename to media/module/extractors/wav/WAVExtractor.cpp
index 9e94587..9c3bac6 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/module/extractors/wav/WAVExtractor.cpp
@@ -459,11 +459,15 @@
mCurrentPos = pos + mOffset;
}
- MediaBufferHelper *buffer;
+ MediaBufferHelper *buffer = nullptr;
media_status_t err = mBufferGroup->acquire_buffer(&buffer);
if (err != OK) {
return err;
}
+ if (buffer == nullptr) {
+ ALOGE("acquire_buffer OK, but no buffer");
+ return AMEDIA_ERROR_UNKNOWN;
+ }
// maxBytesToRead may be reduced so that in-place data conversion will fit in buffer size.
const size_t bufferSize = std::min(buffer->size(), kMaxFrameSize);
diff --git a/media/extractors/wav/exports.lds b/media/module/extractors/wav/exports.lds
similarity index 100%
rename from media/extractors/wav/exports.lds
rename to media/module/extractors/wav/exports.lds
diff --git a/media/extractors/wav/include/WAVExtractor.h b/media/module/extractors/wav/include/WAVExtractor.h
similarity index 100%
rename from media/extractors/wav/include/WAVExtractor.h
rename to media/module/extractors/wav/include/WAVExtractor.h
diff --git a/media/libstagefright/foundation/AAtomizer.cpp b/media/module/foundation/AAtomizer.cpp
similarity index 100%
rename from media/libstagefright/foundation/AAtomizer.cpp
rename to media/module/foundation/AAtomizer.cpp
diff --git a/media/libstagefright/foundation/ABitReader.cpp b/media/module/foundation/ABitReader.cpp
similarity index 100%
rename from media/libstagefright/foundation/ABitReader.cpp
rename to media/module/foundation/ABitReader.cpp
diff --git a/media/libstagefright/foundation/ABuffer.cpp b/media/module/foundation/ABuffer.cpp
similarity index 100%
rename from media/libstagefright/foundation/ABuffer.cpp
rename to media/module/foundation/ABuffer.cpp
diff --git a/media/libstagefright/foundation/ADebug.cpp b/media/module/foundation/ADebug.cpp
similarity index 100%
rename from media/libstagefright/foundation/ADebug.cpp
rename to media/module/foundation/ADebug.cpp
diff --git a/media/libstagefright/foundation/AHandler.cpp b/media/module/foundation/AHandler.cpp
similarity index 100%
rename from media/libstagefright/foundation/AHandler.cpp
rename to media/module/foundation/AHandler.cpp
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/module/foundation/ALooper.cpp
similarity index 77%
rename from media/libstagefright/foundation/ALooper.cpp
rename to media/module/foundation/ALooper.cpp
index a276722..61bac02 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/module/foundation/ALooper.cpp
@@ -69,6 +69,10 @@
return systemTime(SYSTEM_TIME_MONOTONIC) / 1000LL;
}
+int64_t ALooper::getNowUs() {
+ return GetNowUs();
+}
+
ALooper::ALooper()
: mRunningLocally(false) {
// clean up stale AHandlers. Doing it here instead of in the destructor avoids
@@ -170,11 +174,11 @@
int64_t whenUs;
if (delayUs > 0) {
- int64_t nowUs = GetNowUs();
+ int64_t nowUs = getNowUs();
whenUs = (delayUs > INT64_MAX - nowUs ? INT64_MAX : nowUs + delayUs);
} else {
- whenUs = GetNowUs();
+ whenUs = getNowUs();
}
List<Event>::iterator it = mEventQueue.begin();
@@ -185,6 +189,7 @@
Event event;
event.mWhenUs = whenUs;
event.mMessage = msg;
+ event.mToken = nullptr;
if (it == mEventQueue.begin()) {
mQueueChangedCondition.signal();
@@ -193,7 +198,57 @@
mEventQueue.insert(it, event);
}
+status_t ALooper::postUnique(const sp<AMessage> &msg, const sp<RefBase> &token, int64_t delayUs) {
+ if (token == nullptr) {
+ return -EINVAL;
+ }
+ Mutex::Autolock autoLock(mLock);
+
+ int64_t whenUs;
+ if (delayUs > 0) {
+ int64_t nowUs = getNowUs();
+ whenUs = (delayUs > INT64_MAX - nowUs ? INT64_MAX : nowUs + delayUs);
+ } else {
+ whenUs = getNowUs();
+ }
+
+ // We only need to wake the loop up if we're rescheduling to the earliest event in the queue.
+ // This needs to be checked now, before we reschedule the message, in case this message is
+ // already at the beginning of the queue.
+ bool shouldAwakeLoop = mEventQueue.empty() || whenUs < mEventQueue.begin()->mWhenUs;
+
+ // Erase any previously-posted event with this token.
+ for (auto i = mEventQueue.begin(); i != mEventQueue.end();) {
+ if (i->mToken == token) {
+ i = mEventQueue.erase(i);
+ } else {
+ ++i;
+ }
+ }
+
+ // Find the insertion point for the rescheduled message.
+ List<Event>::iterator i = mEventQueue.begin();
+ while (i != mEventQueue.end() && i->mWhenUs <= whenUs) {
+ ++i;
+ }
+
+ Event event;
+ event.mWhenUs = whenUs;
+ event.mMessage = msg;
+ event.mToken = token;
+ mEventQueue.insert(i, event);
+
+ // If we rescheduled the event to be earlier than the first event, then we need to wake up the
+ // looper earlier than it was previously scheduled to be woken up. Otherwise, it can sleep until
+ // the previous wake-up time and then go to sleep again if needed.
+ if (shouldAwakeLoop){
+ mQueueChangedCondition.signal();
+ }
+ return OK;
+}
+
bool ALooper::loop() {
+
Event event;
{
@@ -206,7 +261,7 @@
return true;
}
int64_t whenUs = (*mEventQueue.begin()).mWhenUs;
- int64_t nowUs = GetNowUs();
+ int64_t nowUs = getNowUs();
if (whenUs > nowUs) {
int64_t delayUs = whenUs - nowUs;
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/module/foundation/ALooperRoster.cpp
similarity index 100%
rename from media/libstagefright/foundation/ALooperRoster.cpp
rename to media/module/foundation/ALooperRoster.cpp
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/module/foundation/AMessage.cpp
similarity index 98%
rename from media/libstagefright/foundation/AMessage.cpp
rename to media/module/foundation/AMessage.cpp
index 5c99cc9..b61dc47 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/module/foundation/AMessage.cpp
@@ -430,6 +430,17 @@
return OK;
}
+status_t AMessage::postUnique(const sp<RefBase> &token, int64_t delayUs) {
+ sp<ALooper> looper = mLooper.promote();
+ if (looper == NULL) {
+ ALOGW("failed to post message as target looper for handler %d is gone.",
+ mTarget);
+ return -ENOENT;
+ }
+
+ return looper->postUnique(this, token, delayUs);
+}
+
status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
sp<ALooper> looper = mLooper.promote();
if (looper == NULL) {
diff --git a/media/libstagefright/foundation/AString.cpp b/media/module/foundation/AString.cpp
similarity index 100%
rename from media/libstagefright/foundation/AString.cpp
rename to media/module/foundation/AString.cpp
diff --git a/media/libstagefright/foundation/AStringUtils.cpp b/media/module/foundation/AStringUtils.cpp
similarity index 100%
rename from media/libstagefright/foundation/AStringUtils.cpp
rename to media/module/foundation/AStringUtils.cpp
diff --git a/media/libstagefright/foundation/Android.bp b/media/module/foundation/Android.bp
similarity index 100%
rename from media/libstagefright/foundation/Android.bp
rename to media/module/foundation/Android.bp
diff --git a/media/libstagefright/foundation/AudioPresentationInfo.cpp b/media/module/foundation/AudioPresentationInfo.cpp
similarity index 100%
rename from media/libstagefright/foundation/AudioPresentationInfo.cpp
rename to media/module/foundation/AudioPresentationInfo.cpp
diff --git a/media/libstagefright/foundation/ByteUtils.cpp b/media/module/foundation/ByteUtils.cpp
similarity index 100%
rename from media/libstagefright/foundation/ByteUtils.cpp
rename to media/module/foundation/ByteUtils.cpp
diff --git a/media/libstagefright/foundation/ColorUtils.cpp b/media/module/foundation/ColorUtils.cpp
similarity index 100%
rename from media/libstagefright/foundation/ColorUtils.cpp
rename to media/module/foundation/ColorUtils.cpp
diff --git a/media/libstagefright/foundation/ColorUtils_fill.cpp b/media/module/foundation/ColorUtils_fill.cpp
similarity index 100%
rename from media/libstagefright/foundation/ColorUtils_fill.cpp
rename to media/module/foundation/ColorUtils_fill.cpp
diff --git a/media/libstagefright/foundation/ColorUtils_ndk.cpp b/media/module/foundation/ColorUtils_ndk.cpp
similarity index 100%
rename from media/libstagefright/foundation/ColorUtils_ndk.cpp
rename to media/module/foundation/ColorUtils_ndk.cpp
diff --git a/media/libstagefright/foundation/FoundationUtils.cpp b/media/module/foundation/FoundationUtils.cpp
similarity index 100%
rename from media/libstagefright/foundation/FoundationUtils.cpp
rename to media/module/foundation/FoundationUtils.cpp
diff --git a/media/libstagefright/foundation/MODULE_LICENSE_APACHE2 b/media/module/foundation/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/foundation/MODULE_LICENSE_APACHE2
rename to media/module/foundation/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/foundation/MediaBuffer.cpp b/media/module/foundation/MediaBuffer.cpp
similarity index 100%
rename from media/libstagefright/foundation/MediaBuffer.cpp
rename to media/module/foundation/MediaBuffer.cpp
diff --git a/media/libstagefright/foundation/MediaBufferBase.cpp b/media/module/foundation/MediaBufferBase.cpp
similarity index 100%
rename from media/libstagefright/foundation/MediaBufferBase.cpp
rename to media/module/foundation/MediaBufferBase.cpp
diff --git a/media/libstagefright/foundation/MediaBufferGroup.cpp b/media/module/foundation/MediaBufferGroup.cpp
similarity index 100%
rename from media/libstagefright/foundation/MediaBufferGroup.cpp
rename to media/module/foundation/MediaBufferGroup.cpp
diff --git a/media/libstagefright/foundation/MediaDefs.cpp b/media/module/foundation/MediaDefs.cpp
similarity index 96%
rename from media/libstagefright/foundation/MediaDefs.cpp
rename to media/module/foundation/MediaDefs.cpp
index 5c4ec17..7abab63 100644
--- a/media/libstagefright/foundation/MediaDefs.cpp
+++ b/media/module/foundation/MediaDefs.cpp
@@ -71,7 +71,10 @@
const char *MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM = "audio/x-adpcm-dvi-ima";
const char *MEDIA_MIMETYPE_AUDIO_DTS = "audio/vnd.dts";
const char *MEDIA_MIMETYPE_AUDIO_DTS_HD = "audio/vnd.dts.hd";
+const char *MEDIA_MIMETYPE_AUDIO_DTS_HD_MA = "audio/vnd.dts.hd;profile=dtsma";
const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD = "audio/vnd.dts.uhd";
+const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1 = "audio/vnd.dts.uhd;profile=p1";
+const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2 = "audio/vnd.dts.uhd;profile=p2";
const char *MEDIA_MIMETYPE_AUDIO_EVRC = "audio/evrc";
const char *MEDIA_MIMETYPE_AUDIO_EVRCB = "audio/evrcb";
const char *MEDIA_MIMETYPE_AUDIO_EVRCWB = "audio/evrcwb";
diff --git a/media/libstagefright/foundation/MediaKeys.cpp b/media/module/foundation/MediaKeys.cpp
similarity index 100%
rename from media/libstagefright/foundation/MediaKeys.cpp
rename to media/module/foundation/MediaKeys.cpp
diff --git a/media/libstagefright/foundation/MetaData.cpp b/media/module/foundation/MetaData.cpp
similarity index 100%
rename from media/libstagefright/foundation/MetaData.cpp
rename to media/module/foundation/MetaData.cpp
diff --git a/media/libstagefright/foundation/MetaDataBase.cpp b/media/module/foundation/MetaDataBase.cpp
similarity index 100%
rename from media/libstagefright/foundation/MetaDataBase.cpp
rename to media/module/foundation/MetaDataBase.cpp
diff --git a/media/libstagefright/foundation/NOTICE b/media/module/foundation/NOTICE
similarity index 100%
rename from media/libstagefright/foundation/NOTICE
rename to media/module/foundation/NOTICE
diff --git a/media/libstagefright/foundation/OpusHeader.cpp b/media/module/foundation/OpusHeader.cpp
similarity index 100%
rename from media/libstagefright/foundation/OpusHeader.cpp
rename to media/module/foundation/OpusHeader.cpp
diff --git a/media/libstagefright/foundation/TEST_MAPPING b/media/module/foundation/TEST_MAPPING
similarity index 100%
rename from media/libstagefright/foundation/TEST_MAPPING
rename to media/module/foundation/TEST_MAPPING
diff --git a/media/libstagefright/foundation/avc_utils.cpp b/media/module/foundation/avc_utils.cpp
similarity index 100%
rename from media/libstagefright/foundation/avc_utils.cpp
rename to media/module/foundation/avc_utils.cpp
diff --git a/media/libstagefright/foundation/base64.cpp b/media/module/foundation/base64.cpp
similarity index 100%
rename from media/libstagefright/foundation/base64.cpp
rename to media/module/foundation/base64.cpp
diff --git a/media/libstagefright/foundation/hexdump.cpp b/media/module/foundation/hexdump.cpp
similarity index 100%
rename from media/libstagefright/foundation/hexdump.cpp
rename to media/module/foundation/hexdump.cpp
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AAtomizer.h b/media/module/foundation/include/media/stagefright/foundation/AAtomizer.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AAtomizer.h
rename to media/module/foundation/include/media/stagefright/foundation/AAtomizer.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ABase.h b/media/module/foundation/include/media/stagefright/foundation/ABase.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ABase.h
rename to media/module/foundation/include/media/stagefright/foundation/ABase.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ABitReader.h b/media/module/foundation/include/media/stagefright/foundation/ABitReader.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ABitReader.h
rename to media/module/foundation/include/media/stagefright/foundation/ABitReader.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ABuffer.h b/media/module/foundation/include/media/stagefright/foundation/ABuffer.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ABuffer.h
rename to media/module/foundation/include/media/stagefright/foundation/ABuffer.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h b/media/module/foundation/include/media/stagefright/foundation/AData.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
rename to media/module/foundation/include/media/stagefright/foundation/AData.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h b/media/module/foundation/include/media/stagefright/foundation/ADebug.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h
rename to media/module/foundation/include/media/stagefright/foundation/ADebug.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AHandler.h b/media/module/foundation/include/media/stagefright/foundation/AHandler.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AHandler.h
rename to media/module/foundation/include/media/stagefright/foundation/AHandler.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AHandlerReflector.h b/media/module/foundation/include/media/stagefright/foundation/AHandlerReflector.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AHandlerReflector.h
rename to media/module/foundation/include/media/stagefright/foundation/AHandlerReflector.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ALookup.h b/media/module/foundation/include/media/stagefright/foundation/ALookup.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ALookup.h
rename to media/module/foundation/include/media/stagefright/foundation/ALookup.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ALooper.h b/media/module/foundation/include/media/stagefright/foundation/ALooper.h
similarity index 85%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ALooper.h
rename to media/module/foundation/include/media/stagefright/foundation/ALooper.h
index 09c469b..60bda1f 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/ALooper.h
+++ b/media/module/foundation/include/media/stagefright/foundation/ALooper.h
@@ -59,6 +59,9 @@
}
protected:
+ // overridable by test harness
+ virtual int64_t getNowUs();
+
virtual ~ALooper();
private:
@@ -67,6 +70,7 @@
struct Event {
int64_t mWhenUs;
sp<AMessage> mMessage;
+ sp<RefBase> mToken;
};
Mutex mLock;
@@ -87,9 +91,14 @@
// START --- methods used only by AMessage
- // posts a message on this looper with the given timeout
+ // Posts a message on this looper with the given timeout.
void post(const sp<AMessage> &msg, int64_t delayUs);
+ // Post a message uniquely on this looper with the given timeout.
+ // This method ensures that there is exactly one message with the same token pending posted on
+ // this looper after the call returns. A null token will result in an EINVAL error status.
+ status_t postUnique(const sp<AMessage> &msg, const sp<RefBase> &token, int64_t delayUs);
+
// creates a reply token to be used with this looper
sp<AReplyToken> createReplyToken();
// waits for a response for the reply token. If status is OK, the response
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ALooperRoster.h b/media/module/foundation/include/media/stagefright/foundation/ALooperRoster.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ALooperRoster.h
rename to media/module/foundation/include/media/stagefright/foundation/ALooperRoster.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h b/media/module/foundation/include/media/stagefright/foundation/AMessage.h
similarity index 97%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
rename to media/module/foundation/include/media/stagefright/foundation/AMessage.h
index 960212a..6f73597 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
+++ b/media/module/foundation/include/media/stagefright/foundation/AMessage.h
@@ -141,6 +141,11 @@
status_t post(int64_t delayUs = 0);
+ // Post a message uniquely to its target with the given timeout.
+ // This method ensures that there is exactly one message with the same token posted to its
+ // target after the call returns. A null token will result in an EINVAL error status.
+ status_t postUnique(const sp<RefBase> &token, int64_t delayUs = 0);
+
// Posts the message to its target and waits for a response (or error)
// before returning.
status_t postAndAwaitResponse(sp<AMessage> *response);
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h b/media/module/foundation/include/media/stagefright/foundation/AString.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AString.h
rename to media/module/foundation/include/media/stagefright/foundation/AString.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AStringUtils.h b/media/module/foundation/include/media/stagefright/foundation/AStringUtils.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AStringUtils.h
rename to media/module/foundation/include/media/stagefright/foundation/AStringUtils.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AUtils.h b/media/module/foundation/include/media/stagefright/foundation/AUtils.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AUtils.h
rename to media/module/foundation/include/media/stagefright/foundation/AUtils.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AudioPresentationInfo.h b/media/module/foundation/include/media/stagefright/foundation/AudioPresentationInfo.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AudioPresentationInfo.h
rename to media/module/foundation/include/media/stagefright/foundation/AudioPresentationInfo.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ByteUtils.h b/media/module/foundation/include/media/stagefright/foundation/ByteUtils.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ByteUtils.h
rename to media/module/foundation/include/media/stagefright/foundation/ByteUtils.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ColorUtils.h b/media/module/foundation/include/media/stagefright/foundation/ColorUtils.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ColorUtils.h
rename to media/module/foundation/include/media/stagefright/foundation/ColorUtils.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/FileDescriptor.h b/media/module/foundation/include/media/stagefright/foundation/FileDescriptor.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/FileDescriptor.h
rename to media/module/foundation/include/media/stagefright/foundation/FileDescriptor.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/Flagged.h b/media/module/foundation/include/media/stagefright/foundation/Flagged.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/Flagged.h
rename to media/module/foundation/include/media/stagefright/foundation/Flagged.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h b/media/module/foundation/include/media/stagefright/foundation/MediaDefs.h
similarity index 97%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
rename to media/module/foundation/include/media/stagefright/foundation/MediaDefs.h
index fb8c299..05ee7fc 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
+++ b/media/module/foundation/include/media/stagefright/foundation/MediaDefs.h
@@ -73,7 +73,10 @@
extern const char *MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM;
extern const char *MEDIA_MIMETYPE_AUDIO_DTS;
extern const char *MEDIA_MIMETYPE_AUDIO_DTS_HD;
+extern const char *MEDIA_MIMETYPE_AUDIO_DTS_HD_MA;
extern const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD;
+extern const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1;
+extern const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2;
extern const char *MEDIA_MIMETYPE_AUDIO_EVRC;
extern const char *MEDIA_MIMETYPE_AUDIO_EVRCB;
extern const char *MEDIA_MIMETYPE_AUDIO_EVRCWB;
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaKeys.h b/media/module/foundation/include/media/stagefright/foundation/MediaKeys.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/MediaKeys.h
rename to media/module/foundation/include/media/stagefright/foundation/MediaKeys.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/Mutexed.h b/media/module/foundation/include/media/stagefright/foundation/Mutexed.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/Mutexed.h
rename to media/module/foundation/include/media/stagefright/foundation/Mutexed.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h b/media/module/foundation/include/media/stagefright/foundation/OpusHeader.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h
rename to media/module/foundation/include/media/stagefright/foundation/OpusHeader.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/TypeTraits.h b/media/module/foundation/include/media/stagefright/foundation/TypeTraits.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/TypeTraits.h
rename to media/module/foundation/include/media/stagefright/foundation/TypeTraits.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/avc_utils.h b/media/module/foundation/include/media/stagefright/foundation/avc_utils.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/avc_utils.h
rename to media/module/foundation/include/media/stagefright/foundation/avc_utils.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h b/media/module/foundation/include/media/stagefright/foundation/base64.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/base64.h
rename to media/module/foundation/include/media/stagefright/foundation/base64.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/hexdump.h b/media/module/foundation/include/media/stagefright/foundation/hexdump.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/hexdump.h
rename to media/module/foundation/include/media/stagefright/foundation/hexdump.h
diff --git a/media/libstagefright/foundation/tests/AData_test.cpp b/media/module/foundation/tests/AData_test.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/AData_test.cpp
rename to media/module/foundation/tests/AData_test.cpp
diff --git a/media/module/foundation/tests/AMessage_test.cpp b/media/module/foundation/tests/AMessage_test.cpp
new file mode 100644
index 0000000..e08ed77
--- /dev/null
+++ b/media/module/foundation/tests/AMessage_test.cpp
@@ -0,0 +1,315 @@
+/*
+ * 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <utils/RefBase.h>
+
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/ALooper.h>
+
+using namespace android;
+
+using ::testing::InSequence;
+using ::testing::NiceMock;
+
+class LooperWithSettableClock : public ALooper {
+public:
+ LooperWithSettableClock() : mClockUs(0) {}
+
+ void setClockUs(int64_t nowUs) {
+ mClockUs = nowUs;
+ }
+
+ int64_t getNowUs() override {
+ return mClockUs;
+ }
+
+private:
+ int64_t mClockUs;
+};
+
+timespec millis100 = {0, 100L*1000*1000};
+
+class MockHandler : public AHandler {
+public:
+ MOCK_METHOD(void, onMessageReceived, (const sp<AMessage>&), (override));
+};
+
+TEST(AMessage_tests, settersAndGetters) {
+ 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"));
+}
+
+TEST(AMessage_tests, deliversMultipleMessagesInOrderImmediately) {
+ sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+ sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+ looper->registerHandler(mockHandler);
+
+ sp<AMessage> msgNow1 = new AMessage(0, mockHandler);
+ msgNow1->post();
+ sp<AMessage> msgNow2 = new AMessage(0, mockHandler);
+ msgNow2->post();
+
+ {
+ InSequence inSequence;
+ EXPECT_CALL(*mockHandler, onMessageReceived(msgNow1)).Times(1);
+ EXPECT_CALL(*mockHandler, onMessageReceived(msgNow2)).Times(1);
+ }
+ looper->start();
+ nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, doesNotDeliverDelayedMessageImmediately) {
+ sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+ sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+ looper->registerHandler(mockHandler);
+
+ sp<AMessage> msgNow = new AMessage(0, mockHandler);
+ msgNow->post();
+ sp<AMessage> msgDelayed = new AMessage(0, mockHandler);
+ msgDelayed->post(100);
+
+ EXPECT_CALL(*mockHandler, onMessageReceived(msgNow)).Times(1);
+ // note: never called
+ EXPECT_CALL(*mockHandler, onMessageReceived(msgDelayed)).Times(0);
+ looper->start();
+ nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, deliversDelayedMessagesInSequence) {
+ sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+ sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+ looper->registerHandler(mockHandler);
+
+ sp<AMessage> msgIn500 = new AMessage(0, mockHandler);
+ msgIn500->post(500);
+ sp<AMessage> msgNow = new AMessage(0, mockHandler);
+ msgNow->post();
+ sp<AMessage> msgIn100 = new AMessage(0, mockHandler);
+ msgIn100->post(100);
+ // not expected to be received
+ sp<AMessage> msgIn1000 = new AMessage(0, mockHandler);
+ msgIn1000->post(1000);
+
+ looper->setClockUs(500);
+ {
+ InSequence inSequence;
+
+ EXPECT_CALL(*mockHandler, onMessageReceived(msgNow)).Times(1);
+ EXPECT_CALL(*mockHandler, onMessageReceived(msgIn100)).Times(1);
+ EXPECT_CALL(*mockHandler, onMessageReceived(msgIn500)).Times(1);
+ }
+ // note: never called
+ EXPECT_CALL(*mockHandler, onMessageReceived(msgIn1000)).Times(0);
+ looper->start();
+ nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, deliversDelayedUniqueMessage) {
+ sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+ sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+ looper->registerHandler(mockHandler);
+
+ sp<AMessage> msg = new AMessage(0, mockHandler);
+ msg->postUnique(msg, 50);
+
+ looper->setClockUs(50);
+ EXPECT_CALL(*mockHandler, onMessageReceived(msg)).Times(1);
+ looper->start();
+ nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, deliversImmediateUniqueMessage) {
+ sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+ // note: we don't need to set the clock, but we do want a stable clock that doesn't advance
+ sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+ looper->registerHandler(mockHandler);
+
+ sp<AMessage> msg = new AMessage(0, mockHandler);
+ msg->postUnique(msg, 0);
+
+ EXPECT_CALL(*mockHandler, onMessageReceived(msg)).Times(1);
+ looper->start();
+ nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, doesNotDeliverUniqueMessageAfterRescheduleLater) {
+ sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+ sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+ looper->registerHandler(mockHandler);
+
+ sp<AMessage> msg = new AMessage(0, mockHandler);
+ msg->postUnique(msg, 50);
+ msg->postUnique(msg, 100); // reschedule for later
+
+ looper->setClockUs(50); // if the message is correctly rescheduled, it should not be delivered
+ // Never called because the message was rescheduled to a later point in time
+ EXPECT_CALL(*mockHandler, onMessageReceived(msg)).Times(0);
+ looper->start();
+ nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, deliversUniqueMessageAfterRescheduleEarlier) {
+ sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+ sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+ looper->registerHandler(mockHandler);
+
+ sp<AMessage> msg = new AMessage(0, mockHandler);
+ msg->postUnique(msg, 100);
+ msg->postUnique(msg, 50); // reschedule to fire earlier
+
+ looper->setClockUs(50); // if the message is rescheduled correctly, it should be delivered
+ EXPECT_CALL(*mockHandler, onMessageReceived(msg)).Times(1);
+ looper->start();
+ nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, deliversSameMessageTwice) {
+ sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+ sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+ looper->registerHandler(mockHandler);
+
+ sp<AMessage> msg = new AMessage(0, mockHandler);
+ msg->post(50);
+ msg->post(100);
+
+ looper->setClockUs(100);
+ EXPECT_CALL(*mockHandler, onMessageReceived(msg)).Times(2);
+ looper->start();
+ nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+// When messages are posted twice with the same token, it will only be delivered once after being
+// rescheduled.
+TEST(AMessage_tests, deliversUniqueMessageOnce) {
+ sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+ sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+ looper->registerHandler(mockHandler);
+
+ sp<AMessage> msg1 = new AMessage(0, mockHandler);
+ msg1->postUnique(msg1, 50);
+ sp<AMessage> msg2 = new AMessage(0, mockHandler);
+ msg2->postUnique(msg1, 75); // note, using the same token as msg1
+
+ looper->setClockUs(100);
+ EXPECT_CALL(*mockHandler, onMessageReceived(msg1)).Times(0);
+ EXPECT_CALL(*mockHandler, onMessageReceived(msg2)).Times(1);
+ looper->start();
+ nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, postUnique_withNullToken_returnsInvalidArgument) {
+ sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+ sp<ALooper> looper = new ALooper();
+ looper->registerHandler(mockHandler);
+
+ sp<AMessage> msg = new AMessage(0, mockHandler);
+ EXPECT_EQ(msg->postUnique(nullptr, 0), -EINVAL);
+}
diff --git a/media/libstagefright/foundation/tests/AVCUtils/AVCUtilsTestEnvironment.h b/media/module/foundation/tests/AVCUtils/AVCUtilsTestEnvironment.h
similarity index 100%
rename from media/libstagefright/foundation/tests/AVCUtils/AVCUtilsTestEnvironment.h
rename to media/module/foundation/tests/AVCUtils/AVCUtilsTestEnvironment.h
diff --git a/media/libstagefright/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp b/media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
similarity index 92%
rename from media/libstagefright/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
rename to media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
index 77a8599..57ac822 100644
--- a/media/libstagefright/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
+++ b/media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <fstream>
+#include <memory>
#include "media/stagefright/foundation/ABitReader.h"
#include "media/stagefright/foundation/avc_utils.h"
@@ -151,10 +152,10 @@
size_t fileSize = buf.st_size;
ASSERT_NE(fileSize, 0) << "Invalid file size found";
- const uint8_t *volBuffer = new uint8_t[fileSize];
+ std::unique_ptr<uint8_t[]> volBuffer(new uint8_t[fileSize]);
ASSERT_NE(volBuffer, nullptr) << "Failed to allocate VOL buffer of size: " << fileSize;
- inputFileStream.read((char *)(volBuffer), fileSize);
+ inputFileStream.read((char *)(volBuffer.get()), fileSize);
ASSERT_EQ(inputFileStream.gcount(), fileSize)
<< "Failed to read complete file, bytes read: " << inputFileStream.gcount();
@@ -163,15 +164,13 @@
int32_t volWidth = -1;
int32_t volHeight = -1;
- bool status = ExtractDimensionsFromVOLHeader(volBuffer, fileSize, &volWidth, &volHeight);
+ bool status = ExtractDimensionsFromVOLHeader(volBuffer.get(), fileSize, &volWidth, &volHeight);
ASSERT_TRUE(status)
<< "Failed to get VOL dimensions from function: ExtractDimensionsFromVOLHeader()";
ASSERT_EQ(volWidth, width) << "Expected width: " << width << "Found: " << volWidth;
ASSERT_EQ(volHeight, height) << "Expected height: " << height << "Found: " << volHeight;
-
- delete[] volBuffer;
}
TEST_P(AVCDimensionTest, DimensionTest) {
@@ -186,7 +185,8 @@
stringLine >> type >> chunkLength;
ASSERT_GT(chunkLength, 0) << "Length of the data chunk must be greater than zero";
- const uint8_t *data = new uint8_t[chunkLength];
+ std::unique_ptr<uint8_t[]> dataArray(new uint8_t[chunkLength]);
+ const uint8_t *data = dataArray.get();
ASSERT_NE(data, nullptr) << "Failed to create a data buffer of size: " << chunkLength;
const uint8_t *nalStart;
@@ -197,9 +197,11 @@
<< "Failed to read complete file, bytes read: " << mInputFileStream.gcount();
size_t smallBufferSize = kSmallBufferSize;
- const uint8_t *sanityData = new uint8_t[smallBufferSize];
+ uint8_t sanityDataBuffer[smallBufferSize];
+ const uint8_t *sanityData = sanityDataBuffer;
memcpy((void *)sanityData, (void *)data, smallBufferSize);
+ // sanityData could be changed, but sanityDataPtr is not and can be cleaned up.
status_t result = getNextNALUnit(&sanityData, &smallBufferSize, &nalStart, &nalSize, true);
ASSERT_EQ(result, -EAGAIN) << "Invalid result found when wrong NAL unit passed";
@@ -221,7 +223,6 @@
ASSERT_EQ(avcHeight, mFrameHeight)
<< "Expected height: " << mFrameHeight << "Found: " << avcHeight;
}
- delete[] data;
}
if (mNalUnitsExpected < 0) {
ASSERT_GT(numNalUnits, 0) << "Failed to find an NAL Unit";
@@ -251,7 +252,8 @@
accessUnitLength += chunkLength;
if (!type.compare("SPS")) {
- const uint8_t *data = new uint8_t[chunkLength];
+ std::unique_ptr<uint8_t[]> dataArray(new uint8_t[chunkLength]);
+ const uint8_t *data = dataArray.get();
ASSERT_NE(data, nullptr) << "Failed to create a data buffer of size: " << chunkLength;
const uint8_t *nalStart;
@@ -271,14 +273,13 @@
profile = nalStart[1];
level = nalStart[3];
}
- delete[] data;
}
}
- const uint8_t *accessUnitData = new uint8_t[accessUnitLength];
+ std::unique_ptr<uint8_t[]> accessUnitData(new uint8_t[accessUnitLength]);
ASSERT_NE(accessUnitData, nullptr) << "Failed to create a buffer of size: " << accessUnitLength;
mInputFileStream.seekg(0, ios::beg);
- mInputFileStream.read((char *)accessUnitData, accessUnitLength);
+ mInputFileStream.read((char *)accessUnitData.get(), accessUnitLength);
ASSERT_EQ(mInputFileStream.gcount(), accessUnitLength)
<< "Failed to read complete file, bytes read: " << mInputFileStream.gcount();
@@ -286,7 +287,7 @@
ASSERT_NE(accessUnit, nullptr)
<< "Failed to create an android data buffer of size: " << accessUnitLength;
- memcpy(accessUnit->data(), accessUnitData, accessUnitLength);
+ memcpy(accessUnit->data(), accessUnitData.get(), accessUnitLength);
sp<ABuffer> csdDataBuffer = MakeAVCCodecSpecificData(accessUnit, &avcWidth, &avcHeight);
ASSERT_NE(csdDataBuffer, nullptr) << "No data returned from MakeAVCCodecSpecificData()";
@@ -306,7 +307,6 @@
ASSERT_EQ(*(csdData + 3), level)
<< "Expected AVC level: " << level << " found: " << *(csdData + 3);
csdDataBuffer.clear();
- delete[] accessUnitData;
accessUnit.clear();
}
@@ -321,32 +321,31 @@
stringLine >> type >> chunkLength >> frameLayerID;
ASSERT_GT(chunkLength, 0) << "Length of the data chunk must be greater than zero";
- char *data = new char[chunkLength];
+ std::unique_ptr<char[]> data(new char[chunkLength]);
ASSERT_NE(data, nullptr) << "Failed to allocation data buffer of size: " << chunkLength;
- mInputFileStream.read(data, chunkLength);
+ mInputFileStream.read(data.get(), chunkLength);
ASSERT_EQ(mInputFileStream.gcount(), chunkLength)
<< "Failed to read complete file, bytes read: " << mInputFileStream.gcount();
if (!type.compare("IDR")) {
- bool isIDR = IsIDR((uint8_t *)data, chunkLength);
+ bool isIDR = IsIDR((uint8_t *)data.get(), chunkLength);
ASSERT_TRUE(isIDR);
- layerID = FindAVCLayerId((uint8_t *)data, chunkLength);
+ layerID = FindAVCLayerId((uint8_t *)data.get(), chunkLength);
ASSERT_EQ(layerID, frameLayerID) << "Wrong layer ID found";
} else if (!type.compare("P") || !type.compare("B")) {
sp<ABuffer> accessUnit = new ABuffer(chunkLength);
ASSERT_NE(accessUnit, nullptr) << "Unable to create access Unit";
- memcpy(accessUnit->data(), data, chunkLength);
+ memcpy(accessUnit->data(), data.get(), chunkLength);
bool isReferenceFrame = IsAVCReferenceFrame(accessUnit);
ASSERT_TRUE(isReferenceFrame);
accessUnit.clear();
- layerID = FindAVCLayerId((uint8_t *)data, chunkLength);
+ layerID = FindAVCLayerId((uint8_t *)data.get(), chunkLength);
ASSERT_EQ(layerID, frameLayerID) << "Wrong layer ID found";
}
- delete[] data;
}
}
diff --git a/media/libstagefright/foundation/tests/AVCUtils/Android.bp b/media/module/foundation/tests/AVCUtils/Android.bp
similarity index 100%
rename from media/libstagefright/foundation/tests/AVCUtils/Android.bp
rename to media/module/foundation/tests/AVCUtils/Android.bp
diff --git a/media/libstagefright/foundation/tests/AVCUtils/AndroidTest.xml b/media/module/foundation/tests/AVCUtils/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/foundation/tests/AVCUtils/AndroidTest.xml
rename to media/module/foundation/tests/AVCUtils/AndroidTest.xml
diff --git a/media/libstagefright/foundation/tests/AVCUtils/README.md b/media/module/foundation/tests/AVCUtils/README.md
similarity index 100%
rename from media/libstagefright/foundation/tests/AVCUtils/README.md
rename to media/module/foundation/tests/AVCUtils/README.md
diff --git a/media/libstagefright/foundation/tests/Android.bp b/media/module/foundation/tests/Android.bp
similarity index 96%
rename from media/libstagefright/foundation/tests/Android.bp
rename to media/module/foundation/tests/Android.bp
index e72ce43..c409dd2 100644
--- a/media/libstagefright/foundation/tests/Android.bp
+++ b/media/module/foundation/tests/Android.bp
@@ -20,10 +20,14 @@
shared_libs: [
"liblog",
- "libstagefright_foundation",
"libutils",
],
+ static_libs: [
+ "libstagefright_foundation",
+ "libgmock",
+ ],
+
srcs: [
"AData_test.cpp",
"AMessage_test.cpp",
diff --git a/media/libstagefright/foundation/tests/Base64_test.cpp b/media/module/foundation/tests/Base64_test.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/Base64_test.cpp
rename to media/module/foundation/tests/Base64_test.cpp
diff --git a/media/libstagefright/foundation/tests/Flagged_test.cpp b/media/module/foundation/tests/Flagged_test.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/Flagged_test.cpp
rename to media/module/foundation/tests/Flagged_test.cpp
diff --git a/media/libstagefright/foundation/tests/MetaDataBaseUnitTest.cpp b/media/module/foundation/tests/MetaDataBaseUnitTest.cpp
similarity index 96%
rename from media/libstagefright/foundation/tests/MetaDataBaseUnitTest.cpp
rename to media/module/foundation/tests/MetaDataBaseUnitTest.cpp
index 0aed4d2..b562e07 100644
--- a/media/libstagefright/foundation/tests/MetaDataBaseUnitTest.cpp
+++ b/media/module/foundation/tests/MetaDataBaseUnitTest.cpp
@@ -19,6 +19,7 @@
#include <string.h>
#include <sys/stat.h>
#include <fstream>
+#include <memory>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaDataBase.h>
@@ -48,18 +49,16 @@
class MetaDataBaseUnitTest : public ::testing::Test {};
TEST_F(MetaDataBaseUnitTest, CreateMetaDataBaseTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
// Testing copy constructor
- MetaDataBase *metaDataCopy = metaData;
+ MetaDataBase *metaDataCopy = metaData.get();
ASSERT_NE(metaDataCopy, nullptr) << "Failed to create meta data copy";
-
- delete metaData;
}
TEST_F(MetaDataBaseUnitTest, SetAndFindDataTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
// Setting the different key-value pair type for first time, overwrite
@@ -142,12 +141,10 @@
int32_t angle;
status = metaData->findInt32(kKeyRotation, &angle);
ASSERT_FALSE(status) << "Value for an invalid key is returned when the key is not set";
-
- delete (metaData);
}
TEST_F(MetaDataBaseUnitTest, OverWriteFunctionalityTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
// set/set/read to check first overwrite operation
@@ -186,12 +183,10 @@
status = metaData->findInt32(kKeyHeight, &height);
ASSERT_TRUE(status) << "kKeyHeight key does not exists in metadata";
ASSERT_EQ(height, kHeight3) << "Value of height is not overwritten";
-
- delete (metaData);
}
TEST_F(MetaDataBaseUnitTest, RemoveKeyTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
bool status = metaData->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
@@ -246,12 +241,10 @@
metaData->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
ASSERT_FALSE(status) << "Overwrite should be false since the metadata was cleared";
-
- delete (metaData);
}
TEST_F(MetaDataBaseUnitTest, ConvertToStringTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
String8 info = metaData->toString();
@@ -281,8 +274,6 @@
info = metaData->toString();
ASSERT_EQ(info.length(), 0) << "MetaData length is non-zero after clearing it: "
<< info.length();
-
- delete (metaData);
}
} // namespace android
diff --git a/media/libstagefright/foundation/tests/OpusHeader/Android.bp b/media/module/foundation/tests/OpusHeader/Android.bp
similarity index 89%
rename from media/libstagefright/foundation/tests/OpusHeader/Android.bp
rename to media/module/foundation/tests/OpusHeader/Android.bp
index fa2b40e..f052650 100644
--- a/media/libstagefright/foundation/tests/OpusHeader/Android.bp
+++ b/media/module/foundation/tests/OpusHeader/Android.bp
@@ -54,4 +54,7 @@
],
cfi: true,
},
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/OpusHeader/OpusHeader.zip?unzip=true",
+ ],
}
diff --git a/media/libstagefright/foundation/tests/OpusHeader/AndroidTest.xml b/media/module/foundation/tests/OpusHeader/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/foundation/tests/OpusHeader/AndroidTest.xml
rename to media/module/foundation/tests/OpusHeader/AndroidTest.xml
diff --git a/media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTest.cpp b/media/module/foundation/tests/OpusHeader/OpusHeaderTest.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTest.cpp
rename to media/module/foundation/tests/OpusHeader/OpusHeaderTest.cpp
diff --git a/media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTestEnvironment.h b/media/module/foundation/tests/OpusHeader/OpusHeaderTestEnvironment.h
similarity index 100%
rename from media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTestEnvironment.h
rename to media/module/foundation/tests/OpusHeader/OpusHeaderTestEnvironment.h
diff --git a/media/libstagefright/foundation/tests/OpusHeader/README.md b/media/module/foundation/tests/OpusHeader/README.md
similarity index 100%
rename from media/libstagefright/foundation/tests/OpusHeader/README.md
rename to media/module/foundation/tests/OpusHeader/README.md
diff --git a/media/libstagefright/foundation/tests/TypeTraits_test.cpp b/media/module/foundation/tests/TypeTraits_test.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/TypeTraits_test.cpp
rename to media/module/foundation/tests/TypeTraits_test.cpp
diff --git a/media/libstagefright/foundation/tests/Utils_test.cpp b/media/module/foundation/tests/Utils_test.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/Utils_test.cpp
rename to media/module/foundation/tests/Utils_test.cpp
diff --git a/media/libstagefright/foundation/tests/colorutils/Android.bp b/media/module/foundation/tests/colorutils/Android.bp
similarity index 100%
rename from media/libstagefright/foundation/tests/colorutils/Android.bp
rename to media/module/foundation/tests/colorutils/Android.bp
diff --git a/media/libstagefright/foundation/tests/colorutils/ColorUtilsTest.cpp b/media/module/foundation/tests/colorutils/ColorUtilsTest.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/colorutils/ColorUtilsTest.cpp
rename to media/module/foundation/tests/colorutils/ColorUtilsTest.cpp
diff --git a/media/libstagefright/id3/Android.bp b/media/module/id3/Android.bp
similarity index 100%
rename from media/libstagefright/id3/Android.bp
rename to media/module/id3/Android.bp
diff --git a/media/libstagefright/id3/ID3.cpp b/media/module/id3/ID3.cpp
similarity index 100%
rename from media/libstagefright/id3/ID3.cpp
rename to media/module/id3/ID3.cpp
diff --git a/media/libstagefright/id3/MODULE_LICENSE_APACHE2 b/media/module/id3/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/id3/MODULE_LICENSE_APACHE2
rename to media/module/id3/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/id3/NOTICE b/media/module/id3/NOTICE
similarity index 100%
rename from media/libstagefright/id3/NOTICE
rename to media/module/id3/NOTICE
diff --git a/media/libstagefright/id3/TEST_MAPPING b/media/module/id3/TEST_MAPPING
similarity index 100%
rename from media/libstagefright/id3/TEST_MAPPING
rename to media/module/id3/TEST_MAPPING
diff --git a/media/libstagefright/id3/test/Android.bp b/media/module/id3/test/Android.bp
similarity index 91%
rename from media/libstagefright/id3/test/Android.bp
rename to media/module/id3/test/Android.bp
index 52cdfa5..0481e48 100644
--- a/media/libstagefright/id3/test/Android.bp
+++ b/media/module/id3/test/Android.bp
@@ -57,4 +57,7 @@
"signed-integer-overflow",
],
},
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test-1.2.zip?unzip=true",
+ ],
}
diff --git a/media/libstagefright/id3/test/AndroidTest.xml b/media/module/id3/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/id3/test/AndroidTest.xml
rename to media/module/id3/test/AndroidTest.xml
diff --git a/media/libstagefright/id3/test/ID3Test.cpp b/media/module/id3/test/ID3Test.cpp
similarity index 100%
rename from media/libstagefright/id3/test/ID3Test.cpp
rename to media/module/id3/test/ID3Test.cpp
diff --git a/media/libstagefright/id3/test/ID3TestEnvironment.h b/media/module/id3/test/ID3TestEnvironment.h
similarity index 100%
rename from media/libstagefright/id3/test/ID3TestEnvironment.h
rename to media/module/id3/test/ID3TestEnvironment.h
diff --git a/media/libstagefright/id3/test/README.md b/media/module/id3/test/README.md
similarity index 100%
rename from media/libstagefright/id3/test/README.md
rename to media/module/id3/test/README.md
diff --git a/media/libstagefright/id3/testid3.cpp b/media/module/id3/testid3.cpp
similarity index 100%
rename from media/libstagefright/id3/testid3.cpp
rename to media/module/id3/testid3.cpp
diff --git a/media/libmediaformatshaper/Android.bp b/media/module/libmediaformatshaper/Android.bp
similarity index 100%
rename from media/libmediaformatshaper/Android.bp
rename to media/module/libmediaformatshaper/Android.bp
diff --git a/media/libmediaformatshaper/CodecProperties.cpp b/media/module/libmediaformatshaper/CodecProperties.cpp
similarity index 100%
rename from media/libmediaformatshaper/CodecProperties.cpp
rename to media/module/libmediaformatshaper/CodecProperties.cpp
diff --git a/media/libmediaformatshaper/CodecProperties.h b/media/module/libmediaformatshaper/CodecProperties.h
similarity index 100%
rename from media/libmediaformatshaper/CodecProperties.h
rename to media/module/libmediaformatshaper/CodecProperties.h
diff --git a/media/libmediaformatshaper/CodecSeeding.cpp b/media/module/libmediaformatshaper/CodecSeeding.cpp
similarity index 100%
rename from media/libmediaformatshaper/CodecSeeding.cpp
rename to media/module/libmediaformatshaper/CodecSeeding.cpp
diff --git a/media/libmediaformatshaper/FormatShaper.cpp b/media/module/libmediaformatshaper/FormatShaper.cpp
similarity index 100%
rename from media/libmediaformatshaper/FormatShaper.cpp
rename to media/module/libmediaformatshaper/FormatShaper.cpp
diff --git a/media/libmediaformatshaper/ManageShapingCodecs.cpp b/media/module/libmediaformatshaper/ManageShapingCodecs.cpp
similarity index 100%
rename from media/libmediaformatshaper/ManageShapingCodecs.cpp
rename to media/module/libmediaformatshaper/ManageShapingCodecs.cpp
diff --git a/media/libmediaformatshaper/VQApply.cpp b/media/module/libmediaformatshaper/VQApply.cpp
similarity index 100%
rename from media/libmediaformatshaper/VQApply.cpp
rename to media/module/libmediaformatshaper/VQApply.cpp
diff --git a/media/libmediaformatshaper/VQops.h b/media/module/libmediaformatshaper/VQops.h
similarity index 100%
rename from media/libmediaformatshaper/VQops.h
rename to media/module/libmediaformatshaper/VQops.h
diff --git a/media/libmediaformatshaper/VideoShaper.cpp b/media/module/libmediaformatshaper/VideoShaper.cpp
similarity index 100%
rename from media/libmediaformatshaper/VideoShaper.cpp
rename to media/module/libmediaformatshaper/VideoShaper.cpp
diff --git a/media/libmediaformatshaper/VideoShaper.h b/media/module/libmediaformatshaper/VideoShaper.h
similarity index 100%
rename from media/libmediaformatshaper/VideoShaper.h
rename to media/module/libmediaformatshaper/VideoShaper.h
diff --git a/media/libmediaformatshaper/exports.lds b/media/module/libmediaformatshaper/exports.lds
similarity index 100%
rename from media/libmediaformatshaper/exports.lds
rename to media/module/libmediaformatshaper/exports.lds
diff --git a/media/libmediaformatshaper/include/media/formatshaper/FormatShaper.h b/media/module/libmediaformatshaper/include/media/formatshaper/FormatShaper.h
similarity index 100%
rename from media/libmediaformatshaper/include/media/formatshaper/FormatShaper.h
rename to media/module/libmediaformatshaper/include/media/formatshaper/FormatShaper.h
diff --git a/media/libmediatranscoding/.clang-format b/media/module/libmediatranscoding/.clang-format
similarity index 100%
rename from media/libmediatranscoding/.clang-format
rename to media/module/libmediatranscoding/.clang-format
diff --git a/media/libmediatranscoding/Android.bp b/media/module/libmediatranscoding/Android.bp
similarity index 100%
rename from media/libmediatranscoding/Android.bp
rename to media/module/libmediatranscoding/Android.bp
diff --git a/media/libmediatranscoding/OWNERS b/media/module/libmediatranscoding/OWNERS
similarity index 100%
rename from media/libmediatranscoding/OWNERS
rename to media/module/libmediatranscoding/OWNERS
diff --git a/media/libmediatranscoding/TEST_MAPPING b/media/module/libmediatranscoding/TEST_MAPPING
similarity index 100%
rename from media/libmediatranscoding/TEST_MAPPING
rename to media/module/libmediatranscoding/TEST_MAPPING
diff --git a/media/libmediatranscoding/TranscoderWrapper.cpp b/media/module/libmediatranscoding/TranscoderWrapper.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscoderWrapper.cpp
rename to media/module/libmediatranscoding/TranscoderWrapper.cpp
diff --git a/media/libmediatranscoding/TranscodingClientManager.cpp b/media/module/libmediatranscoding/TranscodingClientManager.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscodingClientManager.cpp
rename to media/module/libmediatranscoding/TranscodingClientManager.cpp
diff --git a/media/libmediatranscoding/TranscodingLogger.cpp b/media/module/libmediatranscoding/TranscodingLogger.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscodingLogger.cpp
rename to media/module/libmediatranscoding/TranscodingLogger.cpp
diff --git a/media/libmediatranscoding/TranscodingResourcePolicy.cpp b/media/module/libmediatranscoding/TranscodingResourcePolicy.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscodingResourcePolicy.cpp
rename to media/module/libmediatranscoding/TranscodingResourcePolicy.cpp
diff --git a/media/libmediatranscoding/TranscodingSessionController.cpp b/media/module/libmediatranscoding/TranscodingSessionController.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscodingSessionController.cpp
rename to media/module/libmediatranscoding/TranscodingSessionController.cpp
diff --git a/media/libmediatranscoding/TranscodingThermalPolicy.cpp b/media/module/libmediatranscoding/TranscodingThermalPolicy.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscodingThermalPolicy.cpp
rename to media/module/libmediatranscoding/TranscodingThermalPolicy.cpp
diff --git a/media/libmediatranscoding/TranscodingUidPolicy.cpp b/media/module/libmediatranscoding/TranscodingUidPolicy.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscodingUidPolicy.cpp
rename to media/module/libmediatranscoding/TranscodingUidPolicy.cpp
diff --git a/media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl b/media/module/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
rename to media/module/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl b/media/module/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl
rename to media/module/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/ITranscodingClientCallback.aidl b/media/module/libmediatranscoding/aidl/android/media/ITranscodingClientCallback.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/ITranscodingClientCallback.aidl
rename to media/module/libmediatranscoding/aidl/android/media/ITranscodingClientCallback.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingErrorCode.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingErrorCode.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingErrorCode.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingErrorCode.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingSessionParcel.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingSessionParcel.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingSessionParcel.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingSessionParcel.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingSessionPriority.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingSessionPriority.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingSessionPriority.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingSessionPriority.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingSessionStats.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingSessionStats.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingSessionStats.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingSessionStats.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingTestConfig.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingTestConfig.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingTestConfig.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingTestConfig.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingType.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingType.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingType.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingType.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingVideoCodecType.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingVideoCodecType.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingVideoCodecType.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingVideoCodecType.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingVideoTrackFormat.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingVideoTrackFormat.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingVideoTrackFormat.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingVideoTrackFormat.aidl
diff --git a/media/libmediatranscoding/build_and_run_all_unit_tests.sh b/media/module/libmediatranscoding/build_and_run_all_unit_tests.sh
similarity index 100%
rename from media/libmediatranscoding/build_and_run_all_unit_tests.sh
rename to media/module/libmediatranscoding/build_and_run_all_unit_tests.sh
diff --git a/media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h b/media/module/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h
similarity index 100%
rename from media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h
rename to media/module/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h
diff --git a/media/libmediatranscoding/include/media/ControllerClientInterface.h b/media/module/libmediatranscoding/include/media/ControllerClientInterface.h
similarity index 100%
rename from media/libmediatranscoding/include/media/ControllerClientInterface.h
rename to media/module/libmediatranscoding/include/media/ControllerClientInterface.h
diff --git a/media/libmediatranscoding/include/media/ResourcePolicyInterface.h b/media/module/libmediatranscoding/include/media/ResourcePolicyInterface.h
similarity index 100%
rename from media/libmediatranscoding/include/media/ResourcePolicyInterface.h
rename to media/module/libmediatranscoding/include/media/ResourcePolicyInterface.h
diff --git a/media/libmediatranscoding/include/media/ThermalPolicyInterface.h b/media/module/libmediatranscoding/include/media/ThermalPolicyInterface.h
similarity index 100%
rename from media/libmediatranscoding/include/media/ThermalPolicyInterface.h
rename to media/module/libmediatranscoding/include/media/ThermalPolicyInterface.h
diff --git a/media/libmediatranscoding/include/media/TranscoderInterface.h b/media/module/libmediatranscoding/include/media/TranscoderInterface.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscoderInterface.h
rename to media/module/libmediatranscoding/include/media/TranscoderInterface.h
diff --git a/media/libmediatranscoding/include/media/TranscoderWrapper.h b/media/module/libmediatranscoding/include/media/TranscoderWrapper.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscoderWrapper.h
rename to media/module/libmediatranscoding/include/media/TranscoderWrapper.h
diff --git a/media/libmediatranscoding/include/media/TranscodingClientManager.h b/media/module/libmediatranscoding/include/media/TranscodingClientManager.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingClientManager.h
rename to media/module/libmediatranscoding/include/media/TranscodingClientManager.h
diff --git a/media/libmediatranscoding/include/media/TranscodingDefs.h b/media/module/libmediatranscoding/include/media/TranscodingDefs.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingDefs.h
rename to media/module/libmediatranscoding/include/media/TranscodingDefs.h
diff --git a/media/libmediatranscoding/include/media/TranscodingLogger.h b/media/module/libmediatranscoding/include/media/TranscodingLogger.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingLogger.h
rename to media/module/libmediatranscoding/include/media/TranscodingLogger.h
diff --git a/media/libmediatranscoding/include/media/TranscodingRequest.h b/media/module/libmediatranscoding/include/media/TranscodingRequest.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingRequest.h
rename to media/module/libmediatranscoding/include/media/TranscodingRequest.h
diff --git a/media/libmediatranscoding/include/media/TranscodingResourcePolicy.h b/media/module/libmediatranscoding/include/media/TranscodingResourcePolicy.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingResourcePolicy.h
rename to media/module/libmediatranscoding/include/media/TranscodingResourcePolicy.h
diff --git a/media/libmediatranscoding/include/media/TranscodingSessionController.h b/media/module/libmediatranscoding/include/media/TranscodingSessionController.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingSessionController.h
rename to media/module/libmediatranscoding/include/media/TranscodingSessionController.h
diff --git a/media/libmediatranscoding/include/media/TranscodingThermalPolicy.h b/media/module/libmediatranscoding/include/media/TranscodingThermalPolicy.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingThermalPolicy.h
rename to media/module/libmediatranscoding/include/media/TranscodingThermalPolicy.h
diff --git a/media/libmediatranscoding/include/media/TranscodingUidPolicy.h b/media/module/libmediatranscoding/include/media/TranscodingUidPolicy.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingUidPolicy.h
rename to media/module/libmediatranscoding/include/media/TranscodingUidPolicy.h
diff --git a/media/libmediatranscoding/include/media/UidPolicyInterface.h b/media/module/libmediatranscoding/include/media/UidPolicyInterface.h
similarity index 100%
rename from media/libmediatranscoding/include/media/UidPolicyInterface.h
rename to media/module/libmediatranscoding/include/media/UidPolicyInterface.h
diff --git a/media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp b/media/module/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp
similarity index 100%
rename from media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp
rename to media/module/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp
diff --git a/media/libmediatranscoding/tests/Android.bp b/media/module/libmediatranscoding/tests/Android.bp
similarity index 100%
rename from media/libmediatranscoding/tests/Android.bp
rename to media/module/libmediatranscoding/tests/Android.bp
diff --git a/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp b/media/module/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
similarity index 100%
rename from media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
rename to media/module/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
diff --git a/media/libmediatranscoding/tests/TranscodingLogger_tests.cpp b/media/module/libmediatranscoding/tests/TranscodingLogger_tests.cpp
similarity index 100%
rename from media/libmediatranscoding/tests/TranscodingLogger_tests.cpp
rename to media/module/libmediatranscoding/tests/TranscodingLogger_tests.cpp
diff --git a/media/libmediatranscoding/tests/TranscodingSessionController_tests.cpp b/media/module/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
similarity index 99%
rename from media/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
rename to media/module/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
index ef9c4f8..fdd327f 100644
--- a/media/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
+++ b/media/module/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
@@ -337,6 +337,8 @@
// Should have created new transcoder.
EXPECT_EQ(mTranscoder->getGeneration(), generation);
EXPECT_EQ(mTranscoder.use_count(), 2);
+ // b/240537336: Allow extra time to finish onError call
+ sleep(1);
}
void testPacerHelper(int numSubmits, int sessionDurationMs, int expectedSuccess) {
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/Video_4K_HEVC_10Frames_Audio.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/Video_4K_HEVC_10Frames_Audio.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/Video_4K_HEVC_10Frames_Audio.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/Video_4K_HEVC_10Frames_Audio.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/backyard_hevc_1920x1080_20Mbps.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/backyard_hevc_1920x1080_20Mbps.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/backyard_hevc_1920x1080_20Mbps.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/backyard_hevc_1920x1080_20Mbps.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/longtest_15s.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/longtest_15s.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/longtest_15s.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/longtest_15s.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_12Mbps.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_12Mbps.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_12Mbps.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_12Mbps.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_20Mbps.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_20Mbps.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_20Mbps.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_20Mbps.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/video_1280x720_hevc_hdr10_static_3mbps.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/video_1280x720_hevc_hdr10_static_3mbps.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/video_1280x720_hevc_hdr10_static_3mbps.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/video_1280x720_hevc_hdr10_static_3mbps.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh b/media/module/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
similarity index 100%
rename from media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
rename to media/module/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
diff --git a/media/libmediatranscoding/tests/push_assets.sh b/media/module/libmediatranscoding/tests/push_assets.sh
similarity index 100%
rename from media/libmediatranscoding/tests/push_assets.sh
rename to media/module/libmediatranscoding/tests/push_assets.sh
diff --git a/media/libmediatranscoding/transcoder/Android.bp b/media/module/libmediatranscoding/transcoder/Android.bp
similarity index 100%
rename from media/libmediatranscoding/transcoder/Android.bp
rename to media/module/libmediatranscoding/transcoder/Android.bp
diff --git a/media/libmediatranscoding/transcoder/MediaSampleQueue.cpp b/media/module/libmediatranscoding/transcoder/MediaSampleQueue.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/MediaSampleQueue.cpp
rename to media/module/libmediatranscoding/transcoder/MediaSampleQueue.cpp
diff --git a/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp b/media/module/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
rename to media/module/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
diff --git a/media/libmediatranscoding/transcoder/MediaSampleWriter.cpp b/media/module/libmediatranscoding/transcoder/MediaSampleWriter.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/MediaSampleWriter.cpp
rename to media/module/libmediatranscoding/transcoder/MediaSampleWriter.cpp
diff --git a/media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp b/media/module/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp
rename to media/module/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp
diff --git a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp b/media/module/libmediatranscoding/transcoder/MediaTranscoder.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/MediaTranscoder.cpp
rename to media/module/libmediatranscoding/transcoder/MediaTranscoder.cpp
diff --git a/media/libmediatranscoding/transcoder/NdkCommon.cpp b/media/module/libmediatranscoding/transcoder/NdkCommon.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/NdkCommon.cpp
rename to media/module/libmediatranscoding/transcoder/NdkCommon.cpp
diff --git a/media/libmediatranscoding/transcoder/PassthroughTrackTranscoder.cpp b/media/module/libmediatranscoding/transcoder/PassthroughTrackTranscoder.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/PassthroughTrackTranscoder.cpp
rename to media/module/libmediatranscoding/transcoder/PassthroughTrackTranscoder.cpp
diff --git a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp b/media/module/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
rename to media/module/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
diff --git a/media/libmediatranscoding/transcoder/benchmark/Android.bp b/media/module/libmediatranscoding/transcoder/benchmark/Android.bp
similarity index 68%
rename from media/libmediatranscoding/transcoder/benchmark/Android.bp
rename to media/module/libmediatranscoding/transcoder/benchmark/Android.bp
index 459f0ae..f98b27d 100644
--- a/media/libmediatranscoding/transcoder/benchmark/Android.bp
+++ b/media/module/libmediatranscoding/transcoder/benchmark/Android.bp
@@ -26,16 +26,25 @@
name: "MediaTranscoderBenchmark",
srcs: ["MediaTranscoderBenchmark.cpp"],
defaults: ["benchmarkdefaults"],
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
+ ],
}
cc_test {
name: "MediaSampleReaderBenchmark",
srcs: ["MediaSampleReaderBenchmark.cpp"],
defaults: ["benchmarkdefaults"],
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
+ ],
}
cc_test {
name: "MediaTrackTranscoderBenchmark",
srcs: ["MediaTrackTranscoderBenchmark.cpp"],
defaults: ["benchmarkdefaults"],
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
+ ],
}
diff --git a/media/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml b/media/module/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml
similarity index 100%
rename from media/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml
rename to media/module/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp b/media/module/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp
rename to media/module/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp b/media/module/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
rename to media/module/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp b/media/module/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
rename to media/module/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSample.h b/media/module/libmediatranscoding/transcoder/include/media/MediaSample.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaSample.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaSample.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleQueue.h b/media/module/libmediatranscoding/transcoder/include/media/MediaSampleQueue.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaSampleQueue.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaSampleQueue.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h b/media/module/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h b/media/module/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h b/media/module/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoder.h b/media/module/libmediatranscoding/transcoder/include/media/MediaTrackTranscoder.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoder.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaTrackTranscoder.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoderCallback.h b/media/module/libmediatranscoding/transcoder/include/media/MediaTrackTranscoderCallback.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoderCallback.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaTrackTranscoderCallback.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaTranscoder.h b/media/module/libmediatranscoding/transcoder/include/media/MediaTranscoder.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaTranscoder.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaTranscoder.h
diff --git a/media/libmediatranscoding/transcoder/include/media/NdkCommon.h b/media/module/libmediatranscoding/transcoder/include/media/NdkCommon.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/NdkCommon.h
rename to media/module/libmediatranscoding/transcoder/include/media/NdkCommon.h
diff --git a/media/libmediatranscoding/transcoder/include/media/PassthroughTrackTranscoder.h b/media/module/libmediatranscoding/transcoder/include/media/PassthroughTrackTranscoder.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/PassthroughTrackTranscoder.h
rename to media/module/libmediatranscoding/transcoder/include/media/PassthroughTrackTranscoder.h
diff --git a/media/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h b/media/module/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h
rename to media/module/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h
diff --git a/media/libmediatranscoding/transcoder/setloglevel.sh b/media/module/libmediatranscoding/transcoder/setloglevel.sh
similarity index 100%
rename from media/libmediatranscoding/transcoder/setloglevel.sh
rename to media/module/libmediatranscoding/transcoder/setloglevel.sh
diff --git a/media/libmediatranscoding/transcoder/tests/Android.bp b/media/module/libmediatranscoding/transcoder/tests/Android.bp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/Android.bp
rename to media/module/libmediatranscoding/transcoder/tests/Android.bp
diff --git a/media/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml b/media/module/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml
rename to media/module/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml
diff --git a/media/libmediatranscoding/transcoder/tests/HdrTranscodeTests.cpp b/media/module/libmediatranscoding/transcoder/tests/HdrTranscodeTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/HdrTranscodeTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/HdrTranscodeTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/MediaSampleQueueTests.cpp b/media/module/libmediatranscoding/transcoder/tests/MediaSampleQueueTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/MediaSampleQueueTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/MediaSampleQueueTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp b/media/module/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp b/media/module/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp b/media/module/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp b/media/module/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/PassthroughTrackTranscoderTests.cpp b/media/module/libmediatranscoding/transcoder/tests/PassthroughTrackTranscoderTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/PassthroughTrackTranscoderTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/PassthroughTrackTranscoderTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/README.md b/media/module/libmediatranscoding/transcoder/tests/README.md
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/README.md
rename to media/module/libmediatranscoding/transcoder/tests/README.md
diff --git a/media/libmediatranscoding/transcoder/tests/TranscoderTestUtils.h b/media/module/libmediatranscoding/transcoder/tests/TranscoderTestUtils.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/TranscoderTestUtils.h
rename to media/module/libmediatranscoding/transcoder/tests/TranscoderTestUtils.h
diff --git a/media/libmediatranscoding/transcoder/tests/VideoTrackTranscoderTests.cpp b/media/module/libmediatranscoding/transcoder/tests/VideoTrackTranscoderTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/VideoTrackTranscoderTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/VideoTrackTranscoderTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/build_and_run_all_unit_tests.sh b/media/module/libmediatranscoding/transcoder/tests/build_and_run_all_unit_tests.sh
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/build_and_run_all_unit_tests.sh
rename to media/module/libmediatranscoding/transcoder/tests/build_and_run_all_unit_tests.sh
diff --git a/media/libmediatranscoding/transcoder/tests/fuzzer/Android.bp b/media/module/libmediatranscoding/transcoder/tests/fuzzer/Android.bp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/fuzzer/Android.bp
rename to media/module/libmediatranscoding/transcoder/tests/fuzzer/Android.bp
diff --git a/media/libmediatranscoding/transcoder/tests/fuzzer/README.md b/media/module/libmediatranscoding/transcoder/tests/fuzzer/README.md
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/fuzzer/README.md
rename to media/module/libmediatranscoding/transcoder/tests/fuzzer/README.md
diff --git a/media/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp b/media/module/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp
rename to media/module/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp
diff --git a/media/libmediatranscoding/transcoder/tools/Android.bp b/media/module/libmediatranscoding/transcoder/tools/Android.bp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tools/Android.bp
rename to media/module/libmediatranscoding/transcoder/tools/Android.bp
diff --git a/media/libmediatranscoding/transcoder/tools/Transcode.cpp b/media/module/libmediatranscoding/transcoder/tools/Transcode.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tools/Transcode.cpp
rename to media/module/libmediatranscoding/transcoder/tools/Transcode.cpp
diff --git a/media/libwatchdog/Android.bp b/media/module/libwatchdog/Android.bp
similarity index 100%
rename from media/libwatchdog/Android.bp
rename to media/module/libwatchdog/Android.bp
diff --git a/media/libwatchdog/Watchdog.cpp b/media/module/libwatchdog/Watchdog.cpp
similarity index 100%
rename from media/libwatchdog/Watchdog.cpp
rename to media/module/libwatchdog/Watchdog.cpp
diff --git a/media/libwatchdog/include/watchdog/Watchdog.h b/media/module/libwatchdog/include/watchdog/Watchdog.h
similarity index 100%
rename from media/libwatchdog/include/watchdog/Watchdog.h
rename to media/module/libwatchdog/include/watchdog/Watchdog.h
diff --git a/media/module/metadatautils/Android.bp b/media/module/metadatautils/Android.bp
new file mode 100644
index 0000000..c77474f
--- /dev/null
+++ b/media/module/metadatautils/Android.bp
@@ -0,0 +1,46 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library_static {
+ name: "libstagefright_metadatautils",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media",
+ ],
+ min_sdk_version: "29",
+
+ srcs: ["MetaDataUtils.cpp"],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ ],
+ cfi: true,
+ },
+
+ header_libs: [
+ "libaudioclient_headers",
+ "libstagefright_headers",
+ "libstagefright_foundation_headers",
+ "media_ndk_headers",
+ ],
+
+ host_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+
+ export_include_dirs: ["include"],
+}
diff --git a/media/libstagefright/MetaDataUtils.cpp b/media/module/metadatautils/MetaDataUtils.cpp
similarity index 100%
rename from media/libstagefright/MetaDataUtils.cpp
rename to media/module/metadatautils/MetaDataUtils.cpp
diff --git a/media/module/metadatautils/TEST_MAPPING b/media/module/metadatautils/TEST_MAPPING
new file mode 100644
index 0000000..21836a5
--- /dev/null
+++ b/media/module/metadatautils/TEST_MAPPING
@@ -0,0 +1,9 @@
+// mappings for frameworks/av/media/module/metadatautils
+{
+ // tests which require dynamic content
+ // invoke with: atest -- --enable-module-dynamic-download=true
+ // TODO(b/148094059): unit tests not allowed to download content
+ "dynamic-presubmit": [
+ { "name": "MetaDataUtilsTest" }
+ ]
+}
diff --git a/media/libstagefright/include/media/stagefright/MetaDataUtils.h b/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h
similarity index 100%
rename from media/libstagefright/include/media/stagefright/MetaDataUtils.h
rename to media/module/metadatautils/include/media/stagefright/MetaDataUtils.h
diff --git a/media/libstagefright/tests/metadatautils/Android.bp b/media/module/metadatautils/test/Android.bp
similarity index 93%
rename from media/libstagefright/tests/metadatautils/Android.bp
rename to media/module/metadatautils/test/Android.bp
index ecdf89b..21f38f6 100644
--- a/media/libstagefright/tests/metadatautils/Android.bp
+++ b/media/module/metadatautils/test/Android.bp
@@ -20,9 +20,6 @@
// all of the 'license_kinds' from "frameworks_av_media_libstagefright_tests_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: [
- "frameworks_av_media_libstagefright_tests_license",
- ],
}
cc_test {
diff --git a/media/libstagefright/tests/metadatautils/AndroidTest.xml b/media/module/metadatautils/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/tests/metadatautils/AndroidTest.xml
rename to media/module/metadatautils/test/AndroidTest.xml
diff --git a/media/libstagefright/tests/metadatautils/MetaDataUtilsTest.cpp b/media/module/metadatautils/test/MetaDataUtilsTest.cpp
similarity index 96%
rename from media/libstagefright/tests/metadatautils/MetaDataUtilsTest.cpp
rename to media/module/metadatautils/test/MetaDataUtilsTest.cpp
index 9fd5fdb..7c35249 100644
--- a/media/libstagefright/tests/metadatautils/MetaDataUtilsTest.cpp
+++ b/media/module/metadatautils/test/MetaDataUtilsTest.cpp
@@ -19,9 +19,10 @@
#include <utils/Log.h>
#include <fstream>
+#include <memory>
#include <string>
-#include <ESDS.h>
+#include <media/esds/ESDS.h>
#include <media/NdkMediaFormat.h>
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/MediaDefs.h>
@@ -228,7 +229,7 @@
ASSERT_TRUE(status) << "Failed to get the mime type";
ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_VIDEO_AVC);
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
status = MakeAVCCodecSpecificData(*metaData, mInputBuffer, mInputBufferSize);
@@ -264,7 +265,6 @@
int32_t result = memcmp(csdAMediaFormatBuffer, csdMetaDataBaseBuffer, csdAMediaFormatSize);
ASSERT_EQ(result, 0) << "CSD from AMediaFormat and MetaDataBase do not match";
- delete metaData;
AMediaFormat_delete(csdData);
}
@@ -275,7 +275,7 @@
bool status = MakeAVCCodecSpecificData(csdData, mInputBuffer, mInputBufferSize);
ASSERT_FALSE(status) << "MakeAVCCodecSpecificData with AMediaFormat succeeds with invalid data";
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
status = MakeAVCCodecSpecificData(*metaData, mInputBuffer, mInputBufferSize);
@@ -307,7 +307,7 @@
ASSERT_TRUE(status) << "Failed to get the mime type";
ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_AUDIO_AAC);
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
status = MakeAACCodecSpecificData(*metaData, mAacProfile, mAacSamplingFreqIndex,
@@ -356,11 +356,10 @@
ASSERT_EQ(memcmpResult, 0) << "AMediaFormat and MetaDataBase CSDs do not match";
AMediaFormat_delete(csdData);
- delete metaData;
}
TEST_P(AacADTSTest, AacADTSValidationTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
bool status = MakeAACCodecSpecificData(*metaData, mInputBuffer, kAdtsCsdSize);
@@ -380,12 +379,10 @@
status = metaData->findCString(kKeyMIMEType, &mimeType);
ASSERT_TRUE(status) << "Failed to get mime type";
ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_AUDIO_AAC);
-
- delete metaData;
}
TEST_P(AacCSDValidateTest, AacInvalidInputTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
bool status = MakeAACCodecSpecificData(*metaData, mInputBuffer, kAdtsCsdSize);
@@ -412,14 +409,14 @@
istringstream dataStringLine(dataLine);
dataStringLine >> comment;
- char *buffer = strndup(comment.c_str(), commentLength);
+ std::unique_ptr<char[]> buffer(new char[commentLength]);
ASSERT_NE(buffer, nullptr) << "Failed to allocate buffer of size: " << commentLength;
+ strncpy(buffer.get(), comment.c_str(), commentLength);
AMediaFormat *fileMeta = AMediaFormat_new();
ASSERT_NE(fileMeta, nullptr) << "Failed to create AMedia format";
- parseVorbisComment(fileMeta, buffer, commentLength);
- free(buffer);
+ parseVorbisComment(fileMeta, buffer.get(), commentLength);
if (!strncasecmp(tag.c_str(), "ANDROID_HAPTIC", sizeof(tag))) {
int32_t numChannelExpected = stoi(value);
diff --git a/media/libstagefright/tests/metadatautils/MetaDataUtilsTestEnvironment.h b/media/module/metadatautils/test/MetaDataUtilsTestEnvironment.h
similarity index 100%
rename from media/libstagefright/tests/metadatautils/MetaDataUtilsTestEnvironment.h
rename to media/module/metadatautils/test/MetaDataUtilsTestEnvironment.h
diff --git a/media/libstagefright/tests/metadatautils/README.md b/media/module/metadatautils/test/README.md
similarity index 100%
rename from media/libstagefright/tests/metadatautils/README.md
rename to media/module/metadatautils/test/README.md
diff --git a/services/minijail/Android.bp b/media/module/minijail/Android.bp
similarity index 100%
rename from services/minijail/Android.bp
rename to media/module/minijail/Android.bp
diff --git a/services/minijail/OWNERS b/media/module/minijail/OWNERS
similarity index 100%
rename from services/minijail/OWNERS
rename to media/module/minijail/OWNERS
diff --git a/services/minijail/TEST_MAPPING b/media/module/minijail/TEST_MAPPING
similarity index 100%
rename from services/minijail/TEST_MAPPING
rename to media/module/minijail/TEST_MAPPING
diff --git a/services/minijail/av_services_minijail_unittest.cpp b/media/module/minijail/av_services_minijail_unittest.cpp
similarity index 100%
rename from services/minijail/av_services_minijail_unittest.cpp
rename to media/module/minijail/av_services_minijail_unittest.cpp
diff --git a/services/minijail/minijail.cpp b/media/module/minijail/minijail.cpp
similarity index 100%
rename from services/minijail/minijail.cpp
rename to media/module/minijail/minijail.cpp
diff --git a/services/minijail/minijail.h b/media/module/minijail/minijail.h
similarity index 100%
rename from services/minijail/minijail.h
rename to media/module/minijail/minijail.h
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/module/mpeg2ts/ATSParser.cpp
similarity index 97%
rename from media/libstagefright/mpeg2ts/ATSParser.cpp
rename to media/module/mpeg2ts/ATSParser.cpp
index 1482072..6aeea3b 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/module/mpeg2ts/ATSParser.cpp
@@ -556,7 +556,15 @@
if (descriptor_length > ES_info_length) {
return ERROR_MALFORMED;
}
- if (descriptor_tag == DESCRIPTOR_CA && descriptor_length >= 4) {
+
+ // The DTS descriptor is used in the PSI PMT to identify streams which carry
+ // DTS audio(core only). If a DTS descriptor is present, a DTS-HD or DTS-UHD
+ // descriptors shall not be present in the same ES_info descriptor loop.
+ if (descriptor_tag == DESCRIPTOR_DTS) {
+ info.mType = STREAMTYPE_DTS;
+ ES_info_length -= descriptor_length;
+ br->skipBits(descriptor_length * 8);
+ } else if (descriptor_tag == DESCRIPTOR_CA && descriptor_length >= 4) {
hasStreamCA = true;
streamCA.mSystemID = br->getBits(16);
streamCA.mPID = br->getBits(16) & 0x1fff;
@@ -575,6 +583,16 @@
if (descTagExt == EXT_DESCRIPTOR_DVB_AC4) {
info.mTypeExt = EXT_DESCRIPTOR_DVB_AC4;
br->skipBits(descriptor_length * 8);
+ } else if (descTagExt == EXT_DESCRIPTOR_DVB_DTS_HD) {
+ // DTS HD extended descriptor which can accommodate core only formats
+ // as well as extension only and core + extension combinations.
+ info.mTypeExt = EXT_DESCRIPTOR_DVB_DTS_HD;
+ br->skipBits(descriptor_length * 8);
+ } else if (descTagExt == EXT_DESCRIPTOR_DVB_DTS_UHD) {
+ // The DTS-UHD descriptor is used in the PSI PMT to identify streams
+ // which carry DTS-UHD audio
+ info.mTypeExt = EXT_DESCRIPTOR_DVB_DTS_UHD;
+ br->skipBits(descriptor_length * 8);
} else if (descTagExt == EXT_DESCRIPTOR_DVB_AUDIO_PRESELECTION &&
descriptor_length >= 1) {
// DVB BlueBook A038 Table 110
@@ -920,9 +938,17 @@
mode = ElementaryStreamQueue::EAC3;
break;
+ case STREAMTYPE_DTS:
+ mode = ElementaryStreamQueue::DTS;
+ break;
+
case STREAMTYPE_PES_PRIVATE_DATA:
if (mStreamTypeExt == EXT_DESCRIPTOR_DVB_AC4) {
mode = ElementaryStreamQueue::AC4;
+ } else if (mStreamTypeExt == EXT_DESCRIPTOR_DVB_DTS_HD) {
+ mode = ElementaryStreamQueue::DTS_HD;
+ } else if (mStreamTypeExt == EXT_DESCRIPTOR_DVB_DTS_UHD) {
+ mode = ElementaryStreamQueue::DTS_UHD;
}
break;
@@ -1158,9 +1184,12 @@
case STREAMTYPE_EAC3:
case STREAMTYPE_AAC_ENCRYPTED:
case STREAMTYPE_AC3_ENCRYPTED:
+ case STREAMTYPE_DTS:
return true;
case STREAMTYPE_PES_PRIVATE_DATA:
- return mStreamTypeExt == EXT_DESCRIPTOR_DVB_AC4;
+ return (mStreamTypeExt == EXT_DESCRIPTOR_DVB_AC4
+ || mStreamTypeExt == EXT_DESCRIPTOR_DVB_DTS_HD
+ || mStreamTypeExt == EXT_DESCRIPTOR_DVB_DTS_UHD);
default:
return false;
diff --git a/media/libstagefright/mpeg2ts/Android.bp b/media/module/mpeg2ts/Android.bp
similarity index 98%
rename from media/libstagefright/mpeg2ts/Android.bp
rename to media/module/mpeg2ts/Android.bp
index 283df1e..bf762c6 100644
--- a/media/libstagefright/mpeg2ts/Android.bp
+++ b/media/module/mpeg2ts/Android.bp
@@ -51,6 +51,7 @@
"libmedia_datasource_headers",
"libaudioclient_headers",
"media_ndk_headers",
+ "libstagefright_headers",
"libstagefright_foundation_headers",
],
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/module/mpeg2ts/AnotherPacketSource.cpp
similarity index 100%
rename from media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
rename to media/module/mpeg2ts/AnotherPacketSource.cpp
diff --git a/media/libstagefright/mpeg2ts/CasManager.cpp b/media/module/mpeg2ts/CasManager.cpp
similarity index 100%
rename from media/libstagefright/mpeg2ts/CasManager.cpp
rename to media/module/mpeg2ts/CasManager.cpp
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/module/mpeg2ts/ESQueue.cpp
similarity index 75%
rename from media/libstagefright/mpeg2ts/ESQueue.cpp
rename to media/module/mpeg2ts/ESQueue.cpp
index 192ba77..2dc7b0a 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/module/mpeg2ts/ESQueue.cpp
@@ -362,6 +362,436 @@
return OK;
}
+#define RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bitstream, size) \
+ do { \
+ if ((bitstream).numBitsLeft() < (size)) { \
+ ALOGE("Not enough bits left for further parsing"); \
+ return ERROR_MALFORMED; } \
+ } while (0)
+
+// Parse DTS Digital Surround and DTS Express(LBR) stream header
+static status_t parseDTSHDSyncFrame(
+ const uint8_t *ptr, size_t size, unsigned &frameSize, sp<MetaData> *metaData) {
+ static const unsigned channelCountTable[] = {1, 2, 2, 2, 2, 3, 3, 4,
+ 4, 5, 6, 6, 6, 7, 8, 8};
+ static const unsigned samplingRateTableCoreSS[] = {0, 8000, 16000, 32000, 0, 0, 11025, 22050,
+ 44100, 0, 0, 12000, 24000, 48000, 0, 0};
+ static const unsigned samplingRateTableExtSS[] = {8000, 16000, 32000, 64000, 128000,
+ 22050, 44100, 88200, 176400, 352800,
+ 12000, 24000, 48000, 96000, 192000, 384000};
+
+ const uint32_t DTSHD_SYNC_CORE_16BIT_BE = 0x7ffe8001;
+ const uint32_t DTSHD_SYNC_EXSS_16BIT_BE = 0x64582025;
+
+ uint32_t numChannels = 0, samplingRate = 0;
+ bool isLBR = false;
+
+ ABitReader bits(ptr, size);
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 32);
+ uint32_t dtshdSyncWord = bits.getBits(32);
+
+ // Expecting DTS Digital Surround or DTS Express(LBR) streams only
+ if (dtshdSyncWord == DTSHD_SYNC_CORE_16BIT_BE) { // DTS Digital Surround Header
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (1 + 5 + 1 + 7 + 14 + 6 + 4 + 15 + 2));
+
+ // FTYPE, SHORT, CRC, NBLKS
+ bits.skipBits(1 + 5 + 1 + 7);
+
+ frameSize = bits.getBits(14) + 1;
+ uint32_t amode = bits.getBits(6);
+ uint32_t freqIndex = bits.getBits(4);
+
+ // RATE, FIXEDBIT, DYNF, TIMEF, AUXF, HDCD, EXT_AUDIO_ID, EXT_AUDIO, ASPF
+ bits.skipBits(5 + 1 + 1 + 1 + 1 + 1 + 3 + 1 + 1);
+
+ uint32_t lfeFlag = bits.getBits(2);
+ numChannels = (amode <= 15) ? channelCountTable[amode] : 0;
+ numChannels += ((lfeFlag == 1) || (lfeFlag == 2)) ? 1 : 0;
+ samplingRate = (freqIndex <= 15) ? samplingRateTableCoreSS[freqIndex] : 0;
+
+ isLBR = false;
+ } else if (dtshdSyncWord == DTSHD_SYNC_EXSS_16BIT_BE) { // DTS Express(LBR) Header
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (8 + 2 + 1));
+
+ uint32_t extHeadersize, extSSFsize;
+ uint32_t numAudioPresent = 1, numAssets = 1;
+ uint32_t nuActiveExSSMask[8];
+
+ // userDefinedBits
+ bits.skipBits(8);
+
+ uint32_t extSSIndex = bits.getBits(2);
+ uint32_t headerSizeType = bits.getBits(1);
+
+ if (headerSizeType == 0) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (8 + 16));
+
+ extHeadersize = bits.getBits(8) + 1;
+ extSSFsize = bits.getBits(16) + 1;
+ } else {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (12 + 20));
+
+ extHeadersize = bits.getBits(12) + 1;
+ extSSFsize = bits.getBits(20) + 1;
+ }
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (1));
+
+ uint32_t staticFieldsPresent = bits.getBits(1);
+
+ if (staticFieldsPresent) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (2 + 3 + 1));
+
+ // nuRefClockCode, nuExSSFrameDurationCode
+ bits.skipBits(2 + 3);
+
+ if (bits.getBits(1)) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (32 + 4));
+
+ bits.skipBits(32 + 4);
+ }
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (3 + 3));
+
+ // numAudioPresent, numAssets
+ bits.skipBits(3 + 3);
+
+ for (uint32_t nAuPr = 0; nAuPr < numAudioPresent; nAuPr++) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (extSSIndex + 1));
+
+ nuActiveExSSMask[nAuPr] = bits.getBits(extSSIndex + 1);
+ }
+
+ for (uint32_t nAuPr = 0; nAuPr < numAudioPresent; nAuPr++) {
+ for (uint32_t nSS = 0; nSS < extSSIndex + 1; nSS++) {
+ if (((nuActiveExSSMask[nAuPr] >> nSS) & 0x1) == 1) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 8);
+
+ // nuActiveAssetMask
+ bits.skipBits(8);
+ }
+ }
+ }
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 1);
+
+ // bMixMetadataEnbl
+ if (bits.getBits(1)) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (2 + 2 + 2));
+
+ // nuMixMetadataAdjLevel
+ bits.skipBits(2);
+
+ uint32_t bits4MixOutMask = (bits.getBits(2) + 1) << 2;
+ uint32_t numMixOutConfigs = bits.getBits(2) + 1;
+
+ for (int ns = 0; ns < numMixOutConfigs; ns++) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, bits4MixOutMask);
+
+ // nuMixOutChMask
+ bits.skipBits(bits4MixOutMask);
+ }
+ }
+ }
+
+ for (int nAst = 0; nAst < numAssets; nAst++) {
+ int bits4ExSSFsize = (headerSizeType == 0) ? 16 : 20;
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, bits4ExSSFsize);
+
+ bits.skipBits(bits4ExSSFsize);
+ }
+
+ /* Asset descriptor */
+ for (int nAst = 0; nAst < numAssets; nAst++) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (9 + 3));
+
+ // nuAssetDescriptFsize, nuAssetIndex
+ bits.skipBits(9 + 3);
+
+ if (staticFieldsPresent) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 1);
+
+ // bAssetTypeDescrPresent
+ if (bits.getBits(1)) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 4);
+
+ // nuAssetTypeDescriptor
+ bits.skipBits(4);
+ }
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 1);
+
+ // bLanguageDescrPresent
+ if (bits.getBits(1)) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 24);
+
+ // LanguageDescriptor
+ bits.skipBits(24);
+ }
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 1);
+
+ // bInfoTextPresent
+ if (bits.getBits(1)) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 10);
+
+ uint32_t nuInfoTextByteSize = bits.getBits(10) + 1;
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (nuInfoTextByteSize * 8));
+
+ // InfoTextString
+ bits.skipBits(nuInfoTextByteSize * 8);
+ }
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (5 + 4 + 8));
+
+ // nuBitResolution
+ bits.skipBits(5);
+
+ samplingRate = samplingRateTableExtSS[bits.getBits(4)];
+ numChannels = bits.getBits(8) + 1;
+ }
+ }
+
+ frameSize = extHeadersize + extSSFsize;
+ isLBR = true;
+ } else {
+ ALOGE("No valid sync word in DTS/DTSHD header");
+ return ERROR_MALFORMED;
+ }
+
+ if (metaData != NULL) {
+ if (isLBR) {
+ (*metaData)->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_DTS_HD);
+ (*metaData)->setInt32(kKeyAudioProfile, 0x2); // CodecProfileLevel.DTS_HDProfileLBR
+ } else {
+ (*metaData)->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_DTS);
+ }
+ (*metaData)->setInt32(kKeyChannelCount, numChannels);
+ (*metaData)->setInt32(kKeySampleRate, samplingRate);
+ }
+ return OK;
+}
+
+static status_t extractVarLenBitFields(
+ ABitReader *bits, size_t *bitsUsed, uint32_t *value,
+ unsigned ucTable[], bool extractAndAddFlag) {
+
+ static const unsigned bitsUsedTbl[8] = {1, 1, 1, 1, 2, 2, 3, 3}; // prefix code lengths
+ static const unsigned indexTbl[8] = {0, 0, 0, 0, 1, 1, 2, 3}; // code to prefix code index map
+
+ /* Clone the bitstream */
+ ABitReader bitStream(bits->data(), bits->numBitsLeft() / 8);
+ ABitReader bitstreamClone(bits->data(), bits->numBitsLeft() / 8);
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bitstreamClone, 3);
+
+ unsigned code = bitstreamClone.getBits(3);
+ unsigned totalBitsUsed = bitsUsedTbl[code];
+ unsigned unIndex = indexTbl[code];
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bitStream, totalBitsUsed);
+
+ bitStream.skipBits(totalBitsUsed);
+
+ uint32_t unValue = 0;
+ if (ucTable[unIndex] > 0) {
+ if (extractAndAddFlag) {
+ for (unsigned un = 0; un < unIndex; un++) {
+ unValue += (1 << ucTable[un]);
+ }
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bitStream, ucTable[unIndex]);
+
+ unValue += bitStream.getBits(ucTable[unIndex]);
+ totalBitsUsed += ucTable[unIndex];
+ } else {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bitStream, ucTable[unIndex]);
+
+ unValue += bitStream.getBits(ucTable[unIndex]);
+ totalBitsUsed += ucTable[unIndex];
+ }
+ }
+
+ *bitsUsed = (size_t)totalBitsUsed;
+ *value = unValue;
+ return OK;
+}
+
+// Parse DTS UHD Profile-2 stream header
+static status_t parseDTSUHDSyncFrame(
+ const uint8_t *ptr, size_t size, unsigned &frameSize, sp<MetaData> *metaData) {
+
+ static const uint32_t DTSUHD_SYNC_CORE_16BIT_BE = 0x40411BF2;
+ static const uint32_t DTSUHD_NONSYNC_CORE_16BIT_BE = 0x71C442E8;
+
+ unsigned audioSamplRate = 0;
+
+ ABitReader bits(ptr, size);
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 32);
+
+ uint32_t syncWord = bits.getBits(32);
+
+ bool isSyncFrameFlag = false;
+ switch (syncWord) {
+ case DTSUHD_SYNC_CORE_16BIT_BE:
+ isSyncFrameFlag = true;
+ break;
+ case DTSUHD_NONSYNC_CORE_16BIT_BE:
+ isSyncFrameFlag = false;
+ break;
+ default:
+ ALOGE("No valid sync word in DTSUHD header");
+ return ERROR_MALFORMED; // invalid sync word
+ }
+
+ unsigned uctable1[4] = { 5, 8, 10, 12 };
+ uint32_t sizeOfFTOCPayload = 0;
+ size_t nuBitsUsed = 0;
+ status_t status = OK;
+
+ status = extractVarLenBitFields(&bits, &nuBitsUsed, &sizeOfFTOCPayload, uctable1, true);
+
+ if (status != OK) {
+ ALOGE("Failed to extractVarLenBitFields from DTSUHD header");
+ return ERROR_MALFORMED;
+ }
+
+ bits.skipBits(nuBitsUsed);
+
+ if (isSyncFrameFlag) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (1 + 2 + 3 + 2 + 1));
+
+ // FullChannelBasedMixFlag, ETSI TS 103 491 V1.2.1, Section 6.4.6.1
+ if (!(bits.getBits(1))) {
+ // This implementation only supports full channel mask-based
+ // audio presentation (i.e. 2.0, 5.1, 11.1 mix without objects)
+ ALOGE("Objects not supported, only DTSUHD full channel mask-based mix");
+ return ERROR_MALFORMED;
+ }
+
+ // BaseDuration, FrameDuration
+ bits.skipBits(2 + 3);
+
+ unsigned clockRateIndex = bits.getBits(2);
+ unsigned clockRateHertz = 0;
+
+ switch (clockRateIndex) {
+ case 0:
+ clockRateHertz = 32000;
+ break;
+ case 1:
+ clockRateHertz = 44100;
+ break;
+ case 2:
+ clockRateHertz = 48000;
+ break;
+ default:
+ ALOGE("Invalid clockRateIndex in DTSUHD header");
+ return ERROR_MALFORMED;
+ }
+
+ if (bits.getBits(1)) {
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (32 + 4));
+
+ bits.skipBits(32 + 4);
+ }
+
+ RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 2);
+
+ unsigned samplRateMultiplier = (1 << bits.getBits(2));
+ audioSamplRate = clockRateHertz * samplRateMultiplier;
+ }
+
+ uint32_t chunkPayloadBytes = 0;
+ int numOfMDChunks = isSyncFrameFlag ? 1 : 0; // Metadata chunks
+ for (int nmdc = 0; nmdc < numOfMDChunks; nmdc++) {
+ unsigned uctable2[4] = {6, 9, 12, 15};
+ uint32_t nuMDChunkSize = 0;
+ nuBitsUsed = 0;
+
+ status = extractVarLenBitFields(&bits, &nuBitsUsed, &nuMDChunkSize, uctable2, true);
+ if (status != OK) {
+ ALOGE("Failed to extractVarLenBitFields from DTSUHD header");
+ return ERROR_MALFORMED;
+ }
+
+ bits.skipBits(nuBitsUsed);
+
+ if (nuMDChunkSize > 32767) {
+ ALOGE("Unsupported number of metadata chunks in DTSUHD header");
+ return ERROR_MALFORMED;
+ }
+ chunkPayloadBytes += nuMDChunkSize;
+ }
+
+ // Ony one audio chunk is supported
+ int numAudioChunks = 1;
+ for (int nac = 0; nac < numAudioChunks; nac++) {
+ uint32_t acID = 256, nuAudioChunkSize = 0;
+
+ // isSyncFrameFlag means that ACID is present
+ if (isSyncFrameFlag) {
+ unsigned uctable3[4] = {2, 4, 6, 8};
+ nuBitsUsed = 0;
+
+ status = extractVarLenBitFields(&bits, &nuBitsUsed, &acID, uctable3, true);
+
+ if (status != OK) {
+ ALOGE("Failed to extractVarLenBitFields from DTSUHD header");
+ return ERROR_MALFORMED;
+ }
+
+ bits.skipBits(nuBitsUsed);
+ }
+
+ nuBitsUsed = 0;
+ if (acID == 0) {
+ nuAudioChunkSize = 0;
+ } else {
+ unsigned uctable4[4] = {9, 11, 13, 16};
+
+ status = extractVarLenBitFields(&bits, &nuBitsUsed, &nuAudioChunkSize, uctable4, true);
+
+ if (status != OK) {
+ ALOGE("Failed to extractVarLenBitFields from DTSUHD header");
+ return ERROR_MALFORMED;
+ }
+ }
+
+ if (nuAudioChunkSize > 65535){
+ ALOGE("Unsupported number of audio chunks in DTSUHD header");
+ return ERROR_MALFORMED;
+ }
+
+ chunkPayloadBytes += nuAudioChunkSize;
+ }
+
+ frameSize = (sizeOfFTOCPayload + 1) + chunkPayloadBytes;
+
+ if (metaData != NULL) {
+ (*metaData)->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_DTS_UHD);
+ (*metaData)->setInt32(kKeyAudioProfile, 0x2); // CodecProfileLevel.DTS_UHDProfileP2
+ (*metaData)->setInt32(kKeyChannelCount, 2); // Setting default channel count as stereo
+ (*metaData)->setInt32(kKeySampleRate, audioSamplRate);
+ }
+
+ return OK;
+}
+
+static status_t isSeeminglyValidDTSHDHeader(const uint8_t *ptr, size_t size,unsigned &frameSize)
+{
+ return parseDTSHDSyncFrame(ptr, size, frameSize, NULL);
+}
+
+static status_t isSeeminglyValidDTSUHDHeader(const uint8_t *ptr, size_t size,unsigned &frameSize)
+{
+ return parseDTSUHDSyncFrame(ptr, size, frameSize, NULL);
+}
+
static status_t IsSeeminglyValidAC4Header(const uint8_t *ptr, size_t size, unsigned &frameSize) {
return parseAC4SyncFrame(ptr, size, frameSize, NULL);
}
@@ -655,6 +1085,70 @@
break;
}
+ case DTS: // Checking for DTS or DTS-HD syncword
+ case DTS_HD:
+ {
+ uint8_t *ptr = (uint8_t *)data;
+ unsigned frameSize = 0;
+ ssize_t startOffset = -1;
+
+ for (size_t i = 0; i < size; ++i) {
+ if (isSeeminglyValidDTSHDHeader(&ptr[i], size - i, frameSize) == OK) {
+ startOffset = i;
+ break;
+ }
+ }
+
+ if (startOffset < 0) {
+ return ERROR_MALFORMED;
+ }
+ if (startOffset > 0) {
+ ALOGI("found something resembling a DTS-HD syncword at "
+ "offset %zd",
+ startOffset);
+ }
+
+ if (frameSize != size - startOffset) {
+ ALOGV("DTS-HD frame size is %u bytes, while the buffer size is %zd bytes.",
+ frameSize, size - startOffset);
+ }
+
+ data = &ptr[startOffset];
+ size -= startOffset;
+ break;
+ }
+
+ case DTS_UHD:
+ {
+ uint8_t *ptr = (uint8_t *)data;
+ ssize_t startOffset = -1;
+ unsigned frameSize = 0;
+
+ for (size_t i = 0; i < size; ++i) {
+ if (isSeeminglyValidDTSUHDHeader(&ptr[i], size - i, frameSize) == OK) {
+ startOffset = i;
+ break;
+ }
+ }
+
+ if (startOffset < 0) {
+ return ERROR_MALFORMED;
+ }
+ if (startOffset >= 0) {
+ ALOGI("found something resembling a DTS UHD syncword"
+ "syncword at offset %zd",
+ startOffset);
+ }
+
+ if (frameSize != size - startOffset) {
+ ALOGV("DTS-UHD frame size is %u bytes, while the buffer size is %zd bytes.",
+ frameSize, size - startOffset);
+ }
+ data = &ptr[startOffset];
+ size -= startOffset;
+ break;
+ }
+
case PCM_AUDIO:
case METADATA:
{
@@ -928,6 +1422,11 @@
return dequeueAccessUnitPCMAudio();
case METADATA:
return dequeueAccessUnitMetadata();
+ case DTS: // Using same dequeue function for both DTS and DTS-HD types.
+ case DTS_HD:
+ return dequeueAccessUnitDTSOrDTSHD();
+ case DTS_UHD:
+ return dequeueAccessUnitDTSUHD();
default:
if (mMode != MPEG_AUDIO) {
ALOGE("Unknown mode");
@@ -937,6 +1436,113 @@
}
}
+sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitDTSOrDTSHD() {
+ unsigned syncStartPos = 0; // in bytes
+ unsigned payloadSize = 0;
+ sp<MetaData> format = new MetaData;
+
+ ALOGV("dequeueAccessUnitDTSOrDTSHD[%d]: mBuffer %p(%zu)", mAUIndex,
+ mBuffer->data(), mBuffer->size());
+
+ while (true) {
+ if (syncStartPos + 4 >= mBuffer->size()) {
+ return NULL;
+ }
+ uint8_t *ptr = mBuffer->data() + syncStartPos;
+ size_t size = mBuffer->size() - syncStartPos;
+ status_t status = parseDTSHDSyncFrame(ptr, size, payloadSize, &format);
+ if (status == 0) {
+ break;
+ }
+ ++syncStartPos;
+ }
+
+ if (mBuffer->size() < syncStartPos + payloadSize) {
+ ALOGV("Not enough buffer size for DTS/DTS-HD");
+ return NULL;
+ }
+
+ if (mFormat == NULL) {
+ mFormat = format;
+ }
+
+ int64_t timeUs = fetchTimestamp(syncStartPos + payloadSize);
+ if (timeUs < 0LL) {
+ ALOGE("negative timeUs");
+ return NULL;
+ }
+ mAUIndex++;
+
+ sp<ABuffer> accessUnit = new ABuffer(syncStartPos + payloadSize);
+ memcpy(accessUnit->data(), mBuffer->data(), syncStartPos + payloadSize);
+
+ accessUnit->meta()->setInt64("timeUs", timeUs);
+ accessUnit->meta()->setInt32("isSync", 1);
+
+ memmove(
+ mBuffer->data(),
+ mBuffer->data() + syncStartPos + payloadSize,
+ mBuffer->size() - syncStartPos - payloadSize);
+
+ mBuffer->setRange(0, mBuffer->size() - syncStartPos - payloadSize);
+
+ return accessUnit;
+}
+
+sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitDTSUHD()
+{
+ unsigned syncStartPos = 0; // in bytes
+ unsigned payloadSize = 0;
+ sp<MetaData> format = new MetaData;
+
+ ALOGV("dequeueAccessUnitDTSUHD[%d]: mBuffer %p(%zu)", mAUIndex,
+ mBuffer->data(), mBuffer->size());
+
+ while (true) {
+ if (syncStartPos + 4 >= mBuffer->size()) {
+ return NULL;
+ }
+ uint8_t *ptr = mBuffer->data() + syncStartPos;
+ size_t size = mBuffer->size() - syncStartPos;
+ status_t status = parseDTSUHDSyncFrame(ptr, size, payloadSize, &format);
+ if (status == 0) {
+ break;
+ }
+ ++syncStartPos;
+ }
+
+ if (mBuffer->size() < syncStartPos + payloadSize) {
+ ALOGV("Not enough buffer size for DTS-UHD");
+ return NULL;
+ }
+
+ if (mFormat == NULL) {
+ mFormat = format;
+ }
+
+ int64_t timeUs = fetchTimestamp(syncStartPos + payloadSize);
+ if (timeUs < 0LL) {
+ ALOGE("negative timeUs");
+ return NULL;
+ }
+ mAUIndex++;
+
+ sp<ABuffer> accessUnit = new ABuffer(syncStartPos + payloadSize);
+ memcpy(accessUnit->data(), mBuffer->data(), syncStartPos + payloadSize);
+
+ accessUnit->meta()->setInt64("timeUs", timeUs);
+ accessUnit->meta()->setInt32("isSync", 1);
+
+ memmove(
+ mBuffer->data(),
+ mBuffer->data() + syncStartPos + payloadSize,
+ mBuffer->size() - syncStartPos - payloadSize);
+
+ mBuffer->setRange(0, mBuffer->size() - syncStartPos - payloadSize);
+
+ return accessUnit;
+}
+
sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitEAC3() {
unsigned syncStartPos = 0; // in bytes
unsigned payloadSize = 0;
diff --git a/media/libstagefright/mpeg2ts/HlsSampleDecryptor.cpp b/media/module/mpeg2ts/HlsSampleDecryptor.cpp
similarity index 100%
rename from media/libstagefright/mpeg2ts/HlsSampleDecryptor.cpp
rename to media/module/mpeg2ts/HlsSampleDecryptor.cpp
diff --git a/media/libstagefright/mpeg2ts/MODULE_LICENSE_APACHE2 b/media/module/mpeg2ts/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/mpeg2ts/MODULE_LICENSE_APACHE2
rename to media/module/mpeg2ts/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/mpeg2ts/NOTICE b/media/module/mpeg2ts/NOTICE
similarity index 100%
rename from media/libstagefright/mpeg2ts/NOTICE
rename to media/module/mpeg2ts/NOTICE
diff --git a/media/libstagefright/mpeg2ts/TEST_MAPPING b/media/module/mpeg2ts/TEST_MAPPING
similarity index 100%
rename from media/libstagefright/mpeg2ts/TEST_MAPPING
rename to media/module/mpeg2ts/TEST_MAPPING
diff --git a/media/libstagefright/mpeg2ts/include/mpeg2ts/ATSParser.h b/media/module/mpeg2ts/include/mpeg2ts/ATSParser.h
similarity index 96%
rename from media/libstagefright/mpeg2ts/include/mpeg2ts/ATSParser.h
rename to media/module/mpeg2ts/include/mpeg2ts/ATSParser.h
index 49578d3..b658c5a 100644
--- a/media/libstagefright/mpeg2ts/include/mpeg2ts/ATSParser.h
+++ b/media/module/mpeg2ts/include/mpeg2ts/ATSParser.h
@@ -157,6 +157,9 @@
STREAMTYPE_LPCM_AC3 = 0x83,
STREAMTYPE_EAC3 = 0x87,
+ // DTS audio stream type which contains only Core substream
+ STREAMTYPE_DTS = 0x8A,
+
//Sample Encrypted types
STREAMTYPE_H264_ENCRYPTED = 0xDB,
STREAMTYPE_AAC_ENCRYPTED = 0xCF,
@@ -168,6 +171,7 @@
DESCRIPTOR_CA = 0x09,
// DVB BlueBook A038 Table 12
+ DESCRIPTOR_DTS = 0x7B,
DESCRIPTOR_DVB_EXTENSION = 0x7F,
};
@@ -175,6 +179,8 @@
enum {
EXT_DESCRIPTOR_DVB_AC4 = 0x15,
EXT_DESCRIPTOR_DVB_AUDIO_PRESELECTION = 0x19,
+ EXT_DESCRIPTOR_DVB_DTS_HD = 0x0E,
+ EXT_DESCRIPTOR_DVB_DTS_UHD = 0x21,
EXT_DESCRIPTOR_DVB_RESERVED_MAX = 0x7F,
};
diff --git a/media/libstagefright/mpeg2ts/include/mpeg2ts/AnotherPacketSource.h b/media/module/mpeg2ts/include/mpeg2ts/AnotherPacketSource.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/include/mpeg2ts/AnotherPacketSource.h
rename to media/module/mpeg2ts/include/mpeg2ts/AnotherPacketSource.h
diff --git a/media/libstagefright/mpeg2ts/include/mpeg2ts/CasManager.h b/media/module/mpeg2ts/include/mpeg2ts/CasManager.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/include/mpeg2ts/CasManager.h
rename to media/module/mpeg2ts/include/mpeg2ts/CasManager.h
diff --git a/media/libstagefright/mpeg2ts/include/mpeg2ts/ESQueue.h b/media/module/mpeg2ts/include/mpeg2ts/ESQueue.h
similarity index 96%
rename from media/libstagefright/mpeg2ts/include/mpeg2ts/ESQueue.h
rename to media/module/mpeg2ts/include/mpeg2ts/ESQueue.h
index a06bd6a..550a0e4 100644
--- a/media/libstagefright/mpeg2ts/include/mpeg2ts/ESQueue.h
+++ b/media/module/mpeg2ts/include/mpeg2ts/ESQueue.h
@@ -45,6 +45,9 @@
MPEG4_VIDEO,
PCM_AUDIO,
METADATA,
+ DTS,
+ DTS_HD,
+ DTS_UHD,
};
enum Flags {
@@ -125,6 +128,8 @@
sp<ABuffer> dequeueAccessUnitMPEG4Video();
sp<ABuffer> dequeueAccessUnitPCMAudio();
sp<ABuffer> dequeueAccessUnitMetadata();
+ sp<ABuffer> dequeueAccessUnitDTSOrDTSHD();
+ sp<ABuffer> dequeueAccessUnitDTSUHD();
// consume a logical (compressed) access unit of size "size",
// returns its timestamp in us (or -1 if no time information).
diff --git a/media/libstagefright/mpeg2ts/include/mpeg2ts/HlsSampleDecryptor.h b/media/module/mpeg2ts/include/mpeg2ts/HlsSampleDecryptor.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/include/mpeg2ts/HlsSampleDecryptor.h
rename to media/module/mpeg2ts/include/mpeg2ts/HlsSampleDecryptor.h
diff --git a/media/libstagefright/mpeg2ts/include/mpeg2ts/SampleDecryptor.h b/media/module/mpeg2ts/include/mpeg2ts/SampleDecryptor.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/include/mpeg2ts/SampleDecryptor.h
rename to media/module/mpeg2ts/include/mpeg2ts/SampleDecryptor.h
diff --git a/media/libstagefright/mpeg2ts/test/Android.bp b/media/module/mpeg2ts/test/Android.bp
similarity index 92%
rename from media/libstagefright/mpeg2ts/test/Android.bp
rename to media/module/mpeg2ts/test/Android.bp
index 34a8d3e..4b1bacd 100644
--- a/media/libstagefright/mpeg2ts/test/Android.bp
+++ b/media/module/mpeg2ts/test/Android.bp
@@ -74,4 +74,7 @@
"signed-integer-overflow",
],
},
+ data: [
+ ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.zip?unzip=true",
+ ],
}
diff --git a/media/libstagefright/mpeg2ts/test/AndroidTest.xml b/media/module/mpeg2ts/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/mpeg2ts/test/AndroidTest.xml
rename to media/module/mpeg2ts/test/AndroidTest.xml
diff --git a/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.cpp b/media/module/mpeg2ts/test/Mpeg2tsUnitTest.cpp
similarity index 100%
rename from media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.cpp
rename to media/module/mpeg2ts/test/Mpeg2tsUnitTest.cpp
diff --git a/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTestEnvironment.h b/media/module/mpeg2ts/test/Mpeg2tsUnitTestEnvironment.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTestEnvironment.h
rename to media/module/mpeg2ts/test/Mpeg2tsUnitTestEnvironment.h
diff --git a/media/libstagefright/mpeg2ts/test/README.md b/media/module/mpeg2ts/test/README.md
similarity index 100%
rename from media/libstagefright/mpeg2ts/test/README.md
rename to media/module/mpeg2ts/test/README.md
diff --git a/services/mediatranscoding/.clang-format b/media/module/service.mediatranscoding/.clang-format
similarity index 100%
rename from services/mediatranscoding/.clang-format
rename to media/module/service.mediatranscoding/.clang-format
diff --git a/services/mediatranscoding/Android.bp b/media/module/service.mediatranscoding/Android.bp
similarity index 96%
rename from services/mediatranscoding/Android.bp
rename to media/module/service.mediatranscoding/Android.bp
index fa5eb4e..37f354b 100644
--- a/services/mediatranscoding/Android.bp
+++ b/media/module/service.mediatranscoding/Android.bp
@@ -26,6 +26,10 @@
"SimulatedTranscoder.cpp",
],
+ export_include_dirs: [
+ ".",
+ ],
+
min_sdk_version: "29",
apex_available: [
"com.android.media",
diff --git a/services/mediatranscoding/MODULE_LICENSE_APACHE2 b/media/module/service.mediatranscoding/MODULE_LICENSE_APACHE2
similarity index 100%
rename from services/mediatranscoding/MODULE_LICENSE_APACHE2
rename to media/module/service.mediatranscoding/MODULE_LICENSE_APACHE2
diff --git a/services/mediatranscoding/MediaTranscodingService.cpp b/media/module/service.mediatranscoding/MediaTranscodingService.cpp
similarity index 100%
rename from services/mediatranscoding/MediaTranscodingService.cpp
rename to media/module/service.mediatranscoding/MediaTranscodingService.cpp
diff --git a/services/mediatranscoding/MediaTranscodingService.h b/media/module/service.mediatranscoding/MediaTranscodingService.h
similarity index 100%
rename from services/mediatranscoding/MediaTranscodingService.h
rename to media/module/service.mediatranscoding/MediaTranscodingService.h
diff --git a/services/mediatranscoding/NOTICE b/media/module/service.mediatranscoding/NOTICE
similarity index 100%
rename from services/mediatranscoding/NOTICE
rename to media/module/service.mediatranscoding/NOTICE
diff --git a/services/mediatranscoding/OWNERS b/media/module/service.mediatranscoding/OWNERS
similarity index 100%
rename from services/mediatranscoding/OWNERS
rename to media/module/service.mediatranscoding/OWNERS
diff --git a/services/mediatranscoding/SimulatedTranscoder.cpp b/media/module/service.mediatranscoding/SimulatedTranscoder.cpp
similarity index 100%
rename from services/mediatranscoding/SimulatedTranscoder.cpp
rename to media/module/service.mediatranscoding/SimulatedTranscoder.cpp
diff --git a/services/mediatranscoding/SimulatedTranscoder.h b/media/module/service.mediatranscoding/SimulatedTranscoder.h
similarity index 100%
rename from services/mediatranscoding/SimulatedTranscoder.h
rename to media/module/service.mediatranscoding/SimulatedTranscoder.h
diff --git a/services/mediatranscoding/main_mediatranscodingservice.cpp b/media/module/service.mediatranscoding/main_mediatranscodingservice.cpp
similarity index 100%
rename from services/mediatranscoding/main_mediatranscodingservice.cpp
rename to media/module/service.mediatranscoding/main_mediatranscodingservice.cpp
diff --git a/services/mediatranscoding/tests/Android.bp b/media/module/service.mediatranscoding/tests/Android.bp
similarity index 95%
rename from services/mediatranscoding/tests/Android.bp
rename to media/module/service.mediatranscoding/tests/Android.bp
index ae13656..97fbd4c 100644
--- a/services/mediatranscoding/tests/Android.bp
+++ b/media/module/service.mediatranscoding/tests/Android.bp
@@ -20,10 +20,6 @@
"-Wextra",
],
- include_dirs: [
- "frameworks/av/services/mediatranscoding",
- ],
-
shared_libs: [
"libactivitymanager_aidl",
"libbinder",
diff --git a/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h b/media/module/service.mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
similarity index 100%
rename from services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
rename to media/module/service.mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
diff --git a/services/mediatranscoding/tests/README.txt b/media/module/service.mediatranscoding/tests/README.txt
similarity index 100%
rename from services/mediatranscoding/tests/README.txt
rename to media/module/service.mediatranscoding/tests/README.txt
diff --git a/services/mediatranscoding/tests/TranscodingUidPolicyTestApp/Android.bp b/media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/Android.bp
similarity index 100%
rename from services/mediatranscoding/tests/TranscodingUidPolicyTestApp/Android.bp
rename to media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/Android.bp
diff --git a/services/mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppA.xml b/media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppA.xml
similarity index 100%
rename from services/mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppA.xml
rename to media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppA.xml
diff --git a/services/mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppB.xml b/media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppB.xml
similarity index 100%
rename from services/mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppB.xml
rename to media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppB.xml
diff --git a/services/mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppC.xml b/media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppC.xml
similarity index 100%
rename from services/mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppC.xml
rename to media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppC.xml
diff --git a/services/mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/MainActivity.java b/media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/MainActivity.java
similarity index 100%
rename from services/mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/MainActivity.java
rename to media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/MainActivity.java
diff --git a/services/mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/ResourcePolicyTestActivity.java b/media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/ResourcePolicyTestActivity.java
similarity index 100%
rename from services/mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/ResourcePolicyTestActivity.java
rename to media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/ResourcePolicyTestActivity.java
diff --git a/services/mediatranscoding/tests/build_and_run_all_unit_tests.sh b/media/module/service.mediatranscoding/tests/build_and_run_all_unit_tests.sh
similarity index 100%
rename from services/mediatranscoding/tests/build_and_run_all_unit_tests.sh
rename to media/module/service.mediatranscoding/tests/build_and_run_all_unit_tests.sh
diff --git a/services/mediatranscoding/tests/mediatranscodingservice_real_tests.cpp b/media/module/service.mediatranscoding/tests/mediatranscodingservice_real_tests.cpp
similarity index 100%
rename from services/mediatranscoding/tests/mediatranscodingservice_real_tests.cpp
rename to media/module/service.mediatranscoding/tests/mediatranscodingservice_real_tests.cpp
diff --git a/services/mediatranscoding/tests/mediatranscodingservice_resource_tests.cpp b/media/module/service.mediatranscoding/tests/mediatranscodingservice_resource_tests.cpp
similarity index 100%
rename from services/mediatranscoding/tests/mediatranscodingservice_resource_tests.cpp
rename to media/module/service.mediatranscoding/tests/mediatranscodingservice_resource_tests.cpp
diff --git a/services/mediatranscoding/tests/mediatranscodingservice_simulated_tests.cpp b/media/module/service.mediatranscoding/tests/mediatranscodingservice_simulated_tests.cpp
similarity index 100%
rename from services/mediatranscoding/tests/mediatranscodingservice_simulated_tests.cpp
rename to media/module/service.mediatranscoding/tests/mediatranscodingservice_simulated_tests.cpp
diff --git a/media/mtp/Android.bp b/media/mtp/Android.bp
index 97e2a22..719d05a 100644
--- a/media/mtp/Android.bp
+++ b/media/mtp/Android.bp
@@ -31,8 +31,8 @@
],
}
-cc_library_shared {
- name: "libmtp",
+cc_defaults {
+ name: "libmtp_defaults",
srcs: [
"MtpDataPacket.cpp",
"MtpDebug.cpp",
@@ -71,3 +71,14 @@
],
header_libs: ["libcutils_headers"],
}
+
+cc_library_shared {
+ name: "libmtp",
+ defaults: ["libmtp_defaults"],
+}
+
+cc_library_shared {
+ name: "libmtp_fuzz",
+ defaults: ["libmtp_defaults"],
+ cflags: ["-DMTP_FUZZER"],
+}
diff --git a/media/mtp/MtpDescriptors.h b/media/mtp/MtpDescriptors.h
index d600a24..9b98a71 100644
--- a/media/mtp/MtpDescriptors.h
+++ b/media/mtp/MtpDescriptors.h
@@ -23,6 +23,17 @@
namespace android {
+#ifdef MTP_FUZZER
+constexpr char FFS_MTP_EP0[] = "/data/local/tmp/usb-ffs/mtp/ep0";
+constexpr char FFS_MTP_EP_IN[] = "/data/local/tmp/usb-ffs/mtp/ep1";
+constexpr char FFS_MTP_EP_OUT[] = "/data/local/tmp/usb-ffs/mtp/ep2";
+constexpr char FFS_MTP_EP_INTR[] = "/data/local/tmp/usb-ffs/mtp/ep3";
+
+constexpr char FFS_PTP_EP0[] = "/data/local/tmp/usb-ffs/ptp/ep0";
+constexpr char FFS_PTP_EP_IN[] = "/data/local/tmp/usb-ffs/ptp/ep1";
+constexpr char FFS_PTP_EP_OUT[] = "/data/local/tmp/usb-ffs/ptp/ep2";
+constexpr char FFS_PTP_EP_INTR[] = "/data/local/tmp/usb-ffs/ptp/ep3";
+#else
constexpr char FFS_MTP_EP0[] = "/dev/usb-ffs/mtp/ep0";
constexpr char FFS_MTP_EP_IN[] = "/dev/usb-ffs/mtp/ep1";
constexpr char FFS_MTP_EP_OUT[] = "/dev/usb-ffs/mtp/ep2";
@@ -32,6 +43,7 @@
constexpr char FFS_PTP_EP_IN[] = "/dev/usb-ffs/ptp/ep1";
constexpr char FFS_PTP_EP_OUT[] = "/dev/usb-ffs/ptp/ep2";
constexpr char FFS_PTP_EP_INTR[] = "/dev/usb-ffs/ptp/ep3";
+#endif
constexpr int MAX_PACKET_SIZE_FS = 64;
constexpr int MAX_PACKET_SIZE_HS = 512;
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 6fcf119..d917772 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -985,7 +985,7 @@
int type = storage->getType();
if (type == MTP_STORAGE_REMOVABLE_RAM) {
- std::string str = android::base::Trim((const char*)name);
+ std::string str = android::base::Trim(name);
name.set(str.c_str());
}
ALOGV("name: %s format: 0x%04X (%s)\n", (const char*)name, format,
diff --git a/media/mtp/MtpStringBuffer.h b/media/mtp/MtpStringBuffer.h
index 4cec58a..30d1bc1 100644
--- a/media/mtp/MtpStringBuffer.h
+++ b/media/mtp/MtpStringBuffer.h
@@ -20,6 +20,7 @@
#include <log/log.h>
#include <stdint.h>
#include <string>
+#include <string_view>
// Max Character number of a MTP String
#define MTP_STRING_MAX_CHARACTER_NUMBER 255
@@ -55,6 +56,7 @@
inline int size() const { return mString.length(); }
inline operator const char*() const { return mString.c_str(); }
+ operator std::string_view() const { return mString; }
};
inline void MtpStringBuffer::append(const char* other) {
diff --git a/media/mtp/tests/MtpFuzzer/Android.bp b/media/mtp/tests/MtpFuzzer/Android.bp
index 5365f4b..9e41680 100644
--- a/media/mtp/tests/MtpFuzzer/Android.bp
+++ b/media/mtp/tests/MtpFuzzer/Android.bp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
@@ -6,29 +22,20 @@
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_av_media_mtp_license"],
}
-
-cc_fuzz {
- name: "mtp_fuzzer",
- srcs: [
- "mtp_fuzzer.cpp",
- "MtpMockDatabase.cpp",
- ],
+cc_defaults {
+ name: "mtp_fuzzer_defaults",
shared_libs: [
- "libmtp",
- "libbase",
- "liblog",
- "libutils",
+ "libbase",
+ "liblog",
+ "libutils",
],
+ static_libs: ["libc++fs",],
cflags: [
"-Wall",
"-Wextra",
"-Werror",
- "-DMTP_DEVICE",
"-Wno-unused-parameter",
],
- dictionary: "mtp_fuzzer.dict",
- corpus: ["corpus/*"],
-
fuzz_config: {
cc: ["jameswei@google.com"],
@@ -38,3 +45,107 @@
],
},
}
+cc_fuzz {
+ name: "mtp_fuzzer",
+ srcs: [
+ "mtp_fuzzer.cpp",
+ "MtpMockDatabase.cpp",
+ ],
+ cflags: ["-DMTP_DEVICE",],
+ shared_libs: ["libmtp",],
+ defaults: ["mtp_fuzzer_defaults"],
+ dictionary: "mtp_fuzzer.dict",
+ corpus: ["corpus/*"],
+}
+
+cc_defaults {
+ name: "mtp_property_fuzzer_defaults",
+ srcs: ["mtp_property_fuzzer.cpp"],
+ shared_libs: [
+ "libmtp",
+ "libasyncio",
+ "libusbhost",
+ ],
+ defaults: ["mtp_fuzzer_defaults"],
+}
+
+cc_fuzz {
+ name: "mtp_device_property_fuzzer",
+ defaults: ["mtp_property_fuzzer_defaults"],
+ cflags: [
+ "-DMTP_DEVICE",
+ ],
+}
+
+cc_fuzz {
+ name: "mtp_host_property_fuzzer",
+ defaults: ["mtp_property_fuzzer_defaults"],
+ cflags: [
+ "-DMTP_HOST",
+ ],
+}
+
+cc_fuzz {
+ name: "mtp_handle_fuzzer",
+ srcs: ["mtp_handle_fuzzer.cpp"],
+ shared_libs: ["libmtp_fuzz"],
+ defaults: ["mtp_fuzzer_defaults"],
+ cflags: ["-DMTP_FUZZER"],
+}
+
+cc_defaults {
+ name: "mtp_packet_defaults",
+ shared_libs: [
+ "libmtp",
+ "libasyncio",
+ "libusbhost",
+ ],
+ defaults: ["mtp_fuzzer_defaults"],
+ cflags: [
+ "-DMTP_HOST",
+ "-DMTP_DEVICE",
+ ],
+}
+
+cc_fuzz {
+ name: "mtp_packet_fuzzer",
+ srcs: ["mtp_packet_fuzzer.cpp"],
+ defaults: ["mtp_packet_defaults"],
+}
+
+cc_fuzz {
+ name: "mtp_device_fuzzer",
+ srcs: ["mtp_device_fuzzer.cpp"],
+ shared_libs: [
+ "libmtp",
+ "libusbhost",
+ ],
+ defaults: ["mtp_fuzzer_defaults"],
+ cflags: [
+ "-DMTP_DEVICE",
+ ],
+}
+
+cc_fuzz {
+ name: "mtp_request_packet_fuzzer",
+ srcs: ["mtp_request_packet_fuzzer.cpp"],
+ defaults: ["mtp_packet_defaults"],
+}
+
+cc_fuzz {
+ name: "mtp_event_packet_fuzzer",
+ srcs: ["mtp_event_packet_fuzzer.cpp"],
+ defaults: ["mtp_packet_defaults"],
+}
+
+cc_fuzz {
+ name: "mtp_response_packet_fuzzer",
+ srcs: ["mtp_response_packet_fuzzer.cpp"],
+ defaults: ["mtp_packet_defaults"],
+}
+
+cc_fuzz {
+ name: "mtp_data_packet_fuzzer",
+ srcs: ["mtp_data_packet_fuzzer.cpp"],
+ defaults: ["mtp_packet_defaults"],
+}
diff --git a/media/mtp/tests/MtpFuzzer/MtpPacketFuzzerUtils.h b/media/mtp/tests/MtpFuzzer/MtpPacketFuzzerUtils.h
new file mode 100644
index 0000000..87fea9f
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/MtpPacketFuzzerUtils.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 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 <MtpStringBuffer.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <linux/usbdevice_fs.h>
+#include <sys/mman.h>
+#include <usbhost/usbhost.h>
+#include <MtpTypes.h>
+
+using namespace android;
+constexpr UrbPacketDivisionMode kUrbPacketDivisionModes[] = {FIRST_PACKET_ONLY_HEADER,
+ FIRST_PACKET_HAS_PAYLOAD};
+
+constexpr size_t kMinSize = 0;
+constexpr size_t kMaxSize = 1000;
+constexpr size_t kMaxLength = 1000;
+
+class MtpPacketFuzzerUtils {
+ protected:
+ struct usb_request mUsbRequest;
+ struct usbdevfs_urb* mUsbDevFsUrb;
+ std::string mPath;
+
+ void fillFd(int32_t& fd, FuzzedDataProvider* fdp) {
+ if (fdp->ConsumeBool()) {
+ std::string text = fdp->ConsumeRandomLengthString(kMaxLength);
+ write(fd, text.c_str(), text.length());
+ }
+ };
+
+ void fillFilePath(FuzzedDataProvider* fdp) {
+ mPath= fdp->ConsumeRandomLengthString(kMaxLength);
+ };
+
+ void fillUsbDevFsUrb(FuzzedDataProvider* fdp) {
+ mUsbDevFsUrb->type = fdp->ConsumeIntegral<unsigned char>();
+ mUsbDevFsUrb->endpoint = fdp->ConsumeIntegral<unsigned char>();
+ mUsbDevFsUrb->flags = fdp->ConsumeIntegral<uint32_t>();
+ std::vector<uint8_t> buffer =
+ fdp->ConsumeBytes<uint8_t>(fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+ mUsbDevFsUrb->buffer = static_cast<void*>(buffer.data());
+ mUsbDevFsUrb->buffer_length = buffer.size();
+ mUsbDevFsUrb->actual_length = fdp->ConsumeIntegral<uint32_t>();
+ mUsbDevFsUrb->start_frame = fdp->ConsumeIntegral<uint32_t>();
+ mUsbDevFsUrb->number_of_packets = fdp->ConsumeIntegral<uint32_t>();
+ mUsbDevFsUrb->stream_id = fdp->ConsumeIntegral<uint32_t>();
+ mUsbDevFsUrb->error_count = fdp->ConsumeIntegral<size_t>();
+ mUsbDevFsUrb->signr = fdp->ConsumeIntegral<uint32_t>();
+ std::vector<uint8_t> userBuffer = (fdp->ConsumeBytes<uint8_t>(
+ fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize)));
+ mUsbDevFsUrb->usercontext = static_cast<void*>(userBuffer.data());
+ mUsbDevFsUrb->iso_frame_desc[0].length = fdp->ConsumeIntegral<uint32_t>();
+ mUsbDevFsUrb->iso_frame_desc[0].actual_length = fdp->ConsumeIntegral<uint32_t>();
+ };
+
+ void fillUsbRequest(int32_t& fd, FuzzedDataProvider* fdp) {
+ fillUsbDevFsUrb(fdp);
+ fillFd(fd, fdp);
+ std::vector<uint8_t> buffer =
+ fdp->ConsumeBytes<uint8_t>(fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+ mUsbRequest.buffer = static_cast<void*>(buffer.data());
+ mUsbRequest.buffer_length = buffer.size();
+ mUsbRequest.actual_length = fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ mUsbRequest.max_packet_size = fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ mUsbRequest.private_data = static_cast<void*>(mUsbDevFsUrb);
+ mUsbRequest.endpoint = fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ std::vector<uint8_t> clientBuffer = (fdp->ConsumeBytes<uint8_t>(
+ fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize)));
+ mUsbRequest.client_data = static_cast<void*>(clientBuffer.data());
+ };
+
+ template <typename Object>
+ void writeHandle(Object obj, FuzzedDataProvider* fdp) {
+ MtpDevHandle handle;
+ std::vector<uint8_t> initData =
+ fdp->ConsumeBytes<uint8_t>(fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+ handle.write(initData.data(), initData.size());
+ obj->write(&handle);
+ };
+};
diff --git a/media/mtp/tests/MtpFuzzer/README.md b/media/mtp/tests/MtpFuzzer/README.md
new file mode 100644
index 0000000..7efaf67
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/README.md
@@ -0,0 +1,210 @@
+# Fuzzers for libmtp
+
+## Table of contents
++ [mtp_fuzzer](#MtpServer)
++ [mtp_host_property_fuzzer](#MtpHostProperty)
++ [mtp_device_property_fuzzer](#MtpDeviceProperty)
++ [mtp_handle_fuzzer](#MtpHandle)
++ [mtp_packet_fuzzer](#MtpPacket)
+ + [mtp_device_fuzzer](#MtpDevice)
++ [mtp_request_packet_fuzzer](#MtpRequestPacket)
++ [mtp_event_packet_fuzzer](#MtpEventPacket)
++ [mtp_response_packet_fuzzer](#MtpResponsePacket)
++ [mtp_data_packet_fuzzer](#MtpDataPacket)
+
+# <a name="MtpServer"></a> Fuzzer for MtpServer
+
+MtpServer supports the following parameters:
+1. PacketData (parameter name: "packetData")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`packetData`| `String` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mtp_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mtp_fuzzer/mtp_fuzzer corpus/ -dict=mtp_fuzzer.dict
+```
+
+# <a name="MtpHostProperty"></a> Fuzzer for MtpHostProperty
+
+MtpHostProperty supports the following parameters:
+1. Feasible Type (parameter name: "kFeasibleTypes")
+2. UrbPacket Division Mode (parameter name: "kUrbPacketDivisionModes")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+| `kFeasibleType`| 1. `MTP_TYPE_UNDEFINED`, 2. `MTP_TYPE_INT8`, 3.`MTP_TYPE_UINT8`, 4.`MTP_TYPE_INT16`, 5.`MTP_TYPE_UINT16`, 6.`MTP_TYPE_INT32`, 7.`MTP_TYPE_UINT32`, 8.`MTP_TYPE_INT64`, 9.`MTP_TYPE_UINT64`, 10.`MTP_TYPE_INT128`, 11.`MTP_TYPE_UINT128`, 12.`MTP_TYPE_AINT8`, 13.`MTP_TYPE_AUINT8`, 14.`MTP_TYPE_AINT16`, 15.`MTP_TYPE_AUINT16`, 16.`MTP_TYPE_AINT32`, 17.`MTP_TYPE_AUINT32`, 18.`MTP_TYPE_AINT64`, 19.`MTP_TYPE_AUINT64`, 20.`MTP_TYPE_AINT128`, 21.`MTP_TYPE_AUINT128`, 22.`MTP_TYPE_STR`,| Value obtained from FuzzedDataProvider|
+|`kUrbPacketDivisionMode`| 1. `FIRST_PACKET_ONLY_HEADER`, 2. `FIRST_PACKET_HAS_PAYLOAD`, |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mtp_host_property_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mtp_host_property_fuzzer/mtp_host_property_fuzzer
+```
+
+# <a name="MtpDeviceProperty"></a> Fuzzer for MtpDeviceProperty
+
+MtpDeviceProperty supports the following parameters:
+1. Feasible Type (parameter name: "kFeasibleType")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+| `kFeasibleType`| 1. `MTP_TYPE_UNDEFINED`, 2. `MTP_TYPE_INT8`, 3.`MTP_TYPE_UINT8`, 4.`MTP_TYPE_INT16`, 5.`MTP_TYPE_UINT16`, 6.`MTP_TYPE_INT32`, 7.`MTP_TYPE_UINT32`, 8.`MTP_TYPE_INT64`, 9.`MTP_TYPE_UINT64`, 10.`MTP_TYPE_INT128`, 11.`MTP_TYPE_UINT128`, 12.`MTP_TYPE_AINT8`, 13.`MTP_TYPE_AUINT8`, 14.`MTP_TYPE_AINT16`, 15.`MTP_TYPE_AUINT16`, 16.`MTP_TYPE_AINT32`, 17.`MTP_TYPE_AUINT32`, 18.`MTP_TYPE_AINT64`, 19.`MTP_TYPE_AUINT64`, 20.`MTP_TYPE_AINT128`, 21.`MTP_TYPE_AUINT128`, 22.`MTP_TYPE_STR`,| Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mtp_device_property_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mtp_device_property_fuzzer/mtp_device_property_fuzzer
+```
+
+# <a name="MtpHandle"></a>Fuzzer for MtpHandle
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mtp_handle_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mtp_handle_fuzzer/mtp_handle_fuzzer
+```
+
+# <a name="MtpPacket"></a> Fuzzer for MtpPacket
+
+MtpPacket supports the following parameters:
+1. bufferSize (parameter name: "size")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`bufferSize`| Integer `1` to `1000`, |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mtp_packet_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mtp_packet_fuzzer/mtp_packet_fuzzer
+```
+
+# <a name="MtpDevice"></a> Fuzzer for MtpDevice
+
+MtpDevice supports the following parameters:
+1. Device Name (parameter name: "deviceName")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`deviceName`| `String` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mtp_device_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mtp_device_fuzzer/mtp_device_fuzzer
+```
+
+# <a name="MtpRequestPacket"></a> Fuzzer for MtpRequestPacket
+
+MtpRequestPacket supports the following parameters:
+1. Data (parameter name: "data")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`data`| Vector of positive Integer |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mtp_request_packet_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mtp_request_packet_fuzzer/mtp_request_packet_fuzzer
+```
+
+# <a name="MtpEventPacket"></a> Fuzzer for MtpEventPacket
+
+MtpEventPacket supports the following parameters:
+1. Size (parameter name: "size")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`size`| Integer `1` to `1000`, |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mtp_event_packet_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mtp_event_packet_fuzzer/mtp_event_packet_fuzzer
+```
+
+# <a name="MtpResponsePacket"></a> Fuzzer for MtpResponsePacket
+
+MtpResponsePacket supports the following parameters:
+1. Size (parameter name: "size")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`size`| Integer `1` to `1000`, |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mtp_response_packet_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mtp_response_packet_fuzzer/mtp_response_packet_fuzzer
+```
+
+# <a name="MtpDataPacket"></a> Fuzzer for MtpDataPacket
+
+MtpDataPacket supports the following parameters:
+1. UrbPacket Division Mode (parameter name: "kUrbPacketDivisionModes")
+2. Size (parameter name: "size")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`kUrbPacketDivisionMode`| 1. `FIRST_PACKET_ONLY_HEADER`, 2. `FIRST_PACKET_HAS_PAYLOAD`, |Value obtained from FuzzedDataProvider|
+|`size`| Integer `1` to `1000`, |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mtp_data_packet_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mtp_data_packet_fuzzer/mtp_data_packet_fuzzer
+```
diff --git a/media/mtp/tests/MtpFuzzer/corpus/6-mtp-open_session_send_object_info.pkt b/media/mtp/tests/MtpFuzzer/corpus/6-mtp-open_session_send_object_info.pkt
new file mode 100644
index 0000000..71f2836
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/corpus/6-mtp-open_session_send_object_info.pkt
Binary files differ
diff --git a/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp
new file mode 100644
index 0000000..f5faf77
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2022 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 <MtpDataPacket.h>
+#include <MtpDevHandle.h>
+#include <MtpPacketFuzzerUtils.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <utils/String16.h>
+
+using namespace android;
+
+class MtpDataPacketFuzzer : MtpPacketFuzzerUtils {
+ public:
+ MtpDataPacketFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+ mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+ sizeof(struct usbdevfs_iso_packet_desc));
+ };
+ ~MtpDataPacketFuzzer() { free(mUsbDevFsUrb); };
+ void process();
+
+ private:
+ FuzzedDataProvider mFdp;
+};
+
+void MtpDataPacketFuzzer::process() {
+ MtpDataPacket mtpDataPacket;
+ while (mFdp.remaining_bytes() > 0) {
+ auto mtpDataAPI = mFdp.PickValueInArray<const std::function<void()>>({
+ [&]() { mtpDataPacket.allocate(mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize)); },
+ [&]() { mtpDataPacket.reset(); },
+ [&]() {
+ mtpDataPacket.setOperationCode(mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
+ },
+ [&]() {
+ mtpDataPacket.setTransactionID(mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
+ },
+ [&]() {
+ Int8List* result = mtpDataPacket.getAInt8();
+ delete result;
+ },
+ [&]() {
+ Int16List* result = mtpDataPacket.getAInt16();
+ delete result;
+ },
+ [&]() {
+ Int32List* result = mtpDataPacket.getAInt32();
+ delete result;
+ },
+ [&]() {
+ Int64List* result = mtpDataPacket.getAInt64();
+ delete result;
+ },
+ [&]() {
+ UInt8List* result = mtpDataPacket.getAUInt8();
+ delete result;
+ },
+ [&]() {
+ UInt16List* result = mtpDataPacket.getAUInt16();
+ delete result;
+ },
+ [&]() {
+ UInt32List* result = mtpDataPacket.getAUInt32();
+ delete result;
+ },
+ [&]() {
+ UInt64List* result = mtpDataPacket.getAUInt64();
+ delete result;
+ },
+ [&]() {
+ if (mFdp.ConsumeBool()) {
+ std::vector<uint8_t> initData =
+ mFdp.ConsumeBytes<uint8_t>(mFdp.ConsumeIntegral<uint8_t>());
+ mtpDataPacket.putAUInt8(initData.data(), initData.size());
+ } else {
+ mtpDataPacket.putAUInt8(nullptr, 0);
+ }
+ },
+ [&]() {
+ if (mFdp.ConsumeBool()) {
+ size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ uint16_t arr[size];
+ for (size_t idx = 0; idx < size; ++idx) {
+ arr[idx] = mFdp.ConsumeIntegral<uint16_t>();
+ }
+ mtpDataPacket.putAUInt16(arr, size);
+ } else {
+ mtpDataPacket.putAUInt16(nullptr, 0);
+ }
+ },
+ [&]() {
+ if (mFdp.ConsumeBool()) {
+ size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ uint32_t arr[size];
+ for (size_t idx = 0; idx < size; ++idx) {
+ arr[idx] = mFdp.ConsumeIntegral<uint32_t>();
+ }
+ mtpDataPacket.putAUInt32(arr, size);
+ } else {
+ mtpDataPacket.putAUInt32(nullptr, 0);
+ }
+ },
+ [&]() {
+ if (mFdp.ConsumeBool()) {
+ size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ uint64_t arr[size];
+ for (size_t idx = 0; idx < size; ++idx) {
+ arr[idx] = mFdp.ConsumeIntegral<uint64_t>();
+ }
+ mtpDataPacket.putAUInt64(arr, size);
+ } else {
+ mtpDataPacket.putAUInt64(nullptr, 0);
+ }
+ },
+ [&]() {
+ if (mFdp.ConsumeBool()) {
+ size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ int64_t arr[size];
+ for (size_t idx = 0; idx < size; ++idx) {
+ arr[idx] = mFdp.ConsumeIntegral<int64_t>();
+ }
+ mtpDataPacket.putAInt64(arr, size);
+ } else {
+ mtpDataPacket.putAInt64(nullptr, 0);
+ }
+ },
+ [&]() {
+ if (mFdp.ConsumeBool()) {
+ std::vector<uint16_t> arr;
+ size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ for (size_t idx = 0; idx < size; ++idx) {
+ arr.push_back(mFdp.ConsumeIntegral<uint16_t>());
+ }
+ mtpDataPacket.putAUInt16(&arr);
+ } else {
+ mtpDataPacket.putAUInt16(nullptr);
+ }
+ },
+ [&]() {
+ if (mFdp.ConsumeBool()) {
+ std::vector<uint32_t> arr;
+ size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ for (size_t idx = 0; idx < size; ++idx) {
+ arr.push_back(mFdp.ConsumeIntegral<uint32_t>());
+ }
+ mtpDataPacket.putAUInt32(&arr);
+ } else {
+ mtpDataPacket.putAUInt32(nullptr);
+ }
+ },
+
+ [&]() {
+ if (mFdp.ConsumeBool()) {
+ size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ int32_t arr[size];
+ for (size_t idx = 0; idx < size; ++idx) {
+ arr[idx] = mFdp.ConsumeIntegral<int32_t>();
+ }
+ mtpDataPacket.putAInt32(arr, size);
+ } else {
+ mtpDataPacket.putAInt32(nullptr, 0);
+ }
+ },
+ [&]() {
+ if (mFdp.ConsumeBool()) {
+ mtpDataPacket.putString(
+ (mFdp.ConsumeRandomLengthString(kMaxLength)).c_str());
+ } else {
+ mtpDataPacket.putString(static_cast<char*>(nullptr));
+ }
+ },
+ [&]() {
+ android::MtpStringBuffer sBuffer(
+ (mFdp.ConsumeRandomLengthString(kMaxLength)).c_str());
+ if (mFdp.ConsumeBool()) {
+ mtpDataPacket.getString(sBuffer);
+ } else {
+ mtpDataPacket.putString(sBuffer);
+ }
+ },
+ [&]() {
+ MtpDevHandle handle;
+ handle.start(mFdp.ConsumeBool());
+ std::string text = mFdp.ConsumeRandomLengthString(kMaxLength);
+ char* data = const_cast<char*>(text.c_str());
+ handle.read(static_cast<void*>(data), text.length());
+ if (mFdp.ConsumeBool()) {
+ mtpDataPacket.read(&handle);
+ } else if (mFdp.ConsumeBool()) {
+ mtpDataPacket.write(&handle);
+ } else {
+ std::string textData = mFdp.ConsumeRandomLengthString(kMaxLength);
+ char* Data = const_cast<char*>(textData.c_str());
+ mtpDataPacket.writeData(&handle, static_cast<void*>(Data),
+ textData.length());
+ }
+ handle.close();
+ },
+ [&]() {
+ if (mFdp.ConsumeBool()) {
+ std::string str = mFdp.ConsumeRandomLengthString(kMaxLength);
+ android::String16 s(str.c_str());
+ char16_t* data = const_cast<char16_t*>(s.string());
+ mtpDataPacket.putString(reinterpret_cast<uint16_t*>(data));
+ } else {
+ mtpDataPacket.putString(static_cast<uint16_t*>(nullptr));
+ }
+ },
+ [&]() {
+ if (mFdp.ConsumeBool()) {
+ std::vector<int8_t> data = mFdp.ConsumeBytes<int8_t>(
+ mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+ mtpDataPacket.putAInt8(data.data(), data.size());
+ } else {
+ mtpDataPacket.putAInt8(nullptr, 0);
+ }
+ },
+ [&]() {
+ if (mFdp.ConsumeBool()) {
+ std::vector<uint8_t> data = mFdp.ConsumeBytes<uint8_t>(
+ mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+ mtpDataPacket.putAUInt8(data.data(), data.size());
+ } else {
+ mtpDataPacket.putAUInt8(nullptr, 0);
+ }
+ },
+ [&]() {
+ fillFilePath(&mFdp);
+ int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+ fillUsbRequest(fd, &mFdp);
+ mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+ std::vector<int8_t> data = mFdp.ConsumeBytes<int8_t>(
+ mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+ mtpDataPacket.readData(&mUsbRequest, data.data(), data.size());
+ usb_device_close(mUsbRequest.dev);
+ },
+ [&]() {
+ fillFilePath(&mFdp);
+ int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+ fillUsbRequest(fd, &mFdp);
+ mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+ mtpDataPacket.write(
+ &mUsbRequest,
+ mFdp.PickValueInArray<UrbPacketDivisionMode>(kUrbPacketDivisionModes),
+ fd, mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
+ usb_device_close(mUsbRequest.dev);
+ },
+ [&]() {
+ fillFilePath(&mFdp);
+ int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+ fillUsbRequest(fd, &mFdp);
+ mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+ mtpDataPacket.read(&mUsbRequest);
+ usb_device_close(mUsbRequest.dev);
+ },
+ [&]() {
+ fillFilePath(&mFdp);
+ int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+ fillUsbRequest(fd, &mFdp);
+ mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+ mtpDataPacket.write(&mUsbRequest, mFdp.PickValueInArray<UrbPacketDivisionMode>(
+ kUrbPacketDivisionModes));
+ usb_device_close(mUsbRequest.dev);
+ },
+ [&]() {
+ fillFilePath(&mFdp);
+ int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+ fillUsbRequest(fd, &mFdp);
+ mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+ mtpDataPacket.readDataHeader(&mUsbRequest);
+ usb_device_close(mUsbRequest.dev);
+ },
+ [&]() {
+ fillFilePath(&mFdp);
+ int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+ fillUsbRequest(fd, &mFdp);
+ mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+ mtpDataPacket.readDataAsync(&mUsbRequest);
+ usb_device_close(mUsbRequest.dev);
+ },
+ [&]() {
+ fillFilePath(&mFdp);
+ int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+ fillUsbRequest(fd, &mFdp);
+ mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+ mtpDataPacket.readDataWait(mUsbRequest.dev);
+ usb_device_close(mUsbRequest.dev);
+ },
+ [&]() {
+ if (mFdp.ConsumeBool()) {
+ std::vector<int16_t> data;
+ for (size_t idx = 0;
+ idx < mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize); ++idx) {
+ data.push_back(mFdp.ConsumeIntegral<int16_t>());
+ }
+ mtpDataPacket.putAInt16(data.data(), data.size());
+ } else {
+ mtpDataPacket.putAInt16(nullptr, 0);
+ }
+ },
+ [&]() {
+ int32_t arr[4];
+ for (size_t idx = 0; idx < 4; ++idx) {
+ arr[idx] = mFdp.ConsumeIntegral<int32_t>();
+ }
+ mtpDataPacket.putInt128(arr);
+ },
+ [&]() { mtpDataPacket.putInt64(mFdp.ConsumeIntegral<int64_t>()); },
+ [&]() {
+ int16_t out;
+ mtpDataPacket.getInt16(out);
+ },
+ [&]() {
+ int32_t out;
+ mtpDataPacket.getInt32(out);
+ },
+ [&]() {
+ int8_t out;
+ mtpDataPacket.getInt8(out);
+ },
+ [&]() {
+ uint32_t arr[4];
+ for (size_t idx = 0; idx < 4; ++idx) {
+ arr[idx] = mFdp.ConsumeIntegral<uint32_t>();
+ }
+ if (mFdp.ConsumeBool()) {
+ mtpDataPacket.putUInt128(arr);
+ } else {
+ mtpDataPacket.getUInt128(arr);
+ }
+ },
+ [&]() { mtpDataPacket.putUInt64(mFdp.ConsumeIntegral<uint64_t>()); },
+ [&]() {
+ uint64_t out;
+ mtpDataPacket.getUInt64(out);
+ },
+ [&]() { mtpDataPacket.putInt128(mFdp.ConsumeIntegral<int64_t>()); },
+ [&]() { mtpDataPacket.putUInt128(mFdp.ConsumeIntegral<uint64_t>()); },
+ [&]() {
+ int32_t length;
+ void* data = mtpDataPacket.getData(&length);
+ free(data);
+ },
+ });
+ mtpDataAPI();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ MtpDataPacketFuzzer mtpDataPacketFuzzer(data, size);
+ mtpDataPacketFuzzer.process();
+ return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp
new file mode 100644
index 0000000..c32d28a
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2022 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 <MtpDevHandle.h>
+#include <MtpDevice.h>
+#include <MtpDeviceInfo.h>
+#include <MtpObjectInfo.h>
+#include <MtpProperty.h>
+#include <MtpStorageInfo.h>
+#include <MtpStringBuffer.h>
+#include <android-base/unique_fd.h>
+#include <fcntl.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <linux/usb/ch9.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <usbhost/usbhost.h>
+
+using namespace android;
+
+constexpr int32_t kMaxStringLength = 20;
+constexpr int32_t kMaxBytes = 200;
+constexpr int32_t kMaxDataSize = 20;
+constexpr uint16_t kWMaxPacketSize = 64;
+constexpr uint16_t kEndpointsCount = 3;
+const std::string kInputFile = "/dev/null";
+const std::string kConfigFilePath = "/data/local/tmp/config";
+
+static bool readCallback(void* data, uint32_t offset, uint32_t length, void* clientData) {
+ return true;
+}
+
+struct fdDescriptors {
+ struct usb_interface_descriptor interface;
+ struct usb_endpoint_descriptor ep[kEndpointsCount];
+};
+
+fdDescriptors writeDescriptorsToFd(int32_t fd, FuzzedDataProvider& fdp) {
+ fdDescriptors desc;
+ desc.interface.bLength = sizeof(desc.interface);
+ desc.interface.bDescriptorType = USB_DT_INTERFACE;
+ desc.interface.bInterfaceNumber = fdp.ConsumeIntegral<uint8_t>();
+ desc.interface.bNumEndpoints = kEndpointsCount;
+ desc.interface.bInterfaceClass =
+ fdp.ConsumeBool() ? USB_CLASS_STILL_IMAGE : USB_CLASS_VENDOR_SPEC;
+ desc.interface.bInterfaceSubClass = fdp.ConsumeBool() ? 1 : 0xFF;
+ desc.interface.bInterfaceProtocol = fdp.ConsumeBool() ? 1 : 0;
+ desc.interface.iInterface = fdp.ConsumeIntegral<uint8_t>();
+ for (uint16_t idx = 0; idx < kEndpointsCount; ++idx) {
+ desc.ep[idx].bLength = sizeof(desc.ep[idx]);
+ desc.ep[idx].bDescriptorType = USB_DT_ENDPOINT;
+ desc.ep[idx].bEndpointAddress = idx | (fdp.ConsumeBool() ? USB_DIR_OUT : USB_DIR_IN);
+ desc.ep[idx].bmAttributes =
+ fdp.ConsumeBool() ? USB_ENDPOINT_XFER_BULK : USB_ENDPOINT_XFER_INT;
+ desc.ep[idx].wMaxPacketSize = kWMaxPacketSize;
+ }
+ write(fd, &desc, sizeof(fdDescriptors));
+ return desc;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider fdp(data, size);
+ int32_t fd = memfd_create(kConfigFilePath.c_str(), MFD_ALLOW_SEALING);
+ fdDescriptors descriptor = writeDescriptorsToFd(fd, fdp);
+ std::string deviceName = fdp.ConsumeRandomLengthString(kMaxStringLength);
+ usb_device* device = usb_device_new(deviceName.c_str(), fd);
+ MtpDevice mtpDevice(device, fdp.ConsumeIntegral<int32_t>(), &descriptor.ep[0],
+ &descriptor.ep[1], &descriptor.ep[2]);
+ while (fdp.remaining_bytes()) {
+ auto mtpDeviceFunction = fdp.PickValueInArray<const std::function<void()>>(
+ {[&]() { mtpDevice.getStorageIDs(); },
+ [&]() {
+ mtpDevice.getStorageInfo(fdp.ConsumeIntegral<int32_t>() /* storageID */);
+ },
+ [&]() {
+ mtpDevice.getObjectHandles(fdp.ConsumeIntegral<uint32_t>() /* storageID */,
+ fdp.ConsumeIntegral<uint16_t>() /* format */,
+ fdp.ConsumeIntegral<uint32_t>() /* parent */);
+ },
+ [&]() { mtpDevice.initialize(); },
+ [&]() {
+ int32_t outLength = 0;
+ mtpDevice.getThumbnail(fdp.ConsumeIntegral<uint32_t>() /* handle */,
+ outLength);
+ },
+ [&]() {
+ MtpObjectInfo mtpObjectInfo(fdp.ConsumeIntegral<uint32_t>() /* handle */);
+ std::string name = fdp.ConsumeRandomLengthString(kMaxStringLength);
+ std::string keywords = fdp.ConsumeRandomLengthString(kMaxStringLength);
+ mtpObjectInfo.mName = strdup(name.c_str());
+ mtpObjectInfo.mKeywords = strdup(keywords.c_str());
+ mtpDevice.sendObjectInfo(&mtpObjectInfo);
+ },
+ [&]() {
+ mtpDevice.sendObject(fdp.ConsumeIntegral<uint32_t>() /* handle */,
+ fdp.ConsumeIntegral<uint32_t>() /* size */, fd);
+ },
+ [&]() { mtpDevice.deleteObject(fdp.ConsumeIntegral<uint32_t>() /* handle */); },
+ [&]() {
+ mtpDevice.getObjectPropsSupported(
+ fdp.ConsumeIntegral<uint16_t>() /* format */);
+ },
+ [&]() {
+ MtpDataType dataType = fdp.ConsumeIntegral<int16_t>();
+ MtpProperty mtpProperty(fdp.ConsumeIntegral<int16_t>() /* propCode */,
+ dataType, fdp.ConsumeBool() /* writeable */,
+ fdp.ConsumeIntegral<int32_t>() /* defaultValue */);
+ if (dataType == MTP_TYPE_STR) {
+ mtpProperty.setCurrentValue(
+ fdp.ConsumeRandomLengthString(kMaxStringLength).c_str());
+ }
+ mtpDevice.setDevicePropValueStr(&mtpProperty);
+ },
+ [&]() {
+ mtpDevice.getObjectPropDesc(fdp.ConsumeIntegral<uint16_t>() /* code */,
+ fdp.ConsumeIntegral<uint16_t>() /* format */);
+ },
+ [&]() {
+ MtpProperty property;
+ mtpDevice.getObjectPropValue(fdp.ConsumeIntegral<uint16_t>() /* handle */,
+ &property);
+ },
+ [&]() {
+ std::vector<uint8_t> clientData = fdp.ConsumeBytes<uint8_t>(kMaxDataSize);
+ mtpDevice.readObject(
+ fdp.ConsumeIntegral<uint32_t>() /* handle */, readCallback,
+ fdp.ConsumeIntegral<uint32_t>() /* objectSize */, &clientData);
+ },
+ [&]() {
+ std::vector<uint8_t> clientData = fdp.ConsumeBytes<uint8_t>(kMaxDataSize);
+ uint32_t writtenSize = 0;
+ mtpDevice.readPartialObject(fdp.ConsumeIntegral<uint32_t>() /* handle */,
+ fdp.ConsumeIntegral<uint32_t>() /* offset */,
+ fdp.ConsumeIntegral<uint32_t>() /* size */,
+ &writtenSize, readCallback, &clientData);
+ },
+ [&]() {
+ std::vector<uint8_t> clientData = fdp.ConsumeBytes<uint8_t>(kMaxDataSize);
+ uint32_t writtenSize = 0;
+ mtpDevice.readPartialObject(fdp.ConsumeIntegral<uint32_t>() /* handle */,
+ fdp.ConsumeIntegral<uint64_t>() /* offset */,
+ fdp.ConsumeIntegral<uint32_t>() /* size */,
+ &writtenSize, readCallback, &clientData);
+ },
+ [&]() {
+ if (mtpDevice.submitEventRequest() != -1) {
+ uint32_t parameters[3];
+ mtpDevice.reapEventRequest(fdp.ConsumeIntegral<int32_t>() /* handle */,
+ ¶meters);
+ }
+ },
+ [&]() {
+ mtpDevice.discardEventRequest(fdp.ConsumeIntegral<int32_t>() /*handle*/);
+ },
+ [&]() {
+ mtpDevice.discardEventRequest(fdp.ConsumeIntegral<int32_t>() /* handle */);
+ },
+ [&]() { mtpDevice.print(); },
+ [&]() { mtpDevice.getDeviceName(); },
+ [&]() { mtpDevice.getObjectInfo(fdp.ConsumeIntegral<uint32_t>() /* handle */); },
+ [&]() { mtpDevice.getParent(fdp.ConsumeIntegral<uint32_t>() /* handle */); },
+ [&]() { mtpDevice.getStorageID(fdp.ConsumeIntegral<uint32_t>() /* handle */); },
+ [&]() { mtpDevice.getDevicePropDesc(fdp.ConsumeIntegral<uint16_t>() /* code */); },
+ [&]() {
+ mtpDevice.readObject(
+ fdp.ConsumeIntegral<uint32_t>() /* handle */,
+ fdp.ConsumeRandomLengthString(kMaxStringLength).c_str() /* destPath */,
+ fdp.ConsumeIntegral<int32_t>() /* group */,
+ fdp.ConsumeIntegral<int32_t>() /* perm */);
+ },
+ [&]() {
+ int32_t filefd = open(kConfigFilePath.c_str(), O_CREAT | O_RDWR);
+ mtpDevice.readObject(fdp.ConsumeIntegral<uint16_t>() /* handle */, filefd);
+ close(filefd);
+ },
+ [&]() { MtpDevice::open(deviceName.c_str(), fd); },
+ [&]() {
+ MtpObjectInfo objectinfo(fdp.ConsumeIntegral<uint32_t>() /* handle */);
+ MtpDataPacket mtpDataPacket;
+ MtpDevHandle devHandle;
+ std::vector<uint8_t> packet = fdp.ConsumeBytes<uint8_t>(kMaxBytes);
+ mtpDataPacket.writeData(&devHandle, packet.data(), packet.size());
+ objectinfo.read(mtpDataPacket);
+ objectinfo.print();
+ },
+ [&]() {
+ MtpStorageInfo storageInfo(fdp.ConsumeIntegral<uint32_t>() /* id */);
+ MtpDataPacket mtpDataPacket;
+ MtpDevHandle devHandle;
+ std::vector<uint8_t> packet = fdp.ConsumeBytes<uint8_t>(kMaxBytes);
+ mtpDataPacket.writeData(&devHandle, packet.data(), packet.size());
+ storageInfo.read(mtpDataPacket);
+ storageInfo.print();
+ }});
+ mtpDeviceFunction();
+ }
+ close(fd);
+ return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_event_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_event_packet_fuzzer.cpp
new file mode 100644
index 0000000..3bd3be2
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_event_packet_fuzzer.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2022 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 <MtpDevHandle.h>
+#include <MtpEventPacket.h>
+#include <MtpPacketFuzzerUtils.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using namespace android;
+
+class MtpEventPacketFuzzer : MtpPacketFuzzerUtils {
+ public:
+ MtpEventPacketFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+ mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+ sizeof(struct usbdevfs_iso_packet_desc));
+ };
+ ~MtpEventPacketFuzzer() { free(mUsbDevFsUrb); };
+ void process();
+
+ private:
+ FuzzedDataProvider mFdp;
+};
+
+void MtpEventPacketFuzzer::process() {
+ MtpEventPacket mtpEventPacket;
+ while (mFdp.remaining_bytes() > 0) {
+ auto mtpEventAPI = mFdp.PickValueInArray<const std::function<void()>>({
+ [&]() { mtpEventPacket.allocate(mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize)); },
+ [&]() { mtpEventPacket.reset(); },
+ [&]() { writeHandle(&mtpEventPacket, &mFdp); },
+ [&]() {
+ fillFilePath(&mFdp);
+ int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+ fillUsbRequest(fd, &mFdp);
+ mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+ mtpEventPacket.sendRequest(&mUsbRequest);
+ usb_device_close(mUsbRequest.dev);
+ },
+ [&]() {
+ fillFilePath(&mFdp);
+ int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+ fillFd(fd, &mFdp);
+ struct usb_device* device = usb_device_new(mPath.c_str(), fd);
+ mtpEventPacket.readResponse(device);
+ usb_device_close(device);
+ },
+ });
+ mtpEventAPI();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ MtpEventPacketFuzzer mtpEventPacketFuzzer(data, size);
+ mtpEventPacketFuzzer.process();
+ return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_fuzzer.cpp
index f578462..e886816 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_fuzzer.cpp
@@ -14,12 +14,15 @@
* limitations under the License.
*/
+#include <android-base/properties.h>
#include <android-base/unique_fd.h>
+#include <fuzzer/FuzzedDataProvider.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
-
+#include <filesystem>
+#include <fstream>
#include <string>
#define LOG_TAG "MtpFuzzer"
@@ -32,38 +35,40 @@
#include "MtpStorage.h"
#include "MtpUtils.h"
-const char* storage_desc = "Fuzz Storage";
+constexpr int32_t kMinFiles = 0;
+constexpr int32_t kMaxFiles = 5;
+constexpr int32_t kMaxBytes = 128;
+constexpr float kMinDataSizeFactor = 0.8;
// prefer tmpfs for file operations to avoid wearing out flash
const char* storage_path = "/storage/fuzzer/0";
-const char* source_database = "srcdb/";
+const char* source_database = "/data/local/tmp/srcdb/";
+const std::string test_path = std::string(source_database) + "TestDir/";
+const std::string kPropertyKey = "sys.fuse.transcode_mtp";
namespace android {
class MtpMockServer {
-public:
- std::unique_ptr<MtpMockHandle> mHandle;
- std::unique_ptr<MtpStorage> mStorage;
- std::unique_ptr<MtpMockDatabase> mDatabase;
- std::unique_ptr<MtpServer> mMtp;
- int mStorageId;
-
- MtpMockServer(const char* storage_path) : mStorageId(0) {
- bool ptp = false;
- const char* manu = "Google";
- const char* model = "Pixel 3XL";
- const char* version = "1.0";
- const char* serial = "ABDEF1231";
-
+ public:
+ MtpMockServer(const uint8_t* data, size_t size) : mFdp(data, size) {
// This is unused in our harness
int controlFd = -1;
mHandle = std::make_unique<MtpMockHandle>();
- mStorage = std::make_unique<MtpStorage>(mStorageId, storage_path, storage_desc, true,
- 0x200000000L);
+ mStorage = std::make_unique<MtpStorage>(
+ mFdp.ConsumeIntegral<uint32_t>() /* storageId */, storage_path,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* descriptor */,
+ mFdp.ConsumeBool() /* removable */,
+ mFdp.ConsumeIntegral<uint64_t>() /* maxFileSize */);
mDatabase = std::make_unique<MtpMockDatabase>();
mDatabase->addStorage(mStorage.get());
- mMtp = std::make_unique<MtpServer>(mDatabase.get(), controlFd, ptp, manu, model, version,
- serial);
+ init(data, size);
+
+ mMtp = std::make_unique<MtpServer>(
+ mDatabase.get(), controlFd, mFdp.ConsumeBool() /* ptp */,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* manu */,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* model */,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* version */,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* serial */);
mMtp->addStorage(mStorage.get());
// clear the old handle first, so we don't leak memory
@@ -71,7 +76,76 @@
mMtp->mHandle = mHandle.get();
}
- void run() { mMtp->run(); }
+ void process() {
+ if (mFdp.ConsumeBool()) {
+ createDatabaseFromSourceDir(source_database, storage_path, MTP_PARENT_ROOT);
+ }
+
+ while (mFdp.remaining_bytes()) {
+ MtpStorage storage(mFdp.ConsumeIntegral<uint32_t>() /* id */,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* filePath */,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* description */,
+ mFdp.ConsumeBool() /* removable */,
+ mFdp.ConsumeIntegral<uint64_t>() /* maxFileSize */);
+
+ auto invokeMtpServerAPI = mFdp.PickValueInArray<const std::function<void()>>({
+ [&]() { mMtp->run(); },
+ [&]() { mMtp->sendObjectAdded(mFdp.ConsumeIntegral<uint32_t>()); },
+ [&]() { mMtp->sendObjectRemoved(mFdp.ConsumeIntegral<uint32_t>()); },
+ [&]() { mMtp->sendObjectInfoChanged(mFdp.ConsumeIntegral<uint32_t>()); },
+ [&]() { mMtp->sendDevicePropertyChanged(mFdp.ConsumeIntegral<uint16_t>()); },
+ [&]() { mMtp->addStorage(&storage); },
+ [&]() { mMtp->removeStorage(&storage); },
+ });
+
+ invokeMtpServerAPI();
+ }
+
+ std::filesystem::remove_all(source_database);
+ }
+
+ private:
+ void createFiles(std::string path, size_t fileCount) {
+ std::ofstream file;
+ for (size_t idx = 0; idx < fileCount; ++idx) {
+ file.open(path.append(std::to_string(idx)));
+ file.close();
+ }
+ }
+
+ void addPackets(const uint8_t* data, size_t size) {
+ size_t off = 0;
+ for (size_t i = 0; i < size; ++i) {
+ // A longer delimiter could be used, but this worked in practice
+ if (data[i] == '@') {
+ size_t pktsz = i - off;
+ if (pktsz > 0) {
+ packet_t pkt = packet_t((unsigned char*)data + off, (unsigned char*)data + i);
+ // insert into packet buffer
+ mHandle->add_packet(pkt);
+ off = i;
+ }
+ }
+ }
+ }
+
+ void init(const uint8_t* data, size_t size) {
+ std::vector<uint8_t> packetData = mFdp.ConsumeBytes<uint8_t>(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinDataSizeFactor * size, size));
+
+ // Packetize the input stream
+ addPackets(packetData.data(), packetData.size());
+
+ // Setting the property to true/false to randomly fuzz the PoC depended on it
+ base::SetProperty(kPropertyKey, mFdp.ConsumeBool() ? "true" : "false");
+
+ std::filesystem::create_directories(source_database);
+ if (mFdp.ConsumeBool()) {
+ std::filesystem::create_directories(test_path);
+ createFiles(test_path, mFdp.ConsumeIntegralInRange<size_t>(kMinFiles, kMaxFiles));
+ }
+ createFiles(source_database, mFdp.ConsumeIntegralInRange<size_t>(kMinFiles, kMaxFiles));
+ }
int createDatabaseFromSourceDir(const char* fromPath, const char* toPath,
MtpObjectHandle parentHandle) {
@@ -130,8 +204,14 @@
closedir(dir);
return ret;
}
+
+ FuzzedDataProvider mFdp;
+ std::unique_ptr<MtpMockHandle> mHandle;
+ std::unique_ptr<MtpStorage> mStorage;
+ std::unique_ptr<MtpMockDatabase> mDatabase;
+ std::unique_ptr<MtpServer> mMtp;
};
-}; // namespace android
+}; // namespace android
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) __attribute__((optnone)) {
// reset our storage (from MtpUtils.h)
@@ -140,26 +220,9 @@
android::makeFolder(storage_path);
std::unique_ptr<android::MtpMockServer> mtp =
- std::make_unique<android::MtpMockServer>(storage_path);
+ std::make_unique<android::MtpMockServer>(data, size);
+ mtp->process();
- size_t off = 0;
-
- // Packetize the input stream
- for (size_t i = 0; i < size; i++) {
- // A longer delimiter could be used, but this worked in practice
- if (data[i] == '@') {
- size_t pktsz = i - off;
- if (pktsz > 0) {
- packet_t pkt = packet_t((unsigned char*)data + off, (unsigned char*)data + i);
- // insert into packet buffer
- mtp->mHandle->add_packet(pkt);
- off = i;
- }
- }
- }
-
- mtp->createDatabaseFromSourceDir(source_database, storage_path, MTP_PARENT_ROOT);
- mtp->run();
-
+ std::filesystem::remove_all("/storage/fuzzer");
return 0;
}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_handle_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_handle_fuzzer.cpp
new file mode 100644
index 0000000..7dcdc3f
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_handle_fuzzer.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2022 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 <MtpDescriptors.h>
+#include <MtpFfsCompatHandle.h>
+#include <android-base/file.h>
+#include <fcntl.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <mtp.h>
+
+using namespace android;
+
+constexpr int32_t kMaxStringLength = 64;
+constexpr int32_t kMinAPICase = 0;
+constexpr int32_t kMaxMtpHandleAPI = 5;
+constexpr int32_t kMinBufferSize = 0;
+constexpr uint32_t kMaxMtpFileSize = 0xFFFFFFFF;
+constexpr float kDataSizeFactor = 0.1;
+
+const std::string kTempPath = "/data/local/tmp/";
+const std::string kFuzzerUsbDirPath = kTempPath + "usb-ffs";
+const std::string kFuzzerMtpPath = kFuzzerUsbDirPath + "/mtp";
+const std::string kFuzzerPtpPath = kFuzzerUsbDirPath + "/ptp";
+const std::string kFuzzerTestFile = kTempPath + "FuzzerTestDescriptorFile";
+const std::string kFuzzerMtpInputFile = kTempPath + "FuzzerMtpInputFile";
+const std::string kFuzzerMtpOutputFile = kTempPath + "FuzzerMtpOutputFile";
+
+const std::string kDeviceFilePaths[] = {FFS_MTP_EP0, FFS_MTP_EP_IN, FFS_MTP_EP_INTR,
+ FFS_PTP_EP0, FFS_PTP_EP_IN, FFS_PTP_EP_INTR,
+ FFS_MTP_EP_OUT, FFS_PTP_EP_OUT};
+
+class MtpFfsHandleFuzzer {
+ public:
+ MtpFfsHandleFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+ mDataSize = kDataSizeFactor * size;
+ createFiles();
+ };
+ void process();
+
+ ~MtpFfsHandleFuzzer() { removeFiles(); };
+
+ private:
+ FuzzedDataProvider mFdp;
+ void invokeWriteDescriptor();
+ void invokeMtpFfsHandle();
+ void createFiles();
+ void removeFiles();
+ void createDeviceFile(const char* file);
+ void writeDeviceFile(const char* file);
+ int32_t writeInputFile(int32_t fd);
+ uint32_t mDataSize = 0;
+};
+
+int32_t MtpFfsHandleFuzzer::writeInputFile(int32_t fd) {
+ uint32_t minFileSize = std::min((uint32_t)MTP_BUFFER_SIZE, mDataSize);
+ uint32_t maxFileSize = std::min(mDataSize, kMaxMtpFileSize);
+ std::vector<char> dataBuffer = mFdp.ConsumeBytes<char>(
+ mFdp.ConsumeIntegralInRange<uint32_t>(minFileSize, maxFileSize));
+ write(fd, dataBuffer.data(), dataBuffer.size());
+ lseek(fd, 0, SEEK_SET);
+ return dataBuffer.size();
+}
+
+void MtpFfsHandleFuzzer::createDeviceFile(const char* file) {
+ int32_t fd = open(file, O_CREAT | O_RDWR | O_NONBLOCK);
+ close(fd);
+}
+
+void MtpFfsHandleFuzzer::writeDeviceFile(const char* file) {
+ int32_t fd = open(file, O_RDWR | O_NONBLOCK);
+ writeInputFile(fd);
+ close(fd);
+}
+
+void MtpFfsHandleFuzzer::createFiles() {
+ mkdir(kFuzzerUsbDirPath.c_str(), 0755);
+ mkdir(kFuzzerMtpPath.c_str(), 0755);
+ mkdir(kFuzzerPtpPath.c_str(), 0755);
+
+ for (auto path : kDeviceFilePaths) {
+ createDeviceFile(path.c_str());
+ }
+
+ writeDeviceFile(FFS_MTP_EP_OUT);
+ writeDeviceFile(FFS_PTP_EP_OUT);
+}
+
+void MtpFfsHandleFuzzer::removeFiles() {
+ for (auto path : kDeviceFilePaths) {
+ remove(path.c_str());
+ }
+
+ rmdir(kFuzzerMtpPath.c_str());
+ rmdir(kFuzzerPtpPath.c_str());
+ rmdir(kFuzzerUsbDirPath.c_str());
+}
+
+void MtpFfsHandleFuzzer::invokeWriteDescriptor() {
+ while (mFdp.remaining_bytes() > 0) {
+ int32_t controlFd = mFdp.ConsumeBool()
+ ? -1 /* Invalid fd*/
+ : open(kFuzzerTestFile.c_str(), O_CREAT | O_RDWR | O_NONBLOCK);
+ std::unique_ptr<MtpFfsHandle> handle(new MtpFfsHandle(controlFd));
+ handle->writeDescriptors(mFdp.ConsumeBool());
+ handle->close();
+ close(controlFd);
+ remove(kFuzzerTestFile.c_str());
+ }
+}
+
+void MtpFfsHandleFuzzer::invokeMtpFfsHandle() {
+ while (mFdp.remaining_bytes() > 0) {
+ int32_t controlFd = open(kFuzzerTestFile.c_str(), O_CREAT | O_RDWR | O_NONBLOCK);
+ writeInputFile(controlFd);
+
+ std::unique_ptr<IMtpHandle> handle;
+ if (mFdp.ConsumeBool()) {
+ std::unique_ptr<IMtpHandle> mtpCompactHandle(new MtpFfsCompatHandle(controlFd));
+ handle = std::move(mtpCompactHandle);
+ } else {
+ std::unique_ptr<IMtpHandle> mtpHandle(new MtpFfsHandle(controlFd));
+ handle = std::move(mtpHandle);
+ }
+
+ int32_t mtpHandle = mFdp.ConsumeIntegralInRange<size_t>(kMinAPICase, kMaxMtpHandleAPI);
+ switch (mtpHandle) {
+ case 0: {
+ handle->start(mFdp.ConsumeBool());
+ break;
+ }
+ case 1: {
+ std::string data = mFdp.ConsumeRandomLengthString(MTP_BUFFER_SIZE);
+ handle->write(data.c_str(), data.length());
+ break;
+ }
+ case 2: {
+ int32_t bufferSize =
+ mFdp.ConsumeIntegralInRange<size_t>(kMinBufferSize, MTP_BUFFER_SIZE);
+ uint8_t buffer[bufferSize + 1];
+ handle->read(buffer, bufferSize);
+ break;
+ }
+ case 3: {
+ mtp_file_range mfr;
+ mfr.fd = open(kFuzzerMtpInputFile.c_str(), O_CREAT | O_RDWR | O_NONBLOCK);
+ mfr.length = writeInputFile(mfr.fd);
+ mfr.offset = 0; /* Offset point to the start of the file */
+ mfr.command = mFdp.ConsumeIntegral<uint16_t>();
+ mfr.transaction_id = mFdp.ConsumeIntegral<uint32_t>();
+ handle->sendFile(mfr);
+ close(mfr.fd);
+ remove(kFuzzerMtpInputFile.c_str());
+ break;
+ }
+ case 4: {
+ struct mtp_event event;
+ std::string dataValue = mFdp.ConsumeRandomLengthString(kMaxStringLength);
+ event.data = const_cast<char*>(dataValue.c_str());
+ event.length = dataValue.length();
+ handle->sendEvent(event);
+ break;
+ }
+ case 5:
+ default: {
+ mtp_file_range mfr;
+ mfr.fd = open(kFuzzerMtpOutputFile.c_str(), O_CREAT | O_RDWR | O_NONBLOCK);
+ mfr.offset = 0; /* Offset point to the start of the file */
+ mfr.length = kMaxMtpFileSize;
+ handle->receiveFile(mfr, mFdp.ConsumeBool());
+ close(mfr.fd);
+ remove(kFuzzerMtpOutputFile.c_str());
+ break;
+ }
+ }
+ handle->close();
+ close(controlFd);
+ remove(kFuzzerTestFile.c_str());
+ }
+}
+
+void MtpFfsHandleFuzzer::process() {
+ if (mFdp.ConsumeBool()) {
+ invokeMtpFfsHandle();
+ } else {
+ invokeWriteDescriptor();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ MtpFfsHandleFuzzer mtpFfsHandleFuzzer(data, size);
+ mtpFfsHandleFuzzer.process();
+ return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp
new file mode 100644
index 0000000..6fc2a96
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2022 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 <MtpDevHandle.h>
+#include <MtpPacket.h>
+#include <MtpPacketFuzzerUtils.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using namespace android;
+
+class MtpPacketFuzzer : MtpPacketFuzzerUtils {
+ public:
+ MtpPacketFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+ mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+ sizeof(struct usbdevfs_iso_packet_desc));
+ };
+ ~MtpPacketFuzzer() { free(mUsbDevFsUrb); };
+ void process();
+
+ private:
+ FuzzedDataProvider mFdp;
+};
+
+void MtpPacketFuzzer::process() {
+ MtpPacket mtpPacket(mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize)); /*bufferSize*/
+ while (mFdp.remaining_bytes() > 0) {
+ auto mtpPacketAPI = mFdp.PickValueInArray<const std::function<void()>>({
+ [&]() {
+ mtpPacket.allocate(mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+ },
+ [&]() { mtpPacket.reset(); },
+ [&]() { mtpPacket.getContainerType(); },
+ [&]() { mtpPacket.getContainerCode(); },
+ [&]() { mtpPacket.dump(); },
+ [&]() { mtpPacket.getTransactionID(); },
+ [&]() {
+ mtpPacket.setContainerCode(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize));
+ },
+ [&]() {
+ mtpPacket.setTransactionID(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize));
+ },
+ [&]() {
+ mtpPacket.getParameter(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize));
+ },
+ [&]() {
+ mtpPacket.setParameter(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize),
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize));
+ },
+ [&]() {
+ MtpPacket testMtpPacket(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize));
+ testMtpPacket.copyFrom(mtpPacket);
+ },
+ [&]() {
+ fillFilePath(&mFdp);
+ int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+ fillUsbRequest(fd, &mFdp);
+ mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+ mtpPacket.transfer(&mUsbRequest);
+ usb_device_close(mUsbRequest.dev);
+ },
+ });
+ mtpPacketAPI();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ MtpPacketFuzzer mtpPacketFuzzer(data, size);
+ mtpPacketFuzzer.process();
+ return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
new file mode 100644
index 0000000..b4e659c
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2022 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 <MtpDataPacket.h>
+#include <MtpDevHandle.h>
+#include <MtpPacketFuzzerUtils.h>
+#include <MtpProperty.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <utils/String16.h>
+
+using namespace android;
+
+constexpr uint16_t kFeasibleTypes[] = {
+ MTP_TYPE_UNDEFINED, MTP_TYPE_INT8, MTP_TYPE_UINT8, MTP_TYPE_INT16, MTP_TYPE_UINT16,
+ MTP_TYPE_INT32, MTP_TYPE_UINT32, MTP_TYPE_INT64, MTP_TYPE_UINT64, MTP_TYPE_INT128,
+ MTP_TYPE_UINT128, MTP_TYPE_AINT8, MTP_TYPE_AUINT8, MTP_TYPE_AINT16, MTP_TYPE_AUINT16,
+ MTP_TYPE_AINT32, MTP_TYPE_AUINT32, MTP_TYPE_AINT64, MTP_TYPE_AUINT64, MTP_TYPE_AINT128,
+ MTP_TYPE_AUINT128, MTP_TYPE_STR,
+};
+
+class MtpPropertyFuzzer : MtpPacketFuzzerUtils {
+ public:
+ MtpPropertyFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+ mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+ sizeof(struct usbdevfs_iso_packet_desc));
+ };
+ ~MtpPropertyFuzzer() { free(mUsbDevFsUrb); };
+ void process();
+
+ private:
+ FuzzedDataProvider mFdp;
+};
+
+void MtpPropertyFuzzer::process() {
+ MtpProperty* mtpProperty = nullptr;
+ if (mFdp.ConsumeBool()) {
+ mtpProperty = new MtpProperty();
+ } else {
+ uint16_t type = mFdp.ConsumeBool() ? mFdp.ConsumeIntegral<uint16_t>()
+ : mFdp.PickValueInArray<uint16_t>(kFeasibleTypes);
+ mtpProperty = new MtpProperty(mFdp.ConsumeIntegral<uint16_t>(), type, mFdp.ConsumeBool(),
+ mFdp.ConsumeIntegral<uint16_t>());
+ }
+
+ while (mFdp.remaining_bytes() > 0) {
+ auto invokeMtpPropertyFuzzer = mFdp.PickValueInArray<const std::function<void()>>({
+ [&]() {
+ MtpDataPacket mtpDataPacket;
+ if (mFdp.ConsumeBool()) {
+ mtpProperty->read(mtpDataPacket);
+
+ } else {
+ if (mFdp.ConsumeBool()) {
+#ifdef MTP_DEVICE
+ android::IMtpHandle* h = new MtpDevHandle();
+ h->start(mFdp.ConsumeBool());
+ std::string text = mFdp.ConsumeRandomLengthString(kMaxLength);
+ char* data = const_cast<char*>(text.c_str());
+ h->read(static_cast<void*>(data), text.length());
+ mtpDataPacket.write(h);
+ h->close();
+ delete h;
+#endif
+
+#ifdef MTP_HOST
+ fillFilePath(&mFdp);
+ int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+ fillUsbRequest(fd, &mFdp);
+ mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+ mtpDataPacket.write(&mUsbRequest,
+ mFdp.PickValueInArray<UrbPacketDivisionMode>(
+ kUrbPacketDivisionModes),
+ fd,
+ mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
+ usb_device_close(mUsbRequest.dev);
+#endif
+ }
+
+ if (mFdp.ConsumeBool()) {
+ mtpProperty->write(mtpDataPacket);
+ } else {
+ mtpProperty->setCurrentValue(mtpDataPacket);
+ }
+ }
+ },
+ [&]() {
+ char16_t* data = nullptr;
+ std::string str = mFdp.ConsumeRandomLengthString(kMaxLength);
+ android::String16 s(str.c_str());
+ if (mFdp.ConsumeBool()) {
+ data = const_cast<char16_t*>(s.string());
+ }
+
+ if (mFdp.ConsumeBool()) {
+ mtpProperty->setDefaultValue(reinterpret_cast<uint16_t*>(data));
+ } else if (mFdp.ConsumeBool()) {
+ mtpProperty->setCurrentValue(reinterpret_cast<uint16_t*>(data));
+ } else {
+ mtpProperty->setCurrentValue(str.c_str());
+ }
+ },
+ [&]() {
+ mtpProperty->setFormRange(mFdp.ConsumeIntegral<int32_t>(),
+ mFdp.ConsumeIntegral<int32_t>(),
+ mFdp.ConsumeIntegral<int32_t>());
+ },
+ [&]() {
+ std::vector<int32_t> init;
+ for (size_t idx = 0; idx < mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize);
+ ++idx) {
+ init.push_back(mFdp.ConsumeIntegral<int32_t>());
+ }
+ mtpProperty->setFormEnum(init.data(), init.size());
+ },
+ });
+ invokeMtpPropertyFuzzer();
+ }
+
+ delete (mtpProperty);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ MtpPropertyFuzzer mtpPropertyFuzzer(data, size);
+ mtpPropertyFuzzer.process();
+ return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_request_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_request_packet_fuzzer.cpp
new file mode 100644
index 0000000..19fbc5b
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_request_packet_fuzzer.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 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 <MtpDevHandle.h>
+#include <MtpPacketFuzzerUtils.h>
+#include <MtpRequestPacket.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <fstream>
+
+using namespace android;
+
+std::string kMtpDevPath = "/dev/mtp_usb";
+constexpr int32_t kMaxBytes = 100000;
+
+class MtpRequestPacketFuzzer : MtpPacketFuzzerUtils {
+ public:
+ MtpRequestPacketFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+ mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+ sizeof(struct usbdevfs_iso_packet_desc));
+ };
+ ~MtpRequestPacketFuzzer() { free(mUsbDevFsUrb); };
+ void process();
+
+ private:
+ FuzzedDataProvider mFdp;
+ void makeFile(std::string s);
+};
+
+void MtpRequestPacketFuzzer::process() {
+ MtpRequestPacket mtpRequestPacket;
+ while (mFdp.remaining_bytes() > 0) {
+ auto mtpRequestAPI = mFdp.PickValueInArray<const std::function<void()>>({
+ [&]() {
+ mtpRequestPacket.allocate(mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
+ },
+ [&]() { mtpRequestPacket.reset(); },
+ [&]() {
+ MtpDevHandle handle;
+ makeFile(kMtpDevPath);
+ handle.start(mFdp.ConsumeBool());
+ std::vector<uint8_t> data = mFdp.ConsumeBytes<uint8_t>(
+ mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+ handle.write(data.data(), data.size());
+ mtpRequestPacket.read(&handle);
+ handle.close();
+ remove(kMtpDevPath.c_str());
+ },
+ [&]() {
+ fillFilePath(&mFdp);
+ int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+ fillUsbRequest(fd, &mFdp);
+ mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+ mtpRequestPacket.write(&mUsbRequest);
+ usb_device_close(mUsbRequest.dev);
+ },
+ });
+ mtpRequestAPI();
+ }
+}
+
+void MtpRequestPacketFuzzer::makeFile(std::string s) {
+ std::ofstream out;
+ out.open(s, std::ios::binary | std::ofstream::trunc);
+ for (int32_t idx = 0; idx < mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize); ++idx) {
+ out << mFdp.ConsumeRandomLengthString(kMaxBytes) << "\n";
+ }
+ out.close();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ MtpRequestPacketFuzzer mtpRequestPacketFuzzer(data, size);
+ mtpRequestPacketFuzzer.process();
+ return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_response_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_response_packet_fuzzer.cpp
new file mode 100644
index 0000000..697785f
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_response_packet_fuzzer.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 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 <MtpDevHandle.h>
+#include <MtpPacketFuzzerUtils.h>
+#include <MtpResponsePacket.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using namespace android;
+
+class MtpResponsePacketFuzzer : MtpPacketFuzzerUtils {
+ public:
+ MtpResponsePacketFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+ mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+ sizeof(struct usbdevfs_iso_packet_desc));
+ };
+ ~MtpResponsePacketFuzzer() { free(mUsbDevFsUrb); };
+ void process();
+
+ private:
+ FuzzedDataProvider mFdp;
+};
+
+void MtpResponsePacketFuzzer::process() {
+ MtpResponsePacket mtpResponsePacket;
+ while (mFdp.remaining_bytes() > 0) {
+ auto mtpResponseAPI = mFdp.PickValueInArray<const std::function<void()>>({
+ [&]() {
+ mtpResponsePacket.allocate(
+ mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize)); /*size*/
+ },
+ [&]() { mtpResponsePacket.reset(); },
+ [&]() { writeHandle(&mtpResponsePacket, &mFdp); },
+ [&]() {
+ fillFilePath(&mFdp);
+ int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+ fillUsbRequest(fd, &mFdp);
+ mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+ mtpResponsePacket.read(&mUsbRequest);
+ usb_device_close(mUsbRequest.dev);
+ },
+ });
+ mtpResponseAPI();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ MtpResponsePacketFuzzer mtpResponsePacketFuzzer(data, size);
+ mtpResponsePacketFuzzer.process();
+ return 0;
+}
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index ddc71db..fded4f5 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -52,6 +52,9 @@
symbol_file: "libmediandk.map.txt",
first_version: "21",
unversioned_until: "current",
+ export_header_libs: [
+ "libmediandk_headers",
+ ],
}
ndk_headers {
@@ -167,7 +170,7 @@
stubs: {
symbol_file: "libmediandk.map.txt",
versions: ["29"],
- }
+ },
}
cc_library {
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index f4674de..0df7636 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -253,7 +253,7 @@
}
static sp<IDrm> CreateDrm() {
- return DrmUtils::MakeDrm();
+ return DrmUtils::MakeDrm(IDRM_NDK);
}
@@ -758,6 +758,9 @@
EXPORT
media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj,
const char *propertyName, const uint8_t *value, size_t valueSize) {
+ if (!mObj || mObj->mDrm == NULL) {
+ return AMEDIA_ERROR_INVALID_OBJECT;
+ }
Vector<uint8_t> byteArray;
byteArray.appendArray(value, valueSize);
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 923453a..a95e874 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -147,38 +147,80 @@
EXPORT
bool AMediaFormat_getInt32(AMediaFormat* format, const char *name, int32_t *out) {
+ if (format == nullptr) {
+ return false;
+ }
+ if (name == nullptr) {
+ return false;
+ }
return format->mFormat->findInt32(name, out);
}
EXPORT
bool AMediaFormat_getInt64(AMediaFormat* format, const char *name, int64_t *out) {
+ if (format == nullptr) {
+ return false;
+ }
+ if (name == nullptr) {
+ return false;
+ }
return format->mFormat->findInt64(name, out);
}
EXPORT
bool AMediaFormat_getFloat(AMediaFormat* format, const char *name, float *out) {
+ if (format == nullptr) {
+ return false;
+ }
+ if (name == nullptr) {
+ return false;
+ }
return format->mFormat->findFloat(name, out);
}
EXPORT
bool AMediaFormat_getDouble(AMediaFormat* format, const char *name, double *out) {
+ if (format == nullptr) {
+ return false;
+ }
+ if (name == nullptr) {
+ return false;
+ }
return format->mFormat->findDouble(name, out);
}
EXPORT
bool AMediaFormat_getSize(AMediaFormat* format, const char *name, size_t *out) {
+ if (format == nullptr) {
+ return false;
+ }
+ if (name == nullptr) {
+ return false;
+ }
return format->mFormat->findSize(name, out);
}
EXPORT
bool AMediaFormat_getRect(AMediaFormat* format, const char *name,
int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) {
+ if (format == nullptr) {
+ return false;
+ }
+ if (name == nullptr) {
+ return false;
+ }
return format->mFormat->findRect(name, left, top, right, bottom);
}
EXPORT
bool AMediaFormat_getBuffer(AMediaFormat* format, const char *name, void** data, size_t *outsize) {
sp<ABuffer> buf;
+ if (format == nullptr) {
+ return false;
+ }
+ if (name == nullptr) {
+ return false;
+ }
if (format->mFormat->findBuffer(name, &buf)) {
*data = buf->data() + buf->offset();
*outsize = buf->size();
@@ -189,7 +231,12 @@
EXPORT
bool AMediaFormat_getString(AMediaFormat* mData, const char *name, const char **out) {
-
+ if (mData == nullptr) {
+ return false;
+ }
+ if (name == nullptr) {
+ return false;
+ }
for (size_t i = 0; i < mData->mStringCache.size(); i++) {
if (strcmp(mData->mStringCache.keyAt(i).string(), name) == 0) {
mData->mStringCache.removeItemsAt(i, 1);
@@ -212,43 +259,91 @@
EXPORT
void AMediaFormat_setInt32(AMediaFormat* format, const char *name, int32_t value) {
+ if (format == nullptr) {
+ return;
+ }
+ if (name == nullptr) {
+ return;
+ }
format->mFormat->setInt32(name, value);
}
EXPORT
void AMediaFormat_setInt64(AMediaFormat* format, const char *name, int64_t value) {
+ if (format == nullptr) {
+ return;
+ }
+ if (name == nullptr) {
+ return;
+ }
format->mFormat->setInt64(name, value);
}
EXPORT
void AMediaFormat_setFloat(AMediaFormat* format, const char* name, float value) {
+ if (format == nullptr) {
+ return;
+ }
+ if (name == nullptr) {
+ return;
+ }
format->mFormat->setFloat(name, value);
}
EXPORT
void AMediaFormat_setDouble(AMediaFormat* format, const char* name, double value) {
+ if (format == nullptr) {
+ return;
+ }
+ if (name == nullptr) {
+ return;
+ }
format->mFormat->setDouble(name, value);
}
EXPORT
void AMediaFormat_setSize(AMediaFormat* format, const char* name, size_t value) {
+ if (format == nullptr) {
+ return;
+ }
+ if (name == nullptr) {
+ return;
+ }
format->mFormat->setSize(name, value);
}
EXPORT
void AMediaFormat_setRect(AMediaFormat* format, const char *name,
int32_t left, int32_t top, int32_t right, int32_t bottom) {
+ if (format == nullptr) {
+ return;
+ }
+ if (name == nullptr) {
+ return;
+ }
format->mFormat->setRect(name, left, top, right, bottom);
}
EXPORT
void AMediaFormat_setString(AMediaFormat* format, const char* name, const char* value) {
+ if (format == nullptr) {
+ return;
+ }
+ if (name == nullptr) {
+ return;
+ }
// AMessage::setString() makes a copy of the string
format->mFormat->setString(name, value, strlen(value));
}
EXPORT
void AMediaFormat_setBuffer(AMediaFormat* format, const char* name, const void* data, size_t size) {
+ if (format == nullptr) {
+ return;
+ }
+ if (name == nullptr) {
+ return;
+ }
// the ABuffer(void*, size_t) constructor doesn't take ownership of the data, so create
// a new buffer and copy the data into it
sp<ABuffer> buf = new ABuffer(size);
diff --git a/media/ndk/NdkMediaMuxer.cpp b/media/ndk/NdkMediaMuxer.cpp
index 1965e62..9d62884 100644
--- a/media/ndk/NdkMediaMuxer.cpp
+++ b/media/ndk/NdkMediaMuxer.cpp
@@ -46,7 +46,7 @@
if (mData == nullptr) {
return nullptr;
}
- mData->mImpl = new (std::nothrow) MediaMuxer(fd, (android::MediaMuxer::OutputFormat)format);
+ mData->mImpl = MediaMuxer::create(fd, (MediaMuxer::OutputFormat)format);
if (mData->mImpl == nullptr) {
delete mData;
return nullptr;
diff --git a/media/ndk/include/media/NdkMediaDrm.h b/media/ndk/include/media/NdkMediaDrm.h
index 4eca3d7..8044140 100644
--- a/media/ndk/include/media/NdkMediaDrm.h
+++ b/media/ndk/include/media/NdkMediaDrm.h
@@ -261,8 +261,8 @@
/**
* Open a new session with the MediaDrm object. A session ID is returned.
*
- * Returns MEDIADRM_NOT_PROVISIONED_ERROR if provisioning is needed.
- * Returns MEDIADRM_RESOURCE_BUSY_ERROR if required resources are in use.
+ * Returns AMEDIA_DRM_NOT_PROVISIONED if provisioning is needed.
+ * Returns AMEDIA_DRM_RESOURCE_BUSY if required resources are in use.
*
* Available since API level 21.
*/
@@ -327,7 +327,7 @@
* 2. keyRequestSize will be set to the size of the request
* If this does not return AMEDIA_OK, value of these parameters should not be used.
*
- * Returns MEDIADRM_NOT_PROVISIONED_ERROR if reprovisioning is needed, due to a
+ * Returns AMEDIA_DRM_NOT_PROVISIONED if reprovisioning is needed, due to a
* problem with the device certificate.
*
* Available since API level 21.
@@ -390,7 +390,7 @@
* 4. keyRequestType will be set to the key request type. Passing in NULL means
* you don't need it to be reported.
*
- * Returns MEDIADRM_NOT_PROVISIONED_ERROR if reprovisioning is needed, due to a
+ * Returns AMEDIA_DRM_NOT_PROVISIONED if reprovisioning is needed, due to a
* problem with the device certificate.
*
* Available since API level 33.
@@ -457,7 +457,7 @@
* On entry, numPairs should be set by the caller to the maximum number of pairs
* that can be returned (the size of the array). On exit, numPairs will be set
* to the number of entries written to the array. If the number of {key, value} pairs
- * to be returned is greater than *numPairs, MEDIADRM_SHORT_BUFFER will be returned
+ * to be returned is greater than *numPairs, AMEDIA_DRM_SHORT_BUFFER will be returned
* and numPairs will be set to the number of pairs available.
*
* Available since API level 21.
@@ -495,7 +495,7 @@
* DRM engine plugin.
* responseSize is the length of the provisioning response in bytes.
*
- * Returns MEDIADRM_DEVICE_REVOKED_ERROR if the response indicates that the
+ * Returns AMEDIA_DRM_DEVICE_REVOKED if the response indicates that the
* server rejected the request
*
* Available since API level 21.
@@ -522,7 +522,7 @@
* numSecureStops is set by the caller to the maximum number of secure stops to
* return. On exit, *numSecureStops will be set to the number actually returned.
* If *numSecureStops is too small for the number of secure stops available,
- * MEDIADRM_SHORT_BUFFER will be returned and *numSecureStops will be set to the
+ * AMEDIA_DRM_SHORT_BUFFER will be returned and *numSecureStops will be set to the
* number required.
*
* Available since API level 21.
@@ -657,7 +657,7 @@
* Generate a signature using the specified macAlgorithm over the message data
* referenced by message of size messageSize and store the signature in the
* buffer referenced signature of max size *signatureSize. If the buffer is not
- * large enough to hold the signature, MEDIADRM_SHORT_BUFFER is returned and
+ * large enough to hold the signature, AMEDIA_DRM_SHORT_BUFFER is returned and
* *signatureSize is set to the buffer size required. The key to use is identified
* by the 16 byte keyId. The key must have been loaded into the session using
* provideKeyResponse.
@@ -670,7 +670,7 @@
/*
* Perform a signature verification using the specified macAlgorithm over the message
- * data referenced by the message parameter of size messageSize. Returns MEDIADRM_OK
+ * data referenced by the message parameter of size messageSize. Returns AMEDIA_OK
* if the signature matches, otherwise MEDAIDRM_VERIFY_FAILED is returned. The key to
* use is identified by the 16 byte keyId. The key must have been loaded into the
* session using provideKeyResponse.
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index c8faced..c0eea63 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -181,11 +181,11 @@
AMediaCodecCryptoInfo_setPattern; # introduced=24
AMediaCodec_configure;
AMediaCodec_createCodecByName;
- AMediaCodec_createCodecByNameForClient; # apex # introduced=31
+ AMediaCodec_createCodecByNameForClient; # systemapi # introduced=31
AMediaCodec_createDecoderByType;
- AMediaCodec_createDecoderByTypeForClient; # apex # introduced=31
+ AMediaCodec_createDecoderByTypeForClient; # systemapi # introduced=31
AMediaCodec_createEncoderByType;
- AMediaCodec_createEncoderByTypeForClient; # apex # introduced=31
+ AMediaCodec_createEncoderByTypeForClient; # systemapi # introduced=31
AMediaCodec_delete;
AMediaCodec_dequeueInputBuffer;
AMediaCodec_dequeueOutputBuffer;
diff --git a/media/ndk/tests/NdkMediaFormat_test.cpp b/media/ndk/tests/NdkMediaFormat_test.cpp
index 668d0a4..18690b8 100644
--- a/media/ndk/tests/NdkMediaFormat_test.cpp
+++ b/media/ndk/tests/NdkMediaFormat_test.cpp
@@ -51,6 +51,13 @@
EXPECT_FALSE(AMediaFormat_getInt64(fmt1, "five", &i64));
EXPECT_EQ(i32, 5);
+ // verify detecting some bad parameters.
+ AMediaFormat_setInt32(nullptr, "whatever", 6);
+ AMediaFormat_setInt32(fmt1, nullptr, 6);
+
+ EXPECT_FALSE(AMediaFormat_getInt32(nullptr, "whatever", &i32));
+ EXPECT_FALSE(AMediaFormat_getInt32(fmt1, nullptr, &i32));
+
AMediaFormat_delete(fmt1);
}
@@ -67,6 +74,13 @@
EXPECT_FALSE(AMediaFormat_getInt64(fmt1, "five", &i64));
EXPECT_EQ(i64, -1);
+ // verify detecting some bad parameters.
+ AMediaFormat_setInt64(nullptr, "whatever", 6);
+ AMediaFormat_setInt64(fmt1, nullptr, 6);
+
+ EXPECT_FALSE(AMediaFormat_getInt64(nullptr, "whatever", &i64));
+ EXPECT_FALSE(AMediaFormat_getInt64(fmt1, nullptr, &i64));
+
AMediaFormat_delete(fmt1);
}
@@ -80,6 +94,13 @@
EXPECT_TRUE(AMediaFormat_getSize(fmt1, "medium", &size));
EXPECT_EQ(size, 10);
+ // verify detecting some bad parameters.
+ AMediaFormat_setSize(nullptr, "whatever", 6);
+ AMediaFormat_setSize(fmt1, nullptr, 6);
+
+ EXPECT_FALSE(AMediaFormat_getSize(nullptr, "whatever", &size));
+ EXPECT_FALSE(AMediaFormat_getSize(fmt1, nullptr, &size));
+
AMediaFormat_delete(fmt1);
}
@@ -90,6 +111,14 @@
AMediaFormat_setFloat(fmt1, "ship", 0.5);
EXPECT_TRUE(AMediaFormat_getFloat(fmt1, "boat", &f));
EXPECT_EQ(f, 1.5);
+
+ // verify detecting some bad parameters.
+ AMediaFormat_setFloat(nullptr, "whatever", 1.5);
+ AMediaFormat_setFloat(fmt1, nullptr, 1.5);
+
+ EXPECT_FALSE(AMediaFormat_getFloat(nullptr, "whatever", &f));
+ EXPECT_FALSE(AMediaFormat_getFloat(fmt1, nullptr, &f));
+
AMediaFormat_delete(fmt1);
}
@@ -100,6 +129,14 @@
AMediaFormat_setDouble(fmt1, "dip", 0.5);
EXPECT_TRUE(AMediaFormat_getDouble(fmt1, "trouble", &d));
EXPECT_EQ(d, 100.5);
+
+ // verify detecting some bad parameters.
+ AMediaFormat_setDouble(nullptr, "whatever", 1.5);
+ AMediaFormat_setDouble(fmt1, nullptr, 1.5);
+
+ EXPECT_FALSE(AMediaFormat_getDouble(nullptr, "whatever", &d));
+ EXPECT_FALSE(AMediaFormat_getDouble(fmt1, nullptr, &d));
+
AMediaFormat_delete(fmt1);
}
@@ -111,8 +148,16 @@
AMediaFormat_setString(fmt1, "stringtheory", content);
EXPECT_TRUE(AMediaFormat_getString(fmt1, "stringtheory", &out));
EXPECT_NE(out, nullptr);
+ EXPECT_NE(out, content); // should not be the original
EXPECT_EQ(strcmp(out,content), 0);
+ // verify detecting some bad parameters.
+ AMediaFormat_setString(nullptr, "whatever", content);
+ AMediaFormat_setString(fmt1, nullptr, content);
+
+ EXPECT_FALSE(AMediaFormat_getString(nullptr, "whatever", &out));
+ EXPECT_FALSE(AMediaFormat_getString(fmt1, nullptr, &out));
+
AMediaFormat_delete(fmt1);
}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java
index 21ba957..7fd2752 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java
@@ -60,14 +60,12 @@
private static final String mStatsFile =
mContext.getExternalFilesDir(null) + "/Muxer." + System.currentTimeMillis() + ".csv";
private static final String TAG = "MuxerTest";
- private static final Map<String, Integer> mMapFormat = new Hashtable<String, Integer>() {
- {
- put("mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
- put("webm", MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM);
- put("3gpp", MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP);
- put("ogg", MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG);
- }
- };
+ private static final Map<String, Integer> mMapFormat = Map.of(
+ "mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4,
+ "webm", MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM,
+ "3gpp", MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP,
+ "ogg", MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG);
+
private String mInputFileName;
private String mFormat;
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeDecoder.cpp b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeDecoder.cpp
index 043bc9e..a0628fa 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeDecoder.cpp
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeDecoder.cpp
@@ -19,6 +19,7 @@
#include <jni.h>
#include <fstream>
+#include <memory>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
@@ -42,7 +43,7 @@
return -1;
}
- Decoder *decoder = new Decoder();
+ std::unique_ptr<Decoder> decoder(new (std::nothrow) Decoder());
Extractor *extractor = decoder->getExtractor();
if (!extractor) {
ALOGE("Extractor creation failed");
@@ -125,6 +126,5 @@
inputFp = nullptr;
}
extractor->deInitExtractor();
- delete decoder;
return 0;
}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeMuxer.cpp b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeMuxer.cpp
index a5ef5b8..a297526 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeMuxer.cpp
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeMuxer.cpp
@@ -19,6 +19,7 @@
#include <jni.h>
#include <fstream>
+#include <memory>
#include <string>
#include <sys/stat.h>
@@ -47,7 +48,7 @@
return MUXER_OUTPUT_FORMAT_INVALID;
}
- Muxer *muxerObj = new Muxer();
+ std::unique_ptr<Muxer> muxerObj(new (std::nothrow) Muxer());
Extractor *extractor = muxerObj->getExtractor();
if (!extractor) {
ALOGE("Extractor creation failed");
@@ -159,7 +160,6 @@
}
env->ReleaseStringUTFChars(jFormat, fmt);
extractor->deInitExtractor();
- delete muxerObj;
return 0;
}
diff --git a/media/tests/benchmark/src/native/common/BenchmarkCommon.h b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
index 40a8c9e..ba3e81a 100644
--- a/media/tests/benchmark/src/native/common/BenchmarkCommon.h
+++ b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
@@ -50,7 +50,7 @@
{
lock_guard<mutex> lock(mMutex);
needsNotify = mQueue.empty();
- mQueue.push(move(elem));
+ mQueue.push(std::move(elem));
}
if (needsNotify) mQueueNotEmptyCondition.notify_one();
}
diff --git a/media/tests/benchmark/src/native/encoder/C2Encoder.cpp b/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
index ca79881..5b7a471 100644
--- a/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
+++ b/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
@@ -17,11 +17,13 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "C2Encoder"
+#include <memory>
+
#include "C2Encoder.h"
int32_t C2Encoder::createCodec2Component(string compName, AMediaFormat *format) {
ALOGV("In %s", __func__);
- mListener.reset(new CodecListener(
+ mListener.reset(new (std::nothrow) CodecListener(
[this](std::list<std::unique_ptr<C2Work>> &workItems) { handleWorkDone(workItems); }));
if (!mListener) return -1;
@@ -125,7 +127,7 @@
}
int32_t numFrames = (inputBufferSize + frameSize - 1) / frameSize;
// Temporary buffer to read data from the input file
- char *data = (char *)malloc(frameSize);
+ std::unique_ptr<char[]> data(new (std::nothrow) char[frameSize]);
if (!data) {
ALOGE("Insufficient memory to read from input file");
return -1;
@@ -169,7 +171,7 @@
if (inputBufferSize - offset < frameSize) {
frameSize = inputBufferSize - offset;
}
- eleStream.read(data, frameSize);
+ eleStream.read(data.get(), frameSize);
if (eleStream.gcount() != frameSize) {
ALOGE("read() from file failed. Incorrect bytes read");
return -1;
@@ -191,8 +193,8 @@
return view.error();
}
- memcpy(view.base(), data, frameSize);
- work->input.buffers.emplace_back(new LinearBuffer(block));
+ memcpy(view.base(), data.get(), frameSize);
+ work->input.buffers.emplace_back(new (std::nothrow) LinearBuffer(block));
} else {
std::shared_ptr<C2GraphicBlock> block;
status = mGraphicPool->fetchGraphicBlock(
@@ -211,16 +213,16 @@
uint8_t *pY = view.data()[C2PlanarLayout::PLANE_Y];
uint8_t *pU = view.data()[C2PlanarLayout::PLANE_U];
uint8_t *pV = view.data()[C2PlanarLayout::PLANE_V];
- memcpy(pY, data, mWidth * mHeight);
- memcpy(pU, data + mWidth * mHeight, (mWidth * mHeight >> 2));
- memcpy(pV, data + (mWidth * mHeight * 5 >> 2), mWidth * mHeight >> 2);
- work->input.buffers.emplace_back(new GraphicBuffer(block));
+ memcpy(pY, data.get(), mWidth * mHeight);
+ memcpy(pU, data.get() + mWidth * mHeight, (mWidth * mHeight >> 2));
+ memcpy(pV, data.get() + (mWidth * mHeight * 5 >> 2), mWidth * mHeight >> 2);
+ work->input.buffers.emplace_back(new (std::nothrow) GraphicBuffer(block));
}
mStats->addFrameSize(frameSize);
}
work->worklets.clear();
- work->worklets.emplace_back(new C2Worklet);
+ work->worklets.emplace_back(new (std::nothrow) C2Worklet);
std::list<std::unique_ptr<C2Work>> items;
items.push_back(std::move(work));
@@ -234,7 +236,6 @@
numFrames--;
mNumInputFrame++;
}
- free(data);
return status;
}
diff --git a/media/tests/benchmark/tests/C2DecoderTest.cpp b/media/tests/benchmark/tests/C2DecoderTest.cpp
index 85dcbc1..6e4d9e1 100644
--- a/media/tests/benchmark/tests/C2DecoderTest.cpp
+++ b/media/tests/benchmark/tests/C2DecoderTest.cpp
@@ -20,6 +20,7 @@
#include <fstream>
#include <iostream>
#include <limits>
+#include <memory>
#include "BenchmarkTestEnvironment.h"
#include "C2Decoder.h"
@@ -50,7 +51,7 @@
};
void C2DecoderTest::setupC2DecoderTest() {
- mDecoder = new C2Decoder();
+ mDecoder = new (std::nothrow) C2Decoder();
ASSERT_NE(mDecoder, nullptr) << "C2Decoder creation failed";
int32_t status = mDecoder->setupCodec2();
@@ -66,7 +67,7 @@
FILE *inputFp = fopen(inputFile.c_str(), "rb");
ASSERT_NE(inputFp, nullptr) << "Unable to open " << inputFile << " file for reading";
- Extractor *extractor = new Extractor();
+ std::unique_ptr<Extractor> extractor(new (std::nothrow) Extractor());
ASSERT_NE(extractor, nullptr) << "Extractor creation failed";
// Read file properties
@@ -85,7 +86,7 @@
int32_t status = extractor->setupTrackFormat(curTrack);
ASSERT_EQ(status, 0) << "Track Format invalid";
- uint8_t *inputBuffer = (uint8_t *)malloc(fileSize);
+ std::unique_ptr<uint8_t[]> inputBuffer(new (std::nothrow) uint8_t[fileSize]);
ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
vector<AMediaCodecBufferInfo> frameInfo;
@@ -100,7 +101,7 @@
// copy the meta data and buffer to be passed to decoder
ASSERT_LE(inputBufferOffset + info.size, fileSize) << "Memory allocated not sufficient";
- memcpy(inputBuffer + inputBufferOffset, csdBuffer, info.size);
+ memcpy(inputBuffer.get() + inputBufferOffset, csdBuffer, info.size);
frameInfo.push_back(info);
inputBufferOffset += info.size;
idx++;
@@ -113,7 +114,7 @@
// copy the meta data and buffer to be passed to decoder
ASSERT_LE(inputBufferOffset + info.size, fileSize) << "Memory allocated not sufficient";
- memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+ memcpy(inputBuffer.get() + inputBufferOffset, extractor->getFrameBuf(), info.size);
frameInfo.push_back(info);
inputBufferOffset += info.size;
}
@@ -127,7 +128,7 @@
ASSERT_EQ(status, 0) << "Create component failed for " << codecName;
// Send the inputs to C2 Decoder and wait till all buffers are returned.
- status = mDecoder->decodeFrames(inputBuffer, frameInfo);
+ status = mDecoder->decodeFrames(inputBuffer.get(), frameInfo);
ASSERT_EQ(status, 0) << "Decoder failed for " << codecName;
mDecoder->waitOnInputConsumption();
@@ -141,10 +142,8 @@
mDecoder->resetDecoder();
}
}
- free(inputBuffer);
fclose(inputFp);
extractor->deInitExtractor();
- delete extractor;
delete mDecoder;
mDecoder = nullptr;
}
@@ -174,7 +173,7 @@
make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "hevc")));
int main(int argc, char **argv) {
- gEnv = new BenchmarkTestEnvironment();
+ gEnv = new (std::nothrow) BenchmarkTestEnvironment();
::testing::AddGlobalTestEnvironment(gEnv);
::testing::InitGoogleTest(&argc, argv);
int status = gEnv->initFromOptions(argc, argv);
diff --git a/media/tests/benchmark/tests/C2EncoderTest.cpp b/media/tests/benchmark/tests/C2EncoderTest.cpp
index b18d856..dfbe496 100644
--- a/media/tests/benchmark/tests/C2EncoderTest.cpp
+++ b/media/tests/benchmark/tests/C2EncoderTest.cpp
@@ -20,6 +20,7 @@
#include <fstream>
#include <iostream>
#include <limits>
+#include <memory>
#include "BenchmarkTestEnvironment.h"
#include "C2Encoder.h"
@@ -50,7 +51,7 @@
};
void C2EncoderTest::setupC2EncoderTest() {
- mEncoder = new C2Encoder();
+ mEncoder = new (std::nothrow) C2Encoder();
ASSERT_NE(mEncoder, nullptr) << "C2Encoder creation failed";
int32_t status = mEncoder->setupCodec2();
@@ -66,7 +67,7 @@
FILE *inputFp = fopen(inputFile.c_str(), "rb");
ASSERT_NE(inputFp, nullptr) << "Unable to open input file for reading";
- Decoder *decoder = new Decoder();
+ std::unique_ptr<Decoder> decoder(new (std::nothrow) Decoder());
ASSERT_NE(decoder, nullptr) << "Decoder creation failed";
Extractor *extractor = decoder->getExtractor();
@@ -88,7 +89,7 @@
int32_t status = extractor->setupTrackFormat(curTrack);
ASSERT_EQ(status, 0) << "Track Format invalid";
- uint8_t *inputBuffer = (uint8_t *)malloc(fileSize);
+ std::unique_ptr<uint8_t[]> inputBuffer(new (std::nothrow) uint8_t[fileSize]);
ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
vector<AMediaCodecBufferInfo> frameInfo;
@@ -102,7 +103,7 @@
// copy the meta data and buffer to be passed to decoder
ASSERT_LE(inputBufferOffset + info.size, fileSize) << "Memory allocated not sufficient";
- memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+ memcpy(inputBuffer.get() + inputBufferOffset, extractor->getFrameBuf(), info.size);
frameInfo.push_back(info);
inputBufferOffset += info.size;
}
@@ -114,7 +115,8 @@
<< " for dumping decoder's output";
decoder->setupDecoder();
- status = decoder->decode(inputBuffer, frameInfo, decName, false /*asyncMode */, outFp);
+ status = decoder->decode(inputBuffer.get(), frameInfo, decName,
+ false /*asyncMode */, outFp);
ASSERT_EQ(status, AMEDIA_OK) << "Decode returned error : " << status;
// Encode the given input stream for all C2 codecs supported by device
@@ -149,11 +151,9 @@
// Destroy the decoder for the given input
decoder->deInitCodec();
decoder->resetDecoder();
- free(inputBuffer);
}
fclose(inputFp);
extractor->deInitExtractor();
- delete decoder;
delete mEncoder;
mEncoder = nullptr;
}
@@ -176,7 +176,7 @@
make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "hevc")));
int main(int argc, char **argv) {
- gEnv = new BenchmarkTestEnvironment();
+ gEnv = new (std::nothrow) BenchmarkTestEnvironment();
::testing::AddGlobalTestEnvironment(gEnv);
::testing::InitGoogleTest(&argc, argv);
int status = gEnv->initFromOptions(argc, argv);
diff --git a/media/tests/benchmark/tests/DecoderTest.cpp b/media/tests/benchmark/tests/DecoderTest.cpp
index 3666724..b363df3 100644
--- a/media/tests/benchmark/tests/DecoderTest.cpp
+++ b/media/tests/benchmark/tests/DecoderTest.cpp
@@ -20,6 +20,7 @@
#include <fstream>
#include <iostream>
#include <limits>
+#include <memory>
#include <android/binder_process.h>
@@ -38,7 +39,7 @@
FILE *inputFp = fopen(inputFile.c_str(), "rb");
ASSERT_NE(inputFp, nullptr) << "Unable to open " << inputFile << " file for reading";
- Decoder *decoder = new Decoder();
+ std::unique_ptr<Decoder> decoder(new (std::nothrow) Decoder());
ASSERT_NE(decoder, nullptr) << "Decoder creation failed";
Extractor *extractor = decoder->getExtractor();
@@ -57,7 +58,7 @@
int32_t status = extractor->setupTrackFormat(curTrack);
ASSERT_EQ(status, 0) << "Track Format invalid";
- uint8_t *inputBuffer = (uint8_t *)malloc(kMaxBufferSize);
+ std::unique_ptr<uint8_t[]> inputBuffer(new (std::nothrow) uint8_t[kMaxBufferSize]);
ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
vector<AMediaCodecBufferInfo> frameInfo;
@@ -72,7 +73,7 @@
ASSERT_LE(inputBufferOffset + info.size, kMaxBufferSize)
<< "Memory allocated not sufficient";
- memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+ memcpy(inputBuffer.get() + inputBufferOffset, extractor->getFrameBuf(), info.size);
frameInfo.push_back(info);
inputBufferOffset += info.size;
}
@@ -80,7 +81,7 @@
string codecName = get<1>(params);
bool asyncMode = get<2>(params);
decoder->setupDecoder();
- status = decoder->decode(inputBuffer, frameInfo, codecName, asyncMode);
+ status = decoder->decode(inputBuffer.get(), frameInfo, codecName, asyncMode);
ASSERT_EQ(status, AMEDIA_OK) << "Decoder failed for " << codecName;
decoder->deInitCodec();
@@ -88,12 +89,10 @@
string inputReference = get<0>(params);
decoder->dumpStatistics(inputReference, codecName, (asyncMode ? "async" : "sync"),
gEnv->getStatsFile());
- free(inputBuffer);
decoder->resetDecoder();
}
fclose(inputFp);
extractor->deInitExtractor();
- delete decoder;
}
// TODO: (b/140549596)
@@ -178,7 +177,7 @@
int main(int argc, char **argv) {
ABinderProcess_startThreadPool();
- gEnv = new BenchmarkTestEnvironment();
+ gEnv = new (std::nothrow) BenchmarkTestEnvironment();
::testing::AddGlobalTestEnvironment(gEnv);
::testing::InitGoogleTest(&argc, argv);
int status = gEnv->initFromOptions(argc, argv);
@@ -190,4 +189,4 @@
ALOGV("Decoder Test result = %d\n", status);
}
return status;
-}
\ No newline at end of file
+}
diff --git a/media/tests/benchmark/tests/EncoderTest.cpp b/media/tests/benchmark/tests/EncoderTest.cpp
index 7e1681d..6703b99 100644
--- a/media/tests/benchmark/tests/EncoderTest.cpp
+++ b/media/tests/benchmark/tests/EncoderTest.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "encoderTest"
#include <fstream>
+#include <memory>
#include "BenchmarkTestEnvironment.h"
#include "Decoder.h"
@@ -39,7 +40,7 @@
FILE *inputFp = fopen(inputFile.c_str(), "rb");
ASSERT_NE(inputFp, nullptr) << "Unable to open " << inputFile << " file for reading";
- Decoder *decoder = new Decoder();
+ std::unique_ptr<Decoder> decoder(new (std::nothrow) Decoder());
ASSERT_NE(decoder, nullptr) << "Decoder creation failed";
Extractor *extractor = decoder->getExtractor();
@@ -54,14 +55,14 @@
int32_t trackCount = extractor->initExtractor(fd, fileSize);
ASSERT_GT(trackCount, 0) << "initExtractor failed";
- Encoder *encoder = new Encoder();
+ std::unique_ptr<Encoder> encoder(new (std::nothrow) Encoder());
ASSERT_NE(encoder, nullptr) << "Decoder creation failed";
for (int curTrack = 0; curTrack < trackCount; curTrack++) {
int32_t status = extractor->setupTrackFormat(curTrack);
ASSERT_EQ(status, 0) << "Track Format invalid";
- uint8_t *inputBuffer = (uint8_t *)malloc(kMaxBufferSize);
+ std::unique_ptr<uint8_t[]> inputBuffer(new (std::nothrow) uint8_t[kMaxBufferSize]);
ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
vector<AMediaCodecBufferInfo> frameInfo;
@@ -76,7 +77,7 @@
ASSERT_LE(inputBufferOffset + info.size, kMaxBufferSize)
<< "Memory allocated not sufficient";
- memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+ memcpy(inputBuffer.get() + inputBufferOffset, extractor->getFrameBuf(), info.size);
frameInfo.push_back(info);
inputBufferOffset += info.size;
}
@@ -88,7 +89,7 @@
<< " for dumping decoder's output";
decoder->setupDecoder();
- status = decoder->decode(inputBuffer, frameInfo, decName, false /*asyncMode */, outFp);
+ status = decoder->decode(inputBuffer.get(), frameInfo, decName, false /*asyncMode */, outFp);
ASSERT_EQ(status, AMEDIA_OK) << "Decode returned error : " << status;
AMediaFormat *decoderFormat = decoder->getFormat();
@@ -154,13 +155,10 @@
}
encoder->resetEncoder();
decoder->deInitCodec();
- free(inputBuffer);
decoder->resetDecoder();
}
- delete encoder;
fclose(inputFp);
extractor->deInitExtractor();
- delete decoder;
}
INSTANTIATE_TEST_SUITE_P(
@@ -220,7 +218,7 @@
"c2.android.hevc.encoder", true)));
int main(int argc, char **argv) {
- gEnv = new BenchmarkTestEnvironment();
+ gEnv = new (std::nothrow) BenchmarkTestEnvironment();
::testing::AddGlobalTestEnvironment(gEnv);
::testing::InitGoogleTest(&argc, argv);
int status = gEnv->initFromOptions(argc, argv);
diff --git a/media/tests/benchmark/tests/ExtractorTest.cpp b/media/tests/benchmark/tests/ExtractorTest.cpp
index 27ee9ba..35fb465 100644
--- a/media/tests/benchmark/tests/ExtractorTest.cpp
+++ b/media/tests/benchmark/tests/ExtractorTest.cpp
@@ -17,6 +17,8 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "extractorTest"
+#include <memory>
+
#include <gtest/gtest.h>
#include <android/binder_process.h>
@@ -29,7 +31,7 @@
class ExtractorTest : public ::testing::TestWithParam<pair<string, int32_t>> {};
TEST_P(ExtractorTest, Extract) {
- Extractor *extractObj = new Extractor();
+ std::unique_ptr<Extractor> extractObj(new (std::nothrow) Extractor());
ASSERT_NE(extractObj, nullptr) << "Extractor creation failed";
string inputFile = gEnv->getRes() + GetParam().first;
@@ -53,7 +55,6 @@
extractObj->dumpStatistics(GetParam().first, "", gEnv->getStatsFile());
fclose(inputFp);
- delete extractObj;
}
INSTANTIATE_TEST_SUITE_P(ExtractorTestAll, ExtractorTest,
@@ -76,7 +77,7 @@
int main(int argc, char **argv) {
ABinderProcess_startThreadPool();
- gEnv = new BenchmarkTestEnvironment();
+ gEnv = new (std::nothrow) BenchmarkTestEnvironment();
::testing::AddGlobalTestEnvironment(gEnv);
::testing::InitGoogleTest(&argc, argv);
int status = gEnv->initFromOptions(argc, argv);
diff --git a/media/tests/benchmark/tests/MuxerTest.cpp b/media/tests/benchmark/tests/MuxerTest.cpp
index 991644b..65a3df4 100644
--- a/media/tests/benchmark/tests/MuxerTest.cpp
+++ b/media/tests/benchmark/tests/MuxerTest.cpp
@@ -20,6 +20,7 @@
#include <fstream>
#include <iostream>
+#include <memory>
#include "BenchmarkTestEnvironment.h"
#include "Muxer.h"
@@ -59,7 +60,7 @@
MUXER_OUTPUT_T outputFormat = getMuxerOutFormat(fmt);
ASSERT_NE(outputFormat, MUXER_OUTPUT_FORMAT_INVALID) << "Invalid muxer output format";
- Muxer *muxerObj = new Muxer();
+ std::unique_ptr<Muxer> muxerObj(new (std::nothrow) Muxer());
ASSERT_NE(muxerObj, nullptr) << "Muxer creation failed";
Extractor *extractor = muxerObj->getExtractor();
@@ -78,7 +79,7 @@
int32_t status = extractor->setupTrackFormat(curTrack);
ASSERT_EQ(status, 0) << "Track Format invalid";
- uint8_t *inputBuffer = (uint8_t *)malloc(kMaxBufferSize);
+ std::unique_ptr<uint8_t[]> inputBuffer(new (std::nothrow) uint8_t[kMaxBufferSize]);
ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
// AMediaCodecBufferInfo : <size of frame> <flags> <presentationTimeUs> <offset>
@@ -94,7 +95,7 @@
ASSERT_LE(inputBufferOffset + info.size, kMaxBufferSize)
<< "Memory allocated not sufficient";
- memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+ memcpy(inputBuffer.get() + inputBufferOffset, extractor->getFrameBuf(), info.size);
info.offset = inputBufferOffset;
frameInfos.push_back(info);
inputBufferOffset += info.size;
@@ -109,18 +110,16 @@
status = muxerObj->initMuxer(fd, outputFormat);
ASSERT_EQ(status, 0) << "initMuxer failed";
- status = muxerObj->mux(inputBuffer, frameInfos);
+ status = muxerObj->mux(inputBuffer.get(), frameInfos);
ASSERT_EQ(status, 0) << "Mux failed";
muxerObj->deInitMuxer();
muxerObj->dumpStatistics(GetParam().first + "." + fmt.c_str(), fmt, gEnv->getStatsFile());
- free(inputBuffer);
fclose(outputFp);
muxerObj->resetMuxer();
}
fclose(inputFp);
extractor->deInitExtractor();
- delete muxerObj;
}
INSTANTIATE_TEST_SUITE_P(
@@ -146,7 +145,7 @@
make_pair("bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", "3gpp")));
int main(int argc, char **argv) {
- gEnv = new BenchmarkTestEnvironment();
+ gEnv = new (std::nothrow) BenchmarkTestEnvironment();
::testing::AddGlobalTestEnvironment(gEnv);
::testing::InitGoogleTest(&argc, argv);
int status = gEnv->initFromOptions(argc, argv);
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index a38ef57..fddbece 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -69,6 +69,7 @@
"-Wall",
"-Wextra",
"-Werror",
+ "-Wthread-safety",
],
header_libs: [
diff --git a/media/utils/MemoryLeakTrackUtil.cpp b/media/utils/MemoryLeakTrackUtil.cpp
index fdb8c4f..7451033 100644
--- a/media/utils/MemoryLeakTrackUtil.cpp
+++ b/media/utils/MemoryLeakTrackUtil.cpp
@@ -33,10 +33,8 @@
#define ABI_STRING "arm"
#elif defined(__aarch64__)
#define ABI_STRING "arm64"
-#elif defined(__mips__) && !defined(__LP64__)
-#define ABI_STRING "mips"
-#elif defined(__mips__) && defined(__LP64__)
-#define ABI_STRING "mips64"
+#elif defined(__riscv)
+#define ABI_STRING "riscv64"
#elif defined(__i386__)
#define ABI_STRING "x86"
#elif defined(__x86_64__)
diff --git a/media/utils/ProcessInfo.cpp b/media/utils/ProcessInfo.cpp
index da199c4..8437222 100644
--- a/media/utils/ProcessInfo.cpp
+++ b/media/utils/ProcessInfo.cpp
@@ -40,11 +40,11 @@
int32_t state;
int32_t score = INVALID_ADJ;
status_t err = service->getProcessStatesAndOomScoresFromPids(length, &pid, &state, &score);
+ ALOGV("%s: pid:%d state:%d score:%d err:%d", __FUNCTION__, pid, state, score, err);
if (err != OK) {
ALOGE("getProcessStatesAndOomScoresFromPids failed");
return false;
}
- ALOGV("pid %d state %d score %d", pid, state, score);
if (score <= NATIVE_ADJ) {
std::scoped_lock lock{mOverrideLock};
diff --git a/media/utils/TimeCheck.cpp b/media/utils/TimeCheck.cpp
index 6823f4f..65b2c52 100644
--- a/media/utils/TimeCheck.cpp
+++ b/media/utils/TimeCheck.cpp
@@ -283,7 +283,7 @@
}
// Automatically create a TimeCheck class for a class and method.
-// This is used for Audio HIDL support.
+// This is used for Audio HAL support.
mediautils::TimeCheck makeTimeCheckStatsForClassMethod(
std::string_view className, std::string_view methodName) {
std::shared_ptr<MethodStatistics<std::string>> statistics =
diff --git a/media/utils/TimerThread.cpp b/media/utils/TimerThread.cpp
index 5e58a3d..d4da28f 100644
--- a/media/utils/TimerThread.cpp
+++ b/media/utils/TimerThread.cpp
@@ -292,6 +292,7 @@
void TimerThread::MonitorThread::threadFunc() {
std::unique_lock _l(mMutex);
+ ::android::base::ScopedLockAssertion lock_assertion(mMutex);
while (!mShouldExit) {
Handle nextDeadline = INVALID_HANDLE;
Handle now = INVALID_HANDLE;
@@ -385,6 +386,7 @@
std::shared_ptr<const TimerThread::Request> TimerThread::MonitorThread::remove(Handle handle) {
std::pair<std::shared_ptr<const Request>, TimerCallback> data;
std::unique_lock ul(mMutex);
+ ::android::base::ScopedLockAssertion lock_assertion(mMutex);
if (const auto it = mMonitorRequests.find(handle);
it != mMonitorRequests.end()) {
data = std::move(it->second);
diff --git a/media/utils/fuzzers/SchedulingPolicyServiceFuzz.cpp b/media/utils/fuzzers/SchedulingPolicyServiceFuzz.cpp
index 130feee..32fc3be 100644
--- a/media/utils/fuzzers/SchedulingPolicyServiceFuzz.cpp
+++ b/media/utils/fuzzers/SchedulingPolicyServiceFuzz.cpp
@@ -34,11 +34,16 @@
const sp<IServiceManager> sm(defaultServiceManager());
if (sm != nullptr) {
const String16 name("batterystats");
- batteryStatService = checked_interface_cast<IBatteryStats>(sm->checkService(name));
- if (batteryStatService == nullptr) {
+ sp<IBinder> obj = sm->checkService(name);
+ if (!obj) {
ALOGW("batterystats service unavailable!");
return nullptr;
}
+ batteryStatService = checked_interface_cast<IBatteryStats>(obj);
+ if (batteryStatService == nullptr) {
+ ALOGW("batterystats service interface is invalid");
+ return nullptr;
+ }
}
return batteryStatService;
}
diff --git a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
index 51e8d7a..15f043a 100644
--- a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
+++ b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
@@ -25,6 +25,7 @@
static constexpr int kMaxOperations = 50;
static constexpr int kMaxStringLen = 256;
+static constexpr int kMaxSpaces = 1000;
using android::content::AttributionSourceState;
@@ -35,7 +36,9 @@
pm.allowPlaybackCapture(uid);
},
[](FuzzedDataProvider* data_provider, android::MediaPackageManager pm) -> void {
- int spaces = data_provider->ConsumeIntegral<int>();
+ /* The large value of spaces was taking time in file write operation.
+ * Limited spaces values in range to avoid timeout.*/
+ int spaces = data_provider->ConsumeIntegralInRange<int>(0, kMaxSpaces);
// Dump everything into /dev/null
int fd = open("/dev/null", O_WRONLY);
diff --git a/media/utils/include/mediautils/TimeCheck.h b/media/utils/include/mediautils/TimeCheck.h
index bdb5337..0823669 100644
--- a/media/utils/include/mediautils/TimeCheck.h
+++ b/media/utils/include/mediautils/TimeCheck.h
@@ -148,4 +148,9 @@
TimeCheck makeTimeCheckStatsForClassMethod(
std::string_view className, std::string_view methodName);
+// A handy statement-like macro to put at the beginning of almost every method
+// which calls into HAL. Note that it requires the class to implement 'getClassName'.
+#define TIME_CHECK() auto timeCheck = \
+ mediautils::makeTimeCheckStatsForClassMethod(getClassName(), __func__)
+
} // namespace android::mediautils
diff --git a/media/utils/include/mediautils/TimerThread.h b/media/utils/include/mediautils/TimerThread.h
index c76fa7d..1e0d8c2 100644
--- a/media/utils/include/mediautils/TimerThread.h
+++ b/media/utils/include/mediautils/TimerThread.h
@@ -297,7 +297,7 @@
std::pair<std::shared_ptr<const Request>, TimerCallback>>
mSecondChanceRequests GUARDED_BY(mMutex);
- RequestQueue& mTimeoutQueue; // locked internally, added to when request times out.
+ RequestQueue& mTimeoutQueue GUARDED_BY(mMutex); // added to when request times out.
// Worker thread variables
bool mShouldExit GUARDED_BY(mMutex) = false;
diff --git a/services/OWNERS b/services/OWNERS
deleted file mode 100644
index 17e605d..0000000
--- a/services/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-elaurent@google.com
-essick@google.com
-etalvala@google.com
-hunga@google.com
-nchalko@google.com
-quxiangfang@google.com
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 763c070..6d4c3a3 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -22,6 +22,10 @@
cc_library_shared {
name: "libaudioflinger",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+
srcs: [
"AudioFlinger.cpp",
"AudioHwDevice.cpp",
@@ -55,7 +59,6 @@
],
shared_libs: [
- "android.media.audio.common.types-V1-cpp",
"audioflinger-aidl-cpp",
"audioclient-types-aidl-cpp",
"av-types-aidl-cpp",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d2363d8..ba7c6b6 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -39,6 +39,7 @@
#include <utils/Log.h>
#include <utils/Trace.h>
#include <binder/Parcel.h>
+#include <media/audiohal/AudioHalVersionInfo.h>
#include <media/audiohal/DeviceHalInterface.h>
#include <media/audiohal/DevicesFactoryHalInterface.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
@@ -106,13 +107,15 @@
namespace android {
-#define MAX_AAUDIO_PROPERTY_DEVICE_HAL_VERSION 7.1
-
using ::android::base::StringPrintf;
using media::IEffectClient;
using media::audio::common::AudioMMapPolicyInfo;
using media::audio::common::AudioMMapPolicyType;
using android::content::AttributionSourceState;
+using android::detail::AudioHalVersionInfo;
+
+static const AudioHalVersionInfo kMaxAAudioPropertyDeviceHalVersion =
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 1);
static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
static const char kHardwareLockedString[] = "Hardware lock is taken\n";
@@ -228,7 +231,9 @@
BINDER_METHOD_ENTRY(setDeviceConnectedState) \
BINDER_METHOD_ENTRY(setRequestedLatencyMode) \
BINDER_METHOD_ENTRY(getSupportedLatencyModes) \
-
+BINDER_METHOD_ENTRY(setBluetoothVariableLatencyEnabled) \
+BINDER_METHOD_ENTRY(isBluetoothVariableLatencyEnabled) \
+BINDER_METHOD_ENTRY(supportsBluetoothVariableLatency) \
// singleton for Binder Method Statistics for IAudioFlinger
static auto& getIAudioFlingerStatistics() {
@@ -322,7 +327,8 @@
mGlobalEffectEnableTime(0),
mPatchPanel(this),
mDeviceEffectManager(this),
- mSystemReady(false)
+ mSystemReady(false),
+ mBluetoothLatencyModesEnabled(true)
{
// Move the audio session unique ID generator start base as time passes to limit risk of
// generating the same ID again after an audioserver restart.
@@ -398,7 +404,7 @@
mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
- if (mDevicesFactoryHal->getHalVersion() <= MAX_AAUDIO_PROPERTY_DEVICE_HAL_VERSION) {
+ if (mDevicesFactoryHal->getHalVersion() <= kMaxAAudioPropertyDeviceHalVersion) {
mAAudioBurstsPerBuffer = getAAudioMixerBurstCountFromSystemProperty();
mAAudioHwBurstMinMicros = getAAudioHardwareBurstMinUsecFromSystemProperty();
}
@@ -444,7 +450,7 @@
*policyInfos = it->second;
return NO_ERROR;
}
- if (mDevicesFactoryHal->getHalVersion() > MAX_AAUDIO_PROPERTY_DEVICE_HAL_VERSION) {
+ if (mDevicesFactoryHal->getHalVersion() > kMaxAAudioPropertyDeviceHalVersion) {
AutoMutex lock(mHardwareLock);
for (size_t i = 0; i < mAudioHwDevs.size(); ++i) {
AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
@@ -1640,6 +1646,44 @@
return thread->getSupportedLatencyModes(modes);
}
+status_t AudioFlinger::setBluetoothVariableLatencyEnabled(bool enabled) {
+ Mutex::Autolock _l(mLock);
+ status_t status = INVALID_OPERATION;
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ // Success if at least one PlaybackThread supports Bluetooth latency modes
+ if (mPlaybackThreads.valueAt(i)->setBluetoothVariableLatencyEnabled(enabled) == NO_ERROR) {
+ status = NO_ERROR;
+ }
+ }
+ if (status == NO_ERROR) {
+ mBluetoothLatencyModesEnabled.store(enabled);
+ }
+ return status;
+}
+
+status_t AudioFlinger::isBluetoothVariableLatencyEnabled(bool *enabled) {
+ if (enabled == nullptr) {
+ return BAD_VALUE;
+ }
+ *enabled = mBluetoothLatencyModesEnabled.load();
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::supportsBluetoothVariableLatency(bool* support) {
+ if (support == nullptr) {
+ return BAD_VALUE;
+ }
+ Mutex::Autolock _l(mLock);
+ *support = false;
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ if (mAudioHwDevs.valueAt(i)->supportsBluetoothVariableLatency()) {
+ *support = true;
+ break;
+ }
+ }
+ return NO_ERROR;
+}
+
status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
{
// check calling permissions
@@ -2142,9 +2186,9 @@
void AudioFlinger::onSupportedLatencyModesChanged(
audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
int32_t outputAidl = VALUE_OR_FATAL(legacy2aidl_audio_io_handle_t_int32_t(output));
- std::vector<media::LatencyMode> modesAidl = VALUE_OR_FATAL(
- convertContainer<std::vector<media::LatencyMode>>(modes,
- legacy2aidl_audio_latency_mode_t_LatencyMode));
+ std::vector<media::audio::common::AudioLatencyMode> modesAidl = VALUE_OR_FATAL(
+ convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+ modes, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
Mutex::Autolock _l(mClientLock);
size_t size = mNotificationClients.size();
@@ -2541,6 +2585,13 @@
flags = static_cast<AudioHwDevice::Flags>(flags | AudioHwDevice::AHWD_IS_INSERT);
}
+
+ if (bool supports = false;
+ dev->supportsBluetoothVariableLatency(&supports) == NO_ERROR && supports) {
+ flags = static_cast<AudioHwDevice::Flags>(flags |
+ AudioHwDevice::AHWD_SUPPORTS_BT_LATENCY_MODES);
+ }
+
audio_module_handle_t handle = (audio_module_handle_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_MODULE);
AudioHwDevice *audioDevice = new AudioHwDevice(handle, name, dev, flags);
if (strcmp(name, AUDIO_HARDWARE_MODULE_ID_PRIMARY) == 0) {
@@ -2550,7 +2601,7 @@
mHardwareStatus = AUDIO_HW_IDLE;
}
- if (mDevicesFactoryHal->getHalVersion() > MAX_AAUDIO_PROPERTY_DEVICE_HAL_VERSION) {
+ if (mDevicesFactoryHal->getHalVersion() > kMaxAAudioPropertyDeviceHalVersion) {
if (int32_t mixerBursts = dev->getAAudioMixerBurstCount();
mixerBursts > 0 && mixerBursts > mAAudioBurstsPerBuffer) {
mAAudioBurstsPerBuffer = mixerBursts;
@@ -2748,20 +2799,25 @@
return NO_ERROR;
}
-status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfo> *microphones)
+status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones)
{
AutoMutex lock(mHardwareLock);
status_t status = INVALID_OPERATION;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
- std::vector<media::MicrophoneInfo> mics;
+ std::vector<audio_microphone_characteristic_t> mics;
AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
mHardwareStatus = AUDIO_HW_GET_MICROPHONES;
status_t devStatus = dev->hwDevice()->getMicrophones(&mics);
mHardwareStatus = AUDIO_HW_IDLE;
if (devStatus == NO_ERROR) {
- microphones->insert(microphones->begin(), mics.begin(), mics.end());
// report success if at least one HW module supports the function.
+ std::transform(mics.begin(), mics.end(), std::back_inserter(*microphones), [](auto& mic)
+ {
+ auto microphone =
+ legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(mic);
+ return microphone.ok() ? microphone.value() : media::MicrophoneInfoFw{};
+ });
status = NO_ERROR;
}
}
@@ -2869,13 +2925,15 @@
ALOGV("openOutput_l() created spatializer output: ID %d thread %p",
*output, thread.get());
} else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
- thread = new OffloadThread(this, outputStream, *output, mSystemReady);
+ thread = new OffloadThread(this, outputStream, *output,
+ mSystemReady, halConfig->offload_info);
ALOGV("openOutput_l() created offload output: ID %d thread %p",
*output, thread.get());
} else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
|| !isValidPcmSinkFormat(halConfig->format)
|| !isValidPcmSinkChannelMask(halConfig->channel_mask)) {
- thread = new DirectOutputThread(this, outputStream, *output, mSystemReady);
+ thread = new DirectOutputThread(this, outputStream, *output,
+ mSystemReady, halConfig->offload_info);
ALOGV("openOutput_l() created direct output: ID %d thread %p",
*output, thread.get());
} else {
@@ -2889,6 +2947,7 @@
if (thread->isMsdDevice()) {
thread->setDownStreamPatch(&patch);
}
+ thread->setBluetoothVariableLatencyEnabled(mBluetoothLatencyModesEnabled.load());
return thread;
}
}
@@ -4526,12 +4585,9 @@
// ----------------------------------------------------------------------------
status_t AudioFlinger::onTransactWrapper(TransactionCode code,
- const Parcel& data,
- uint32_t flags,
+ [[maybe_unused]] const Parcel& data,
+ [[maybe_unused]] uint32_t flags,
const std::function<status_t()>& delegate) {
- (void) data;
- (void) flags;
-
// make sure transactions reserved to AudioPolicyManager do not come from other processes
switch (code) {
case TransactionCode::SET_STREAM_VOLUME:
@@ -4585,7 +4641,10 @@
case TransactionCode::SYSTEM_READY:
case TransactionCode::SET_AUDIO_HAL_PIDS:
case TransactionCode::SET_VIBRATOR_INFOS:
- case TransactionCode::UPDATE_SECONDARY_OUTPUTS: {
+ case TransactionCode::UPDATE_SECONDARY_OUTPUTS:
+ case TransactionCode::SET_BLUETOOTH_VARIABLE_LATENCY_ENABLED:
+ case TransactionCode::IS_BLUETOOTH_VARIABLE_LATENCY_ENABLED:
+ case TransactionCode::SUPPORTS_BLUETOOTH_VARIABLE_LATENCY: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index fc4c807..ebfe32c 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -274,7 +274,7 @@
bool isAudioPolicyReady() const { return mAudioPolicyReady.load(); }
- virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+ virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones);
virtual status_t setAudioHalPids(const std::vector<pid_t>& pids);
@@ -299,6 +299,12 @@
virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
std::vector<audio_latency_mode_t>* modes);
+ virtual status_t setBluetoothVariableLatencyEnabled(bool enabled);
+
+ virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled);
+
+ virtual status_t supportsBluetoothVariableLatency(bool* support);
+
status_t onTransactWrapper(TransactionCode code, const Parcel& data, uint32_t flags,
const std::function<status_t()>& delegate) override;
@@ -678,14 +684,16 @@
binder::Status getVolumeShaperState(
int32_t id,
std::optional<media::VolumeShaperState>* _aidl_return) override;
- binder::Status getDualMonoMode(media::AudioDualMonoMode* _aidl_return) override;
- binder::Status setDualMonoMode(media::AudioDualMonoMode mode) override;
+ binder::Status getDualMonoMode(
+ media::audio::common::AudioDualMonoMode* _aidl_return) override;
+ binder::Status setDualMonoMode(
+ media::audio::common::AudioDualMonoMode mode) override;
binder::Status getAudioDescriptionMixLevel(float* _aidl_return) override;
binder::Status setAudioDescriptionMixLevel(float leveldB) override;
binder::Status getPlaybackRateParameters(
- media::AudioPlaybackRate* _aidl_return) override;
+ media::audio::common::AudioPlaybackRate* _aidl_return) override;
binder::Status setPlaybackRateParameters(
- const media::AudioPlaybackRate& playbackRate) override;
+ const media::audio::common::AudioPlaybackRate& playbackRate) override;
private:
const sp<PlaybackThread::Track> mTrack;
@@ -700,7 +708,7 @@
int /*audio_session_t*/ triggerSession);
virtual binder::Status stop();
virtual binder::Status getActiveMicrophones(
- std::vector<media::MicrophoneInfoData>* activeMicrophones);
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones);
virtual binder::Status setPreferredMicrophoneDirection(
int /*audio_microphone_direction_t*/ direction);
virtual binder::Status setPreferredMicrophoneFieldDimension(float zoom);
@@ -1029,6 +1037,9 @@
std::vector<media::audio::common::AudioMMapPolicyInfo>> mPolicyInfos;
int32_t mAAudioBurstsPerBuffer = 0;
int32_t mAAudioHwBurstMinMicros = 0;
+
+ // Bluetooth Variable latency control logic is enabled or disabled
+ std::atomic_bool mBluetoothLatencyModesEnabled;
};
#undef INCLUDING_FROM_AUDIOFLINGER_H
diff --git a/services/audioflinger/AudioHwDevice.h b/services/audioflinger/AudioHwDevice.h
index 8c5d239..1749f3f 100644
--- a/services/audioflinger/AudioHwDevice.h
+++ b/services/audioflinger/AudioHwDevice.h
@@ -40,6 +40,8 @@
// Means that this isn't a terminal module, and software patches
// are used to transport audio data further.
AHWD_IS_INSERT = 0x4,
+ // This Module supports BT Latency mode control
+ AHWD_SUPPORTS_BT_LATENCY_MODES = 0x8,
};
AudioHwDevice(audio_module_handle_t handle,
@@ -64,6 +66,10 @@
return (0 != (mFlags & AHWD_IS_INSERT));
}
+ bool supportsBluetoothVariableLatency() const {
+ return (0 != (mFlags & AHWD_SUPPORTS_BT_LATENCY_MODES));
+ }
+
audio_module_handle_t handle() const { return mHandle; }
const char *moduleName() const { return mModuleName; }
sp<DeviceHalInterface> hwDevice() const { return mHwDevice; }
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index 53ac5cb..3a8c1bc 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -30,6 +30,7 @@
namespace android {
+using detail::AudioHalVersionInfo;
using media::IEffectClient;
void AudioFlinger::DeviceEffectManager::createAudioPatch(audio_patch_handle_t handle,
@@ -106,8 +107,13 @@
if (lStatus == NO_ERROR) {
lStatus = effect->addHandle(handle.get());
if (lStatus == NO_ERROR) {
- effect->init(patches);
- mDeviceEffects.emplace(device, effect);
+ lStatus = effect->init(patches);
+ if (lStatus == NAME_NOT_FOUND) {
+ lStatus = NO_ERROR;
+ }
+ if (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS) {
+ mDeviceEffects.emplace(device, effect);
+ }
}
}
}
@@ -125,14 +131,17 @@
return BAD_VALUE;
}
- static const float sMinDeviceEffectHalVersion = 6.0;
- float halVersion = effectsFactory->getHalVersion();
+ static AudioHalVersionInfo sMinDeviceEffectHalVersion =
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0);
+ AudioHalVersionInfo halVersion = effectsFactory->getHalVersion();
+ // We can trust AIDL generated AudioHalVersionInfo comparison operator (based on std::tie) as
+ // long as the type, major and minor sequence doesn't change in the definition.
if (((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC
&& (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_POST_PROC)
|| halVersion < sMinDeviceEffectHalVersion) {
- ALOGW("%s() non pre/post processing device effect %s or incompatible API version %f",
- __func__, desc->name, halVersion);
+ ALOGW("%s() non pre/post processing device effect %s or incompatible API version %s",
+ __func__, desc->name, halVersion.toString().c_str());
return BAD_VALUE;
}
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 9ebff0b..98829d0 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -569,7 +569,8 @@
mMaxDisableWaitCnt(1), // set by configure(), should be >= 1
mDisableWaitCnt(0), // set by process() and updateState()
mOffloaded(false),
- mAddedToHal(false)
+ mAddedToHal(false),
+ mIsOutput(false)
#ifdef FLOAT_EFFECT_CHAIN
, mSupportsFloat(false)
#endif
@@ -962,6 +963,7 @@
mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
mConfig.inputCfg.buffer.frameCount = callback->frameCount();
mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
+ mIsOutput = callback->isOutput();
ALOGV("configure() %p chain %p buffer %p framecount %zu",
this, callback->chain().promote().get(),
@@ -980,7 +982,7 @@
#ifdef MULTICHANNEL_EFFECT_CHAIN
if (status != NO_ERROR &&
- callback->isOutput() &&
+ mIsOutput &&
(mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
|| mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO)) {
// Older effects may require exact STEREO position mask.
@@ -1056,6 +1058,13 @@
&size,
&cmdStatus);
}
+
+ if (isVolumeControl()) {
+ // Force initializing the volume as 0 for volume control effect for safer ramping
+ uint32_t left = 0;
+ uint32_t right = 0;
+ setVolumeInternal(&left, &right, true /*controller*/);
+ }
}
// mConfig.outputCfg.buffer.frameCount cannot be zero.
@@ -1429,23 +1438,24 @@
((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
(mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND ||
(mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_MONITOR)) {
- uint32_t volume[2];
- uint32_t *pVolume = NULL;
- uint32_t size = sizeof(volume);
- volume[0] = *left;
- volume[1] = *right;
- if (controller) {
- pVolume = volume;
- }
- status = mEffectInterface->command(EFFECT_CMD_SET_VOLUME,
- size,
- volume,
- &size,
- pVolume);
- if (controller && status == NO_ERROR && size == sizeof(volume)) {
- *left = volume[0];
- *right = volume[1];
- }
+ status = setVolumeInternal(left, right, controller);
+ }
+ return status;
+}
+
+status_t AudioFlinger::EffectModule::setVolumeInternal(
+ uint32_t *left, uint32_t *right, bool controller) {
+ uint32_t volume[2] = {*left, *right};
+ uint32_t *pVolume = controller ? volume : nullptr;
+ uint32_t size = sizeof(volume);
+ status_t status = mEffectInterface->command(EFFECT_CMD_SET_VOLUME,
+ size,
+ volume,
+ &size,
+ pVolume);
+ if (controller && status == NO_ERROR && size == sizeof(volume)) {
+ *left = volume[0];
+ *right = volume[1];
}
return status;
}
@@ -1643,6 +1653,22 @@
return status;
}
+status_t AudioFlinger::EffectModule::getConfigs(
+ audio_config_base_t* inputCfg, audio_config_base_t* outputCfg, bool* isOutput) const {
+ Mutex::Autolock _l(mLock);
+ if (mConfig.inputCfg.mask == 0 || mConfig.outputCfg.mask == 0) {
+ return NO_INIT;
+ }
+ inputCfg->sample_rate = mConfig.inputCfg.samplingRate;
+ inputCfg->channel_mask = static_cast<audio_channel_mask_t>(mConfig.inputCfg.channels);
+ inputCfg->format = static_cast<audio_format_t>(mConfig.inputCfg.format);
+ outputCfg->sample_rate = mConfig.outputCfg.samplingRate;
+ outputCfg->channel_mask = static_cast<audio_channel_mask_t>(mConfig.outputCfg.channels);
+ outputCfg->format = static_cast<audio_format_t>(mConfig.outputCfg.format);
+ *isOutput = mIsOutput;
+ return NO_ERROR;
+}
+
static std::string dumpInOutBuffer(bool isInput, const sp<EffectBufferHalInterface> &buffer) {
std::stringstream ss;
@@ -1761,6 +1787,7 @@
BINDER_METHOD_ENTRY(command) \
BINDER_METHOD_ENTRY(disconnect) \
BINDER_METHOD_ENTRY(getCblk) \
+BINDER_METHOD_ENTRY(getConfig) \
// singleton for Binder Method Statistics for IEffect
mediautils::MethodStatistics<int>& getIEffectStatistics() {
@@ -1804,6 +1831,13 @@
*_aidl_return = (code); \
return Status::ok();
+#define VALUE_OR_RETURN_STATUS_AS_OUT(exp) \
+ ({ \
+ auto _tmp = (exp); \
+ if (!_tmp.ok()) { RETURN(_tmp.error()); } \
+ std::move(_tmp.value()); \
+ })
+
Status AudioFlinger::EffectHandle::enable(int32_t* _aidl_return)
{
AutoMutex _l(mLock);
@@ -1915,6 +1949,32 @@
return Status::ok();
}
+Status AudioFlinger::EffectHandle::getConfig(
+ media::EffectConfig* _config, int32_t* _aidl_return) {
+ AutoMutex _l(mLock);
+ sp<EffectBase> effect = mEffect.promote();
+ if (effect == nullptr || mDisconnected) {
+ RETURN(DEAD_OBJECT);
+ }
+ sp<EffectModule> effectModule = effect->asEffectModule();
+ if (effectModule == nullptr) {
+ RETURN(INVALID_OPERATION);
+ }
+ audio_config_base_t inputCfg = AUDIO_CONFIG_BASE_INITIALIZER;
+ audio_config_base_t outputCfg = AUDIO_CONFIG_BASE_INITIALIZER;
+ bool isOutput;
+ status_t status = effectModule->getConfigs(&inputCfg, &outputCfg, &isOutput);
+ if (status == NO_ERROR) {
+ constexpr bool isInput = false; // effects always use 'OUT' channel masks.
+ _config->inputCfg = VALUE_OR_RETURN_STATUS_AS_OUT(
+ legacy2aidl_audio_config_base_t_AudioConfigBase(inputCfg, isInput));
+ _config->outputCfg = VALUE_OR_RETURN_STATUS_AS_OUT(
+ legacy2aidl_audio_config_base_t_AudioConfigBase(outputCfg, isInput));
+ _config->isOnInputStream = !isOutput;
+ }
+ RETURN(status);
+}
+
Status AudioFlinger::EffectHandle::command(int32_t cmdCode,
const std::vector<uint8_t>& cmdData,
int32_t maxResponseSize,
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 42614cc..78788df 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -283,6 +283,10 @@
status_t setHapticIntensity(int id, int intensity);
status_t setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo);
+ status_t getConfigs(audio_config_base_t* inputCfg,
+ audio_config_base_t* outputCfg,
+ bool* isOutput) const;
+
void dump(int fd, const Vector<String16>& args);
private:
@@ -302,6 +306,8 @@
? EFFECT_BUFFER_ACCESS_WRITE : EFFECT_BUFFER_ACCESS_ACCUMULATE;
}
+ status_t setVolumeInternal(uint32_t *left, uint32_t *right, bool controller);
+
effect_config_t mConfig; // input and output audio configuration
sp<EffectHalInterface> mEffectInterface; // Effect module HAL
@@ -314,6 +320,7 @@
uint32_t mDisableWaitCnt; // current process() calls count during disable period.
bool mOffloaded; // effect is currently offloaded to the audio DSP
bool mAddedToHal; // effect has been added to the audio HAL
+ bool mIsOutput; // direction of the AF thread
#ifdef FLOAT_EFFECT_CHAIN
bool mSupportsFloat; // effect supports float processing
@@ -370,6 +377,8 @@
int32_t* _aidl_return) override;
android::binder::Status disconnect() override;
android::binder::Status getCblk(media::SharedFileRegion* _aidl_return) override;
+ android::binder::Status getConfig(media::EffectConfig* _config,
+ int32_t* _aidl_return) override;
sp<Client> client() const { return mClient; }
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 26bd92d..61dd3f2 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -79,8 +79,6 @@
mMasterMono(false),
mThreadIoHandle(parentIoHandle)
{
- (void)mThreadIoHandle; // prevent unused warning, see C++17 [[maybe_unused]]
-
// FIXME pass sInitial as parameter to base class constructor, and make it static local
mPrevious = &sInitial;
mCurrent = &sInitial;
diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/FastMixer.h
index 97ab635..d71519f 100644
--- a/services/audioflinger/FastMixer.h
+++ b/services/audioflinger/FastMixer.h
@@ -107,7 +107,8 @@
std::atomic<float> mMasterBalance{};
std::atomic_int_fast64_t mBoottimeOffset;
- const audio_io_handle_t mThreadIoHandle; // parent thread id for debugging purposes
+ // parent thread id for debugging purposes
+ [[maybe_unused]] const audio_io_handle_t mThreadIoHandle;
#ifdef TEE_SINK
NBAIO_Tee mTee;
#endif
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 93593a3..68a3800 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -31,7 +31,6 @@
mPlaybackThreadHandle(playbackThreadHandle),
mRecordThreadHandle(recordThreadHandle) {}
SoftwarePatch(const SoftwarePatch&) = default;
- SoftwarePatch& operator=(const SoftwarePatch&) = default;
// Must be called under AudioFlinger::mLock
status_t getLatencyMs_l(double *latencyMs) const;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 6a138bb..33983d7 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -310,6 +310,7 @@
binder::Status unmute(/*out*/ bool *ret) override;
private:
Track* const mTrack;
+ bool setMute(bool muted);
};
sp<AudioVibrationController> mAudioVibrationController;
sp<os::ExternalVibration> mExternalVibration;
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index daec57e..f0a5f76 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -73,7 +73,8 @@
void setSilenced(bool silenced) { if (!isPatchTrack()) mSilenced = silenced; }
bool isSilenced() const { return mSilenced; }
- status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ status_t getActiveMicrophones(
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones);
status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
status_t setPreferredMicrophoneFieldDimension(float zoom);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 73ee691..37b8fe8 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -271,8 +271,8 @@
static std::string toString(audio_latency_mode_t mode) {
// We convert to the AIDL type to print (eventually the legacy type will be removed).
- const auto result = legacy2aidl_audio_latency_mode_t_LatencyMode(mode);
- return result.has_value() ? media::toString(*result) : "UNKNOWN";
+ const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+ return result.has_value() ? media::audio::common::toString(*result) : "UNKNOWN";
}
// Could be made a template, but other toString overloads for std::vector are confused.
@@ -2063,7 +2063,8 @@
mHwSupportsPause(false), mHwPaused(false), mFlushPending(false),
mLeftVolFloat(-1.0), mRightVolFloat(-1.0),
mDownStreamPatch{},
- mIsTimestampAdvancing(kMinimumTimeBetweenTimestampChecksNs)
+ mIsTimestampAdvancing(kMinimumTimeBetweenTimestampChecksNs),
+ mBluetoothLatencyModesEnabled(true)
{
snprintf(mThreadName, kThreadNameLength, "AudioOut_%X", id);
mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
@@ -2139,9 +2140,19 @@
if (!isStreamInitialized()) {
ALOGE("The stream is not open yet"); // This should not happen.
} else {
- // setEventCallback will need a strong pointer as a parameter. Calling it
- // here instead of constructor of PlaybackThread so that the onFirstRef
- // callback would not be made on an incompletely constructed object.
+ // Callbacks take strong or weak pointers as a parameter.
+ // Since PlaybackThread passes itself as a callback handler, it can only
+ // be done outside of the constructor. Creating weak and especially strong
+ // pointers to a refcounted object in its own constructor is strongly
+ // discouraged, see comments in system/core/libutils/include/utils/RefBase.h.
+ // Even if a function takes a weak pointer, it is possible that it will
+ // need to convert it to a strong pointer down the line.
+ if (mOutput->flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING &&
+ mOutput->stream->setCallback(this) == OK) {
+ mUseAsyncWrite = true;
+ mCallbackThread = new AudioFlinger::AsyncCallbackThread(this);
+ }
+
if (mOutput->stream->setEventCallback(this) != OK) {
ALOGD("Failed to add event callback");
}
@@ -2908,7 +2919,14 @@
void AudioFlinger::PlaybackThread::onCodecFormatChanged(
const std::basic_string<uint8_t>& metadataBs)
{
- std::thread([this, metadataBs]() {
+ wp<AudioFlinger::PlaybackThread> weakPointerThis = this;
+ std::thread([this, metadataBs, weakPointerThis]() {
+ sp<AudioFlinger::PlaybackThread> playbackThread = weakPointerThis.promote();
+ if (playbackThread == nullptr) {
+ ALOGW("PlaybackThread was destroyed, skip codec format change event");
+ return;
+ }
+
audio_utils::metadata::Data metadata =
audio_utils::metadata::dataFromByteString(metadataBs);
if (metadata.empty()) {
@@ -2999,13 +3017,6 @@
mFrameCount);
}
- if (mOutput->flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING) {
- if (mOutput->stream->setCallback(this) == OK) {
- mUseAsyncWrite = true;
- mCallbackThread = new AudioFlinger::AsyncCallbackThread(this);
- }
- }
-
mHwSupportsPause = false;
if (mOutput->flags & AUDIO_OUTPUT_FLAG_DIRECT) {
bool supportsPause = false, supportsResume = false;
@@ -3282,7 +3293,7 @@
}
void AudioFlinger::PlaybackThread::threadLoop_removeTracks(
- const Vector< sp<Track> >& tracksToRemove)
+ [[maybe_unused]] const Vector< sp<Track> >& tracksToRemove)
{
// Miscellaneous track cleanup when removed from the active list,
// called without Thread lock but synchronized with threadLoop processing.
@@ -3293,8 +3304,6 @@
addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
}
}
-#else
- (void)tracksToRemove; // suppress unused warning
#endif
}
@@ -3527,9 +3536,9 @@
if (result != OK) return result;
#ifdef FLOAT_EFFECT_CHAIN
- buffer = halInBuffer->audioBuffer()->f32;
+ buffer = halInBuffer ? halInBuffer->audioBuffer()->f32 : buffer;
#else
- buffer = halInBuffer->audioBuffer()->s16;
+ buffer = halInBuffer ? halInBuffer->audioBuffer()->s16 : buffer;
#endif
ALOGV("addEffectChain_l() creating new input buffer %p session %d",
buffer, session);
@@ -3558,7 +3567,8 @@
halOutBuffer = halInBuffer;
ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
if (!audio_is_global_session(session)) {
- buffer = reinterpret_cast<effect_buffer_t*>(halInBuffer->externalData());
+ buffer = halInBuffer ? reinterpret_cast<effect_buffer_t*>(halInBuffer->externalData())
+ : buffer;
// Only one effect chain can be present in direct output thread and it uses
// the sink buffer as input
if (mType != DIRECT) {
@@ -3570,9 +3580,9 @@
&halInBuffer);
if (result != OK) return result;
#ifdef FLOAT_EFFECT_CHAIN
- buffer = halInBuffer->audioBuffer()->f32;
+ buffer = halInBuffer ? halInBuffer->audioBuffer()->f32 : buffer;
#else
- buffer = halInBuffer->audioBuffer()->s16;
+ buffer = halInBuffer ? halInBuffer->audioBuffer()->s16 : buffer;
#endif
ALOGV("addEffectChain_l() creating new input buffer %p session %d",
buffer, session);
@@ -5817,7 +5827,7 @@
}
// Push the new FastMixer state if necessary
- bool pauseAudioWatchdog = false;
+ [[maybe_unused]] bool pauseAudioWatchdog = false;
if (didModify) {
state->mFastTracksGen++;
// if the fast mixer was active, but now there are no fast tracks, then put it in cold idle
@@ -6133,8 +6143,10 @@
// ----------------------------------------------------------------------------
AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
- AudioStreamOut* output, audio_io_handle_t id, ThreadBase::type_t type, bool systemReady)
+ AudioStreamOut* output, audio_io_handle_t id, ThreadBase::type_t type, bool systemReady,
+ const audio_offload_info_t& offloadInfo)
: PlaybackThread(audioFlinger, output, id, type, systemReady)
+ , mOffloadInfo(offloadInfo)
{
setMasterBalance(audioFlinger->getMasterBalance_l());
}
@@ -6400,7 +6412,8 @@
// fill a buffer, then remove it from active list.
// Only consider last track started for mixer state control
bool isTimestampAdvancing = mIsTimestampAdvancing.check(mOutput);
- if (--(track->mRetryCount) <= 0) {
+ if (!isTunerStream() // tuner streams remain active in underrun
+ && --(track->mRetryCount) <= 0) {
if (isTimestampAdvancing) { // HAL is still playing audio, give us more time.
track->mRetryCount = kMaxTrackRetriesOffload;
} else {
@@ -6444,6 +6457,7 @@
(doHwPause || (mFlushPending && !mHwPaused && (count != 0)))) {
status_t result = mOutput->stream->pause();
ALOGE_IF(result != OK, "Error when pausing output stream: %d", result);
+ doHwResume = !doHwPause; // resume if pause is due to flush.
}
if (mFlushPending) {
flushHw_l();
@@ -6763,8 +6777,9 @@
// ----------------------------------------------------------------------------
AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
- AudioStreamOut* output, audio_io_handle_t id, bool systemReady)
- : DirectOutputThread(audioFlinger, output, id, OFFLOAD, systemReady),
+ AudioStreamOut* output, audio_io_handle_t id, bool systemReady,
+ const audio_offload_info_t& offloadInfo)
+ : DirectOutputThread(audioFlinger, output, id, OFFLOAD, systemReady, offloadInfo),
mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true)
{
//FIXME: mStandby should be set to true by ThreadBase constructo
@@ -6983,7 +6998,8 @@
// No buffers for this track. Give it a few chances to
// fill a buffer, then remove it from active list.
bool isTimestampAdvancing = mIsTimestampAdvancing.check(mOutput);
- if (--(track->mRetryCount) <= 0) {
+ if (!isTunerStream() // tuner streams remain active in underrun
+ && --(track->mRetryCount) <= 0) {
if (isTimestampAdvancing) { // HAL is still playing audio, give us more time.
track->mRetryCount = kMaxTrackRetriesOffload;
} else {
@@ -7012,6 +7028,7 @@
if (!mStandby && (doHwPause || (mFlushPending && !mHwPaused && (count != 0)))) {
status_t result = mOutput->stream->pause();
ALOGE_IF(result != OK, "Error when pausing output stream: %d", result);
+ doHwResume = !doHwPause; // resume if pause is due to flush.
}
if (mFlushPending) {
flushHw_l();
@@ -7427,6 +7444,15 @@
return NO_ERROR;
}
+status_t AudioFlinger::PlaybackThread::setBluetoothVariableLatencyEnabled(bool enabled) {
+ if (mOutput == nullptr || mOutput->audioHwDev == nullptr
+ || !mOutput->audioHwDev->supportsBluetoothVariableLatency()) {
+ return INVALID_OPERATION;
+ }
+ mBluetoothLatencyModesEnabled.store(enabled);
+ return NO_ERROR;
+}
+
void AudioFlinger::SpatializerThread::checkOutputStageEffects()
{
bool hasVirtualizer = false;
@@ -7542,7 +7568,7 @@
size_t numCounterOffers = 0;
const NBAIO_Format offers[1] = {Format_from_SR_C(mSampleRate, mChannelCount, mFormat)};
#if !LOG_NDEBUG
- ssize_t index =
+ [[maybe_unused]] ssize_t index =
#else
(void)
#endif
@@ -7561,10 +7587,11 @@
ALOGV("%p kUseFastCapture = Always, initFastCapture = true", this);
break;
case FastCapture_Static:
- initFastCapture = (mFrameCount * 1000) / mSampleRate < kMinNormalCaptureBufferSizeMs;
- ALOGV("%p kUseFastCapture = Static, (%lld * 1000) / %u vs %u, initFastCapture = %d",
- this, (long long)mFrameCount, mSampleRate, kMinNormalCaptureBufferSizeMs,
- initFastCapture);
+ initFastCapture = !mIsMsdDevice // Disable fast capture for MSD BUS devices.
+ && (mFrameCount * 1000) / mSampleRate < kMinNormalCaptureBufferSizeMs;
+ ALOGV("%p kUseFastCapture = Static, (%lld * 1000) / %u vs %u, initFastCapture = %d "
+ "mIsMsdDevice = %d", this, (long long)mFrameCount, mSampleRate,
+ kMinNormalCaptureBufferSizeMs, initFastCapture, mIsMsdDevice);
break;
// case FastCapture_Dynamic:
}
@@ -7592,7 +7619,7 @@
Pipe *pipe = new Pipe(pipeFramesP2, format, pipeBuffer);
const NBAIO_Format offers[1] = {format};
size_t numCounterOffers = 0;
- ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
+ [[maybe_unused]] ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
ALOG_ASSERT(index == 0);
mPipeSink = pipe;
PipeReader *pipeReader = new PipeReader(*pipe);
@@ -8696,7 +8723,7 @@
}
status_t AudioFlinger::RecordThread::getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones)
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones)
{
ALOGV("RecordThread::getActiveMicrophones");
AutoMutex _l(mLock);
@@ -9048,7 +9075,8 @@
audio_format_t reqFormat = mFormat;
uint32_t samplingRate = mSampleRate;
// TODO this may change if we want to support capture from HDMI PCM multi channel (e.g on TVs).
- audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(mChannelCount);
+ [[maybe_unused]] audio_channel_mask_t channelMask =
+ audio_channel_in_mask_from_count(mChannelCount);
AudioParameter param = AudioParameter(keyValuePair);
int value;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index ad5617d..ce90767 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1086,6 +1086,8 @@
return INVALID_OPERATION;
}
+ virtual status_t setBluetoothVariableLatencyEnabled(bool enabled);
+
protected:
// updated by readOutputParameters_l()
size_t mNormalFrameCount; // normal mixer and effects
@@ -1436,6 +1438,9 @@
virtual void flushHw_l() {
mIsTimestampAdvancing.clear();
}
+
+ // Bluetooth Variable latency control logic is enabled or disabled for this thread
+ std::atomic_bool mBluetoothLatencyModesEnabled;
};
class MixerThread : public PlaybackThread {
@@ -1541,8 +1546,9 @@
public:
DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, bool systemReady)
- : DirectOutputThread(audioFlinger, output, id, DIRECT, systemReady) { }
+ audio_io_handle_t id, bool systemReady,
+ const audio_offload_info_t& offloadInfo)
+ : DirectOutputThread(audioFlinger, output, id, DIRECT, systemReady, offloadInfo) { }
virtual ~DirectOutputThread();
@@ -1574,11 +1580,14 @@
virtual void onAddNewTrack_l();
+ const audio_offload_info_t mOffloadInfo;
bool mVolumeShaperActive = false;
DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, ThreadBase::type_t type, bool systemReady);
+ audio_io_handle_t id, ThreadBase::type_t type, bool systemReady,
+ const audio_offload_info_t& offloadInfo);
void processVolume_l(Track *track, bool lastTrack);
+ bool isTunerStream() const { return (mOffloadInfo.content_id > 0); }
// prepareTracks_l() tells threadLoop_mix() the name of the single active track
sp<Track> mActiveTrack;
@@ -1616,7 +1625,8 @@
public:
OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, bool systemReady);
+ audio_io_handle_t id, bool systemReady,
+ const audio_offload_info_t& offloadInfo);
virtual ~OffloadThread() {};
void flushHw_l() override;
@@ -1931,7 +1941,8 @@
// Sets the UID records silence
void setRecordSilenced(audio_port_handle_t portId, bool silenced);
- status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ status_t getActiveMicrophones(
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones);
status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
status_t setPreferredMicrophoneFieldDimension(float zoom);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 10f9f73..300ad9f 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -439,7 +439,8 @@
return Status::ok();
}
-Status AudioFlinger::TrackHandle::getDualMonoMode(media::AudioDualMonoMode* _aidl_return)
+Status AudioFlinger::TrackHandle::getDualMonoMode(
+ media::audio::common::AudioDualMonoMode* _aidl_return)
{
audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
const status_t status = mTrack->getDualMonoMode(&mode)
@@ -452,7 +453,7 @@
}
Status AudioFlinger::TrackHandle::setDualMonoMode(
- media::AudioDualMonoMode mode)
+ media::audio::common::AudioDualMonoMode mode)
{
const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
@@ -476,7 +477,7 @@
}
Status AudioFlinger::TrackHandle::getPlaybackRateParameters(
- media::AudioPlaybackRate* _aidl_return)
+ media::audio::common::AudioPlaybackRate* _aidl_return)
{
audio_playback_rate_t localPlaybackRate{};
status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
@@ -489,7 +490,7 @@
}
Status AudioFlinger::TrackHandle::setPlaybackRateParameters(
- const media::AudioPlaybackRate& playbackRate)
+ const media::audio::common::AudioPlaybackRate& playbackRate)
{
const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
@@ -1916,9 +1917,7 @@
}
}
-binder::Status AudioFlinger::PlaybackThread::Track::AudioVibrationController::mute(
- /*out*/ bool *ret) {
- *ret = false;
+bool AudioFlinger::PlaybackThread::Track::AudioVibrationController::setMute(bool muted) {
sp<ThreadBase> thread = mTrack->mThread.promote();
if (thread != 0) {
// Lock for updating mHapticPlaybackEnabled.
@@ -1926,27 +1925,22 @@
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
&& playbackThread->mHapticChannelCount > 0) {
- mTrack->setHapticPlaybackEnabled(false);
- *ret = true;
+ mTrack->setHapticPlaybackEnabled(!muted);
+ return true;
}
}
+ return false;
+}
+
+binder::Status AudioFlinger::PlaybackThread::Track::AudioVibrationController::mute(
+ /*out*/ bool *ret) {
+ *ret = setMute(true);
return binder::Status::ok();
}
binder::Status AudioFlinger::PlaybackThread::Track::AudioVibrationController::unmute(
/*out*/ bool *ret) {
- *ret = false;
- sp<ThreadBase> thread = mTrack->mThread.promote();
- if (thread != 0) {
- // Lock for updating mHapticPlaybackEnabled.
- Mutex::Autolock _l(thread->mLock);
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
- if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
- && playbackThread->mHapticChannelCount > 0) {
- mTrack->setHapticPlaybackEnabled(true);
- *ret = true;
- }
- }
+ *ret = setMute(false);
return binder::Status::ok();
}
@@ -2356,15 +2350,9 @@
}
binder::Status AudioFlinger::RecordHandle::getActiveMicrophones(
- std::vector<media::MicrophoneInfoData>* activeMicrophones) {
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
ALOGV("%s()", __func__);
- std::vector<media::MicrophoneInfo> mics;
- status_t status = mRecordTrack->getActiveMicrophones(&mics);
- activeMicrophones->resize(mics.size());
- for (size_t i = 0; status == OK && i < mics.size(); ++i) {
- status = mics[i].writeToParcelable(&activeMicrophones->at(i));
- }
- return binderStatusFromStatusT(status);
+ return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
}
binder::Status AudioFlinger::RecordHandle::setPreferredMicrophoneDirection(
@@ -2684,7 +2672,7 @@
}
status_t AudioFlinger::RecordThread::RecordTrack::getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones)
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones)
{
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index cf1f64c..a62d3f0 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -194,6 +194,9 @@
{AUDIO_FORMAT_E_AC3, {}},
{AUDIO_FORMAT_DTS, {}},
{AUDIO_FORMAT_DTS_HD, {}},
+ {AUDIO_FORMAT_DTS_HD_MA, {}},
+ {AUDIO_FORMAT_DTS_UHD, {}},
+ {AUDIO_FORMAT_DTS_UHD_P2, {}},
{AUDIO_FORMAT_AAC_LC, {
AUDIO_FORMAT_AAC_HE_V1, AUDIO_FORMAT_AAC_HE_V2, AUDIO_FORMAT_AAC_ELD,
AUDIO_FORMAT_AAC_XHE}},
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index bb1699e..3b19e52 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -55,7 +55,7 @@
status_t getAudioPolicyMix(audio_devices_t deviceType,
const String8& address, sp<AudioPolicyMix> &policyMix) const;
- status_t registerMix(AudioMix mix, sp<SwAudioOutputDescriptor> desc);
+ status_t registerMix(const AudioMix& mix, const sp<SwAudioOutputDescriptor>& desc);
status_t unregisterMix(const AudioMix& mix);
@@ -76,7 +76,7 @@
sp<AudioPolicyMix> &primaryMix,
std::vector<sp<AudioPolicyMix>> *secondaryMixes);
- sp<DeviceDescriptor> getDeviceAndMixForInputSource(audio_source_t inputSource,
+ sp<DeviceDescriptor> getDeviceAndMixForInputSource(const audio_attributes_t& attributes,
const DeviceVector &availableDeviceTypes,
uid_t uid,
sp<AudioPolicyMix> *policyMix) const;
@@ -124,7 +124,7 @@
void dump(String8 *dst) const;
private:
- enum class MixMatchStatus { MATCH, NO_MATCH, INVALID_MIX };
+ enum class MixMatchStatus { MATCH, NO_MATCH };
MixMatchStatus mixMatch(const AudioMix* mix, size_t mixIndex,
const audio_attributes_t& attributes,
const audio_config_base_t& config,
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index e142bef..56c0603 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "APM_AudioPolicyMix"
//#define LOG_NDEBUG 0
+#include <algorithm>
#include "AudioPolicyMix.h"
#include "TypeConverter.h"
#include "HwModule.h"
@@ -25,6 +26,89 @@
#include <AudioOutputDescriptor.h>
namespace android {
+namespace {
+
+// Returns true if the criterion matches.
+// The exclude criteria are handled in the same way as positive
+// ones - only condition is matched (the function will return
+// same result both for RULE_MATCH_X and RULE_EXCLUDE_X).
+bool isCriterionMatched(const AudioMixMatchCriterion& criterion,
+ const audio_attributes_t& attr,
+ const uid_t uid) {
+ uint32_t ruleWithoutExclusion = criterion.mRule & ~RULE_EXCLUSION_MASK;
+ switch(ruleWithoutExclusion) {
+ case RULE_MATCH_ATTRIBUTE_USAGE:
+ return criterion.mValue.mUsage == attr.usage;
+ case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+ return criterion.mValue.mSource == attr.source;
+ case RULE_MATCH_UID:
+ return criterion.mValue.mUid == uid;
+ case RULE_MATCH_USERID:
+ {
+ userid_t userId = multiuser_get_user_id(uid);
+ return criterion.mValue.mUserId == userId;
+ }
+ }
+ ALOGE("Encountered invalid mix rule 0x%x", criterion.mRule);
+ return false;
+}
+
+// Returns true if vector of criteria is matched:
+// - If any of the exclude criteria is matched the criteria doesn't match.
+// - Otherwise, for each 'dimension' of positive rule present
+// (usage, capture preset, uid, userid...) at least one rule must match
+// for the criteria to match.
+bool areMixCriteriaMatched(const std::vector<AudioMixMatchCriterion>& criteria,
+ const audio_attributes_t& attr,
+ const uid_t uid) {
+ // If any of the exclusion criteria are matched the mix doesn't match.
+ auto isMatchingExcludeCriterion = [&](const AudioMixMatchCriterion& c) {
+ return c.isExcludeCriterion() && isCriterionMatched(c, attr, uid);
+ };
+ if (std::any_of(criteria.begin(), criteria.end(), isMatchingExcludeCriterion)) {
+ return false;
+ }
+
+ uint32_t presentPositiveRules = 0; // Bitmask of all present positive criteria.
+ uint32_t matchedPositiveRules = 0; // Bitmask of all matched positive criteria.
+ for (const auto& criterion : criteria) {
+ if (criterion.isExcludeCriterion()) {
+ continue;
+ }
+ presentPositiveRules |= criterion.mRule;
+ if (isCriterionMatched(criterion, attr, uid)) {
+ matchedPositiveRules |= criterion.mRule;
+ }
+ }
+ return presentPositiveRules == matchedPositiveRules;
+}
+
+// Consistency checks: for each "dimension" of rules (usage, uid...), we can
+// only have MATCH rules, or EXCLUDE rules in each dimension, not a combination.
+bool areMixCriteriaConsistent(const std::vector<AudioMixMatchCriterion>& criteria) {
+ std::set<uint32_t> positiveCriteria;
+ for (const AudioMixMatchCriterion& c : criteria) {
+ if (c.isExcludeCriterion()) {
+ continue;
+ }
+ positiveCriteria.insert(c.mRule);
+ }
+
+ auto isConflictingCriterion = [&positiveCriteria](const AudioMixMatchCriterion& c) {
+ uint32_t ruleWithoutExclusion = c.mRule & ~RULE_EXCLUSION_MASK;
+ return c.isExcludeCriterion() &&
+ (positiveCriteria.find(ruleWithoutExclusion) != positiveCriteria.end());
+ };
+ return std::none_of(criteria.begin(), criteria.end(), isConflictingCriterion);
+}
+
+template <typename Predicate>
+void EraseCriteriaIf(std::vector<AudioMixMatchCriterion>& v,
+ const Predicate& predicate) {
+ v.erase(std::remove_if(v.begin(), v.end(), predicate), v.end());
+}
+
+} // namespace
void AudioPolicyMix::dump(String8 *dst, int spaces, int index) const
{
@@ -78,7 +162,8 @@
}
}
-status_t AudioPolicyMixCollection::registerMix(AudioMix mix, sp<SwAudioOutputDescriptor> desc)
+status_t AudioPolicyMixCollection::registerMix(const AudioMix& mix,
+ const sp<SwAudioOutputDescriptor>& desc)
{
for (size_t i = 0; i < size(); i++) {
const sp<AudioPolicyMix>& registeredMix = itemAt(i);
@@ -89,12 +174,17 @@
return BAD_VALUE;
}
}
- sp<AudioPolicyMix> policyMix = new AudioPolicyMix(mix);
+ if (!areMixCriteriaConsistent(mix.mCriteria)) {
+ ALOGE("registerMix(): Mix contains inconsistent criteria "
+ "(MATCH & EXCLUDE criteria of the same type)");
+ return BAD_VALUE;
+ }
+ sp<AudioPolicyMix> policyMix = sp<AudioPolicyMix>::make(mix);
add(policyMix);
ALOGD("registerMix(): adding mix for dev=0x%x addr=%s",
policyMix->mDeviceType, policyMix->mDeviceAddress.string());
- if (desc != 0) {
+ if (desc != nullptr) {
desc->mPolicyMix = policyMix;
policyMix->setOutput(desc);
}
@@ -177,15 +267,9 @@
continue; // Primary output already found
}
- switch (mixMatch(policyMix.get(), i, attributes, config, uid)) {
- case MixMatchStatus::INVALID_MIX:
- // The mix has contradictory rules, ignore it
- // TODO: reject invalid mix at registration
- continue;
- case MixMatchStatus::NO_MATCH:
- ALOGV("%s: Mix %zu: does not match", __func__, i);
- continue; // skip the mix
- case MixMatchStatus::MATCH:;
+ if(mixMatch(policyMix.get(), i, attributes, config, uid) == MixMatchStatus::NO_MATCH) {
+ ALOGV("%s: Mix %zu: does not match", __func__, i);
+ continue; // skip the mix
}
if (primaryOutputMix) {
@@ -239,136 +323,19 @@
return MixMatchStatus::NO_MATCH;
}
- int userId = (int) multiuser_get_user_id(uid);
-
- // TODO if adding more player rules (currently only 2), make rule handling "generic"
- // as there is no difference in the treatment of usage- or uid-based rules
- bool hasUsageMatchRules = false;
- bool hasUsageExcludeRules = false;
- bool usageMatchFound = false;
- bool usageExclusionFound = false;
-
- bool hasUidMatchRules = false;
- bool hasUidExcludeRules = false;
- bool uidMatchFound = false;
- bool uidExclusionFound = false;
-
- bool hasUserIdExcludeRules = false;
- bool userIdExclusionFound = false;
- bool hasUserIdMatchRules = false;
- bool userIdMatchFound = false;
-
-
- bool hasAddrMatch = false;
-
- // iterate over all mix criteria to list what rules this mix contains
- for (size_t j = 0; j < mix->mCriteria.size(); j++) {
- ALOGV(" getOutputForAttr: mix %zu: inspecting mix criteria %zu of %zu",
- mixIndex, j, mix->mCriteria.size());
-
- // if there is an address match, prioritize that match
- if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
- strncmp(attributes.tags + strlen("addr="),
- mix->mDeviceAddress.string(),
- AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
- hasAddrMatch = true;
- break;
- }
-
- switch (mix->mCriteria[j].mRule) {
- case RULE_MATCH_ATTRIBUTE_USAGE:
- ALOGV("\tmix has RULE_MATCH_ATTRIBUTE_USAGE for usage %d",
- mix->mCriteria[j].mValue.mUsage);
- hasUsageMatchRules = true;
- if (mix->mCriteria[j].mValue.mUsage == attributes.usage) {
- // found one match against all allowed usages
- usageMatchFound = true;
- }
- break;
- case RULE_EXCLUDE_ATTRIBUTE_USAGE:
- ALOGV("\tmix has RULE_EXCLUDE_ATTRIBUTE_USAGE for usage %d",
- mix->mCriteria[j].mValue.mUsage);
- hasUsageExcludeRules = true;
- if (mix->mCriteria[j].mValue.mUsage == attributes.usage) {
- // found this usage is to be excluded
- usageExclusionFound = true;
- }
- break;
- case RULE_MATCH_UID:
- ALOGV("\tmix has RULE_MATCH_UID for uid %d", mix->mCriteria[j].mValue.mUid);
- hasUidMatchRules = true;
- if (mix->mCriteria[j].mValue.mUid == uid) {
- // found one UID match against all allowed UIDs
- uidMatchFound = true;
- }
- break;
- case RULE_EXCLUDE_UID:
- ALOGV("\tmix has RULE_EXCLUDE_UID for uid %d", mix->mCriteria[j].mValue.mUid);
- hasUidExcludeRules = true;
- if (mix->mCriteria[j].mValue.mUid == uid) {
- // found this UID is to be excluded
- uidExclusionFound = true;
- }
- break;
- case RULE_MATCH_USERID:
- ALOGV("\tmix has RULE_MATCH_USERID for userId %d",
- mix->mCriteria[j].mValue.mUserId);
- hasUserIdMatchRules = true;
- if (mix->mCriteria[j].mValue.mUserId == userId) {
- // found one userId match against all allowed userIds
- userIdMatchFound = true;
- }
- break;
- case RULE_EXCLUDE_USERID:
- ALOGV("\tmix has RULE_EXCLUDE_USERID for userId %d",
- mix->mCriteria[j].mValue.mUserId);
- hasUserIdExcludeRules = true;
- if (mix->mCriteria[j].mValue.mUserId == userId) {
- // found this userId is to be excluded
- userIdExclusionFound = true;
- }
- break;
- default:
- break;
- }
-
- // consistency checks: for each "dimension" of rules (usage, uid...), we can
- // only have MATCH rules, or EXCLUDE rules in each dimension, not a combination
- if (hasUsageMatchRules && hasUsageExcludeRules) {
- ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_ATTRIBUTE_USAGE"
- " and RULE_EXCLUDE_ATTRIBUTE_USAGE in mix %zu", mixIndex);
- return MixMatchStatus::INVALID_MIX;
- }
- if (hasUidMatchRules && hasUidExcludeRules) {
- ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_UID"
- " and RULE_EXCLUDE_UID in mix %zu", mixIndex);
- return MixMatchStatus::INVALID_MIX;
- }
- if (hasUserIdMatchRules && hasUserIdExcludeRules) {
- ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_USERID"
- " and RULE_EXCLUDE_USERID in mix %zu", mixIndex);
- return MixMatchStatus::INVALID_MIX;
- }
-
- if ((hasUsageExcludeRules && usageExclusionFound)
- || (hasUidExcludeRules && uidExclusionFound)
- || (hasUserIdExcludeRules && userIdExclusionFound)) {
- break; // stop iterating on criteria because an exclusion was found (will fail)
- }
- }//iterate on mix criteria
-
- // determine if exiting on success (or implicit failure as desc is 0)
- if (hasAddrMatch ||
- !((hasUsageExcludeRules && usageExclusionFound) ||
- (hasUsageMatchRules && !usageMatchFound) ||
- (hasUidExcludeRules && uidExclusionFound) ||
- (hasUidMatchRules && !uidMatchFound) ||
- (hasUserIdExcludeRules && userIdExclusionFound) ||
- (hasUserIdMatchRules && !userIdMatchFound))) {
+ // if there is an address match, prioritize that match
+ if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
+ strncmp(attributes.tags + strlen("addr="),
+ mix->mDeviceAddress.string(),
+ AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
ALOGV("\tgetOutputForAttr will use mix %zu", mixIndex);
return MixMatchStatus::MATCH;
}
+ if (areMixCriteriaMatched(mix->mCriteria, attributes, uid)) {
+ ALOGV("\tgetOutputForAttr will use mix %zu", mixIndex);
+ return MixMatchStatus::MATCH;
+ }
} else if (mix->mMixType == MIX_TYPE_RECORDERS) {
if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
@@ -399,7 +366,7 @@
}
sp<DeviceDescriptor> AudioPolicyMixCollection::getDeviceAndMixForInputSource(
- audio_source_t inputSource,
+ const audio_attributes_t& attributes,
const DeviceVector &availDevices,
uid_t uid,
sp<AudioPolicyMix> *policyMix) const
@@ -409,28 +376,17 @@
if (mix->mMixType != MIX_TYPE_RECORDERS) {
continue;
}
- for (size_t j = 0; j < mix->mCriteria.size(); j++) {
- if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mix->mCriteria[j].mRule &&
- mix->mCriteria[j].mValue.mSource == inputSource) ||
- (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mix->mCriteria[j].mRule &&
- mix->mCriteria[j].mValue.mSource != inputSource) ||
- (RULE_MATCH_UID == mix->mCriteria[j].mRule &&
- mix->mCriteria[j].mValue.mUid == uid) ||
- (RULE_EXCLUDE_UID == mix->mCriteria[j].mRule &&
- mix->mCriteria[j].mValue.mUid != uid)) {
- // assuming PolicyMix only for remote submix for input
- // so mix->mDeviceType can only be AUDIO_DEVICE_OUT_REMOTE_SUBMIX
- audio_devices_t device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
- auto mixDevice =
- availDevices.getDevice(device, mix->mDeviceAddress, AUDIO_FORMAT_DEFAULT);
+ if (areMixCriteriaMatched(mix->mCriteria, attributes, uid)) {
+ // Assuming PolicyMix only for remote submix for input
+ // so mix->mDeviceType can only be AUDIO_DEVICE_OUT_REMOTE_SUBMIX.
+ auto mixDevice = availDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ mix->mDeviceAddress, AUDIO_FORMAT_DEFAULT);
if (mixDevice != nullptr) {
if (policyMix != nullptr) {
*policyMix = mix;
}
return mixDevice;
}
- break;
- }
}
}
return nullptr;
@@ -501,7 +457,7 @@
// AND it doesn't have a "match uid" rule
// THEN add a rule to exclude the uid
for (size_t i = 0; i < size(); i++) {
- const AudioPolicyMix *mix = itemAt(i).get();
+ AudioPolicyMix *mix = itemAt(i).get();
if (!mix->isDeviceAffinityCompatible()) {
continue;
}
@@ -531,27 +487,16 @@
status_t AudioPolicyMixCollection::removeUidDeviceAffinities(uid_t uid) {
// for each player mix: remove existing rules that match or exclude this uid
for (size_t i = 0; i < size(); i++) {
- bool foundUidRule = false;
- const AudioPolicyMix *mix = itemAt(i).get();
+ AudioPolicyMix *mix = itemAt(i).get();
if (!mix->isDeviceAffinityCompatible()) {
continue;
}
- std::vector<size_t> criteriaToRemove;
- for (size_t j = 0; j < mix->mCriteria.size(); j++) {
- const uint32_t rule = mix->mCriteria[j].mRule;
- // is this rule excluding the uid? (not considering uid match rules
- // as those are not used for uid-device affinity)
- if (rule == RULE_EXCLUDE_UID
- && uid == mix->mCriteria[j].mValue.mUid) {
- foundUidRule = true;
- criteriaToRemove.insert(criteriaToRemove.begin(), j);
- }
- }
- if (foundUidRule) {
- for (size_t j = 0; j < criteriaToRemove.size(); j++) {
- mix->mCriteria.removeAt(criteriaToRemove[j]);
- }
- }
+
+ // is this rule excluding the uid? (not considering uid match rules
+ // as those are not used for uid-device affinity)
+ EraseCriteriaIf(mix->mCriteria, [uid](const AudioMixMatchCriterion& c) {
+ return c.mRule == RULE_EXCLUDE_UID && c.mValue.mUid == uid;
+ });
}
return NO_ERROR;
}
@@ -586,7 +531,7 @@
// "match userId" rule for this userId, return an error
// (adding a userId-device affinity would result in contradictory rules)
for (size_t i = 0; i < size(); i++) {
- const AudioPolicyMix* mix = itemAt(i).get();
+ AudioPolicyMix* mix = itemAt(i).get();
if (!mix->isDeviceAffinityCompatible()) {
continue;
}
@@ -603,7 +548,7 @@
// AND it doesn't have a "match userId" rule
// THEN add a rule to exclude the userId
for (size_t i = 0; i < size(); i++) {
- const AudioPolicyMix *mix = itemAt(i).get();
+ AudioPolicyMix *mix = itemAt(i).get();
if (!mix->isDeviceAffinityCompatible()) {
continue;
}
@@ -633,27 +578,16 @@
status_t AudioPolicyMixCollection::removeUserIdDeviceAffinities(int userId) {
// for each player mix: remove existing rules that match or exclude this userId
for (size_t i = 0; i < size(); i++) {
- bool foundUserIdRule = false;
- const AudioPolicyMix *mix = itemAt(i).get();
+ AudioPolicyMix *mix = itemAt(i).get();
if (!mix->isDeviceAffinityCompatible()) {
continue;
}
- std::vector<size_t> criteriaToRemove;
- for (size_t j = 0; j < mix->mCriteria.size(); j++) {
- const uint32_t rule = mix->mCriteria[j].mRule;
- // is this rule excluding the userId? (not considering userId match rules
- // as those are not used for userId-device affinity)
- if (rule == RULE_EXCLUDE_USERID
- && userId == mix->mCriteria[j].mValue.mUserId) {
- foundUserIdRule = true;
- criteriaToRemove.insert(criteriaToRemove.begin(), j);
- }
- }
- if (foundUserIdRule) {
- for (size_t j = 0; j < criteriaToRemove.size(); j++) {
- mix->mCriteria.removeAt(criteriaToRemove[j]);
- }
- }
+
+ // is this rule excluding the userId? (not considering userId match rules
+ // as those are not used for userId-device affinity)
+ EraseCriteriaIf(mix->mCriteria, [userId](const AudioMixMatchCriterion& c) {
+ return c.mRule == RULE_EXCLUDE_USERID && c.mValue.mUserId == userId;
+ });
}
return NO_ERROR;
}
diff --git a/services/audiopolicy/config/surround_sound_configuration_aidl.xml b/services/audiopolicy/config/surround_sound_configuration_aidl.xml
new file mode 100644
index 0000000..cf15711
--- /dev/null
+++ b/services/audiopolicy/config/surround_sound_configuration_aidl.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<surroundSound>
+ <!-- Each of the listed formats gets an entry in Surround Settings dialog on TV devices.
+ There must be a corresponding Java ENCODING_... constant defined in AudioFormat.java,
+ and a display name defined in AudioFormat.toDisplayName. For the formats that don't
+ need a dedicated Surround Settings dialog entry, a subformats list has to be used. -->
+ <formats>
+ <format name="AUDIO_FORMAT_AC3" />
+ <format name="AUDIO_FORMAT_E_AC3" />
+ <format name="AUDIO_FORMAT_E_AC3_JOC" />
+ <format name="AUDIO_FORMAT_DOLBY_TRUEHD" />
+ <format name="AUDIO_FORMAT_DTS" />
+ <format name="AUDIO_FORMAT_DTS_HD" />
+ <format name="AUDIO_FORMAT_DTS_HD_MA" />
+ <format name="AUDIO_FORMAT_DTS_UHD" />
+ <format name="AUDIO_FORMAT_DTS_UHD_P2" />
+ <format name="AUDIO_FORMAT_AAC_LC" subformats="AUDIO_FORMAT_AAC_HE_V1 AUDIO_FORMAT_AAC_HE_V2 AUDIO_FORMAT_AAC_ELD AUDIO_FORMAT_AAC_XHE" />
+ <format name="AUDIO_FORMAT_AC4" />
+ </formats>
+</surroundSound>
diff --git a/services/audiopolicy/engine/common/src/VolumeCurve.cpp b/services/audiopolicy/engine/common/src/VolumeCurve.cpp
index 8aa4b08..fccbc60 100644
--- a/services/audiopolicy/engine/common/src/VolumeCurve.cpp
+++ b/services/audiopolicy/engine/common/src/VolumeCurve.cpp
@@ -52,7 +52,7 @@
volIdx = volIndexMin;
} else {
// This would result in a divide-by-zero below
- ALOG_ASSERT(volIndexmin != volIndexMax, "Invalid volume index range & value: 0");
+ ALOG_ASSERT(volIndexMin != volIndexMax, "Invalid volume index range & value: 0");
return NAN;
}
} else {
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 3d74920..2831a9b 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -333,7 +333,7 @@
return device;
}
- device = policyMixes.getDeviceAndMixForInputSource(attr.source,
+ device = policyMixes.getDeviceAndMixForInputSource(attr,
availableInputDevices,
uid,
mix);
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
index 40efb3d..b6089b7 100644
--- a/services/audiopolicy/engineconfigurable/tools/Android.bp
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -21,36 +21,23 @@
default_applicable_licenses: ["frameworks_av_license"],
}
-python_defaults {
- name: "tools_default",
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- },
- },
-}
-
//##################################################################################################
// Tools for audio policy engine criterion type configuration file
//
python_binary_host {
- name: "buildPolicyCriterionTypes.py",
+ name: "buildPolicyCriterionTypes",
main: "buildPolicyCriterionTypes.py",
srcs: [
"buildPolicyCriterionTypes.py",
],
- defaults: ["tools_default"],
}
genrule_defaults {
name: "buildpolicycriteriontypesrule",
- tools: ["buildPolicyCriterionTypes.py"],
+ tools: ["buildPolicyCriterionTypes"],
cmd: "cp $(locations :audio_policy_configuration_files) $(genDir)/. && " +
"cp $(location :audio_policy_configuration_top_file) $(genDir)/audio_policy_configuration.xml && " +
- "$(location buildPolicyCriterionTypes.py) " +
+ "$(location buildPolicyCriterionTypes) " +
" --androidaudiobaseheader $(location :libaudio_system_audio_base) " +
" --androidaudiocommonbaseheader $(location :libaudio_system_audio_common_base) " +
"--audiopolicyconfigurationfile $(genDir)/audio_policy_configuration.xml " +
@@ -72,12 +59,11 @@
// Tools for audio policy engine parameter framework configurable domains
//
python_binary_host {
- name: "domainGeneratorPolicy.py",
+ name: "domainGeneratorPolicy",
main: "domainGeneratorPolicy.py",
srcs: [
"domainGeneratorPolicy.py",
],
- defaults: ["tools_default"],
libs: [
"EddParser.py",
"hostConfig.py",
@@ -91,13 +77,13 @@
genrule_defaults {
name: "domaingeneratorpolicyrule",
tools: [
- "domainGeneratorPolicy.py",
+ "domainGeneratorPolicy",
"domainGeneratorConnector",
],
cmd: "mkdir -p $(genDir)/Structure/Policy && " +
"cp $(locations :audio_policy_pfw_structure_files) $(genDir)/Structure/Policy && " +
"cp $(location :audio_policy_pfw_toplevel) $(genDir)/top_level && " +
- "$(location domainGeneratorPolicy.py) " +
+ "$(location domainGeneratorPolicy) " +
"--validate " +
"--domain-generator-tool $(location domainGeneratorConnector) " +
"--toplevel-config $(genDir)/top_level " +
@@ -121,19 +107,18 @@
// Tools for policy parameter-framework product strategies structure file generation
//
python_binary_host {
- name: "buildStrategiesStructureFile.py",
+ name: "buildStrategiesStructureFile",
main: "buildStrategiesStructureFile.py",
srcs: [
"buildStrategiesStructureFile.py",
],
- defaults: ["tools_default"],
}
genrule_defaults {
name: "buildstrategiesstructurerule",
- tools: ["buildStrategiesStructureFile.py"],
+ tools: ["buildStrategiesStructureFile"],
cmd: "cp $(locations :audio_policy_engine_configuration_files) $(genDir) && ls -l $(genDir) &&"+
- "$(location buildStrategiesStructureFile.py) " +
+ "$(location buildStrategiesStructureFile) " +
"--audiopolicyengineconfigurationfile $(genDir)/audio_policy_engine_configuration.xml "+
"--productstrategiesstructurefile $(location :product_strategies_structure_template) " +
"--outputfile $(out)",
@@ -149,18 +134,17 @@
// Tools for policy parameter-framework common type structure file generation
//
python_binary_host {
- name: "buildCommonTypesStructureFile.py",
+ name: "buildCommonTypesStructureFile",
main: "buildCommonTypesStructureFile.py",
srcs: [
"buildCommonTypesStructureFile.py",
],
- defaults: ["tools_default"],
}
genrule_defaults {
name: "buildcommontypesstructurerule",
- tools: ["buildCommonTypesStructureFile.py"],
- cmd: "$(location buildCommonTypesStructureFile.py) " +
+ tools: ["buildCommonTypesStructureFile"],
+ cmd: "$(location buildCommonTypesStructureFile) " +
"--androidaudiobaseheader $(location :libaudio_system_audio_base) " +
"--commontypesstructure $(location :common_types_structure_template) " +
"--outputfile $(out)",
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 52b9826..649c63f 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -779,7 +779,7 @@
return device;
}
- device = policyMixes.getDeviceAndMixForInputSource(attr.source,
+ device = policyMixes.getDeviceAndMixForInputSource(attr,
availableInputDevices,
uid,
mix);
diff --git a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
index 48f7410..28268c9 100644
--- a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
+++ b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
@@ -544,10 +544,11 @@
status_t AudioPolicyManagerFuzzerDynamicPolicy::addPolicyMix(
int mixType, int mixFlag, audio_devices_t deviceType, std::string mixAddress,
const audio_config_t &audioConfig, const std::vector<PolicyMixTuple> &rules) {
- Vector<AudioMixMatchCriterion> myMixMatchCriteria;
+ std::vector<AudioMixMatchCriterion> myMixMatchCriteria;
+ myMixMatchCriteria.reserve(rules.size());
for (const auto &rule : rules) {
- myMixMatchCriteria.add(
+ myMixMatchCriteria.push_back(
AudioMixMatchCriterion(std::get<0>(rule), std::get<1>(rule), std::get<2>(rule)));
}
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
index 4b4817e..6e34eb0 100644
--- a/services/audiopolicy/managerdefault/Android.bp
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -10,6 +10,10 @@
cc_library_shared {
name: "libaudiopolicymanagerdefault",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+
srcs: [
"AudioPolicyManager.cpp",
"EngineLibrary.cpp",
@@ -36,7 +40,6 @@
"libaudiopolicyenginedefault",
"framework-permission-aidl-cpp",
"libaudioclient_aidl_conversion",
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
],
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 8d00a3d..24c003e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -68,16 +68,6 @@
// media / notification / system volume.
constexpr float IN_CALL_EARPIECE_HEADROOM_DB = 3.f;
-// Compressed formats for MSD module, ordered from most preferred to least preferred.
-static const std::vector<audio_format_t> msdCompressedFormatsOrder = {{
- AUDIO_FORMAT_IEC60958, AUDIO_FORMAT_MAT_2_1, AUDIO_FORMAT_MAT_2_0, AUDIO_FORMAT_E_AC3,
- AUDIO_FORMAT_AC3, AUDIO_FORMAT_PCM_16_BIT }};
-// Channel masks for MSD module, 3D > 2D > 1D ordering (most preferred to least preferred).
-static const std::vector<audio_channel_mask_t> msdSurroundChannelMasksOrder = {{
- AUDIO_CHANNEL_OUT_3POINT1POINT2, AUDIO_CHANNEL_OUT_3POINT0POINT2,
- AUDIO_CHANNEL_OUT_2POINT1POINT2, AUDIO_CHANNEL_OUT_2POINT0POINT2,
- AUDIO_CHANNEL_OUT_5POINT1, AUDIO_CHANNEL_OUT_STEREO }};
-
template <typename T>
bool operator== (const SortedVector<T> &left, const SortedVector<T> &right)
{
@@ -114,7 +104,7 @@
const char* device_address,
const char* device_name,
audio_format_t encodedFormat) {
- media::AudioPort aidlPort;
+ media::AudioPortFw aidlPort;
if (status_t status = deviceToAudioPort(device, device_address, device_name, &aidlPort);
status == OK) {
return setDeviceConnectionState(state, aidlPort.hal, encodedFormat);
@@ -140,8 +130,6 @@
status_t AudioPolicyManager::setDeviceConnectionStateInt(
audio_policy_dev_state_t state, const android::media::audio::common::AudioPort& port,
audio_format_t encodedFormat) {
- // TODO: b/211601178 Forward 'port' to Audio HAL via mHwModules. For now, only device_type,
- // device_address and device_name are forwarded.
if (port.ext.getTag() != AudioPortExt::device) {
return BAD_VALUE;
}
@@ -160,7 +148,13 @@
sp<DeviceDescriptor> device = mHwModules.getDeviceDescriptor(
device_type, device_address.c_str(), device_name, encodedFormat,
state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
- return device ? setDeviceConnectionStateInt(device, state) : INVALID_OPERATION;
+ if (device == nullptr) {
+ return INVALID_OPERATION;
+ }
+ if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+ device->setExtraAudioDescriptors(port.extraAudioDescriptors);
+ }
+ return setDeviceConnectionStateInt(device, state);
}
status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t deviceType,
@@ -168,7 +162,7 @@
const char* device_address,
const char* device_name,
audio_format_t encodedFormat) {
- media::AudioPort aidlPort;
+ media::AudioPortFw aidlPort;
if (status_t status = deviceToAudioPort(deviceType, device_address, device_name, &aidlPort);
status == OK) {
return setDeviceConnectionStateInt(state, aidlPort.hal, encodedFormat);
@@ -450,7 +444,7 @@
status_t AudioPolicyManager::deviceToAudioPort(audio_devices_t device, const char* device_address,
const char* device_name,
- media::AudioPort* aidlPort) {
+ media::AudioPortFw* aidlPort) {
DeviceDescriptorBase devDescr(device, device_address);
devDescr.setName(device_name);
return devDescr.writeToParcelable(aidlPort);
@@ -602,7 +596,10 @@
audioDeviceSet = getAudioDeviceOutAllA2dpSet();
break;
case AUDIO_DEVICE_OUT_BLE_HEADSET:
- audioDeviceSet = getAudioDeviceOutAllBleSet();
+ audioDeviceSet = getAudioDeviceOutLeAudioUnicastSet();
+ break;
+ case AUDIO_DEVICE_OUT_BLE_BROADCAST:
+ audioDeviceSet = getAudioDeviceOutLeAudioBroadcastSet();
break;
default:
ALOGE("%s() device type 0x%08x not supported", __func__, device);
@@ -1034,7 +1031,7 @@
// when searching for direct outputs, if several profiles are compatible, give priority
// to one with offload capability
- if (profile != 0 &&
+ if (profile != 0 &&
((curProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) {
continue;
}
@@ -1534,6 +1531,10 @@
if ((*flags & (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ)) != 0) {
return AUDIO_IO_HANDLE_NONE;
}
+ // A request for Tuner cannot fallback to a mixed output
+ if ((directConfig.offload_info.content_id || directConfig.offload_info.sync_id)) {
+ return AUDIO_IO_HANDLE_NONE;
+ }
// ignoring channel mask due to downmix capability in mixer
@@ -1641,10 +1642,28 @@
const AudioProfileVector &sourceProfiles, const AudioProfileVector &sinkProfiles,
audio_port_config *sourceConfig, audio_port_config *sinkConfig) const
{
+ // Compressed formats for MSD module, ordered from most preferred to least preferred.
+ static const std::vector<audio_format_t> formatsOrder = {{
+ AUDIO_FORMAT_IEC60958, AUDIO_FORMAT_MAT_2_1, AUDIO_FORMAT_MAT_2_0, AUDIO_FORMAT_E_AC3,
+ AUDIO_FORMAT_AC3, AUDIO_FORMAT_PCM_16_BIT }};
+ static const std::vector<audio_channel_mask_t> channelMasksOrder = [](){
+ // Channel position masks for MSD module, 3D > 2D > 1D ordering (most preferred to least
+ // preferred).
+ std::vector<audio_channel_mask_t> masks = {{
+ AUDIO_CHANNEL_OUT_3POINT1POINT2, AUDIO_CHANNEL_OUT_3POINT0POINT2,
+ AUDIO_CHANNEL_OUT_2POINT1POINT2, AUDIO_CHANNEL_OUT_2POINT0POINT2,
+ AUDIO_CHANNEL_OUT_5POINT1, AUDIO_CHANNEL_OUT_STEREO }};
+ // insert index masks (higher counts most preferred) as preferred over position masks
+ for (int i = 1; i <= AUDIO_CHANNEL_COUNT_MAX; i++) {
+ masks.insert(
+ masks.begin(), audio_channel_mask_for_index_assignment_from_count(i));
+ }
+ return masks;
+ }();
+
struct audio_config_base bestSinkConfig;
- status_t result = findBestMatchingOutputConfig(sourceProfiles, sinkProfiles,
- msdCompressedFormatsOrder, msdSurroundChannelMasksOrder,
- true /*preferHigherSamplingRates*/, bestSinkConfig);
+ status_t result = findBestMatchingOutputConfig(sourceProfiles, sinkProfiles, formatsOrder,
+ channelMasksOrder, true /*preferHigherSamplingRates*/, bestSinkConfig);
if (result != NO_ERROR) {
ALOGD("%s() no matching config found for sink, hwAvSync: %d",
__func__, hwAvSync);
@@ -1666,7 +1685,10 @@
}
sourceConfig->sample_rate = bestSinkConfig.sample_rate;
// Specify exact channel mask to prevent guessing by bit count in PatchPanel.
- sourceConfig->channel_mask = audio_channel_mask_out_to_in(bestSinkConfig.channel_mask);
+ sourceConfig->channel_mask =
+ audio_channel_mask_get_representation(bestSinkConfig.channel_mask)
+ == AUDIO_CHANNEL_REPRESENTATION_INDEX ?
+ bestSinkConfig.channel_mask : audio_channel_mask_out_to_in(bestSinkConfig.channel_mask);
sourceConfig->format = bestSinkConfig.format;
// Copy input stream directly without any processing (e.g. resampling).
sourceConfig->flags.input = static_cast<audio_input_flags_t>(
@@ -3168,7 +3190,7 @@
// stream by the engine.
DeviceTypeSet deviceTypes = {device};
if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
- DeviceTypeSet deviceTypes = mEngine->getOutputDevicesForAttributes(
+ deviceTypes = mEngine->getOutputDevicesForAttributes(
attr, nullptr, true /*fromCache*/).types();
}
return getVolumeIndex(getVolumeCurves(attr), index, deviceTypes);
@@ -3178,7 +3200,7 @@
int &index,
const DeviceTypeSet& deviceTypes) const
{
- if (isSingleDeviceType(deviceTypes, audio_is_output_device)) {
+ if (!isSingleDeviceType(deviceTypes, audio_is_output_device)) {
return BAD_VALUE;
}
index = curves.getVolumeIndex(deviceTypes);
@@ -5628,6 +5650,17 @@
return status;
}
+ // If microphones address is empty, set it according to device type
+ for (size_t i = 0; i < mInputDevicesAll.size(); i++) {
+ if (mInputDevicesAll[i]->address().empty()) {
+ if (mInputDevicesAll[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ mInputDevicesAll[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+ } else if (mInputDevicesAll[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
+ mInputDevicesAll[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
+ }
+ }
+ }
+
mEngine->updateDeviceSelectionCache();
mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
@@ -5642,17 +5675,6 @@
mDefaultOutputDevice->toString().c_str());
status = NO_INIT;
}
- // If microphones address is empty, set it according to device type
- for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
- if (mAvailableInputDevices[i]->address().empty()) {
- if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
- mAvailableInputDevices[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
- } else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
- mAvailableInputDevices[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
- }
- }
- }
-
ALOGW_IF(mPrimaryOutput == nullptr, "The policy configuration does not declare a primary output");
// Silence ALOGV statements
@@ -7345,7 +7367,8 @@
// if sco and call follow same curves, bypass forceUseForComm
if ((callVolSrc != btScoVolSrc) &&
((isVoiceVolSrc && isScoRequested) ||
- (isBtScoVolSrc && !(isScoRequested || isHAUsed)))) {
+ (isBtScoVolSrc && !(isScoRequested || isHAUsed))) &&
+ !isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
ALOGV("%s cannot set volume group %d volume when is%srequested for comm", __func__,
volumeSource, isScoRequested ? " " : " not ");
// Do not return an error here as AudioService will always set both voice call
@@ -7866,6 +7889,9 @@
addOutput(output, desc);
+ sp<DeviceDescriptor> speaker = mAvailableOutputDevices.getDevice(
+ AUDIO_DEVICE_OUT_SPEAKER, String8(""), AUDIO_FORMAT_DEFAULT);
+
if (audio_is_remote_submix_device(deviceType) && address != "0") {
sp<AudioPolicyMix> policyMix;
if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix) == NO_ERROR) {
@@ -7876,13 +7902,13 @@
address.string());
}
- } else if (hasPrimaryOutput() && profile->getModule()
- != mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)
+ } else if (hasPrimaryOutput() && speaker != nullptr
+ && mPrimaryOutput->supportsDevice(speaker) && !desc->supportsDevice(speaker)
&& ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) {
// no duplicated output for:
// - direct outputs
// - outputs used by dynamic policy mixes
- // - outputs opened on the primary HW module
+ // - outputs that supports SPEAKER while the primary output does not.
audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE;
//TODO: configure audio effect output stage here
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index a69e088..8466d097 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -1016,7 +1016,7 @@
// Called by setDeviceConnectionState()
status_t deviceToAudioPort(audio_devices_t deviceType, const char* device_address,
- const char* device_name, media::AudioPort* aidPort);
+ const char* device_name, media::AudioPortFw* aidPort);
bool isMsdPatch(const audio_patch_handle_t &handle) const;
private:
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index cdad9a6..4c19d40 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -10,6 +10,10 @@
cc_library_shared {
name: "libaudiopolicyservice",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+
srcs: [
"AudioPolicyClientImpl.cpp",
"AudioPolicyEffects.cpp",
@@ -49,7 +53,6 @@
"libshmemcompat",
"libutils",
"libstagefright_foundation",
- "android.media.audio.common.types-V1-cpp",
"audioclient-types-aidl-cpp",
"audioflinger-aidl-cpp",
"audiopolicy-aidl-cpp",
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 70fdfcb..c7a60c2 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -127,7 +127,8 @@
attributionSource.packageName = "android";
attributionSource.token = sp<BBinder>::make();
sp<AudioEffect> fx = new AudioEffect(attributionSource);
- fx->set(NULL, &effect->mUuid, -1, 0, 0, audioSession, input);
+ fx->set(nullptr /*type */, &effect->mUuid, -1 /* priority */, nullptr /* callback */,
+ audioSession, input);
status_t status = fx->initCheck();
if (status != NO_ERROR && status != ALREADY_EXISTS) {
ALOGW("addInputEffects(): failed to create Fx %s on source %d",
@@ -279,7 +280,8 @@
attributionSource.packageName = "android";
attributionSource.token = sp<BBinder>::make();
sp<AudioEffect> fx = new AudioEffect(attributionSource);
- fx->set(NULL, &effect->mUuid, 0, 0, 0, audioSession, output);
+ fx->set(nullptr /* type */, &effect->mUuid, 0 /* priority */, nullptr /* callback */,
+ audioSession, output);
status_t status = fx->initCheck();
if (status != NO_ERROR && status != ALREADY_EXISTS) {
ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
@@ -984,8 +986,8 @@
attributionSource.packageName = "android";
attributionSource.token = sp<BBinder>::make();
sp<AudioEffect> fx = new AudioEffect(attributionSource);
- fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0, nullptr,
- nullptr, AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
+ fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0 /* priority */, nullptr /* callback */,
+ AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
deviceEffects->getDeviceAddress()});
status_t status = fx->initCheck();
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 49224c5..fdf5787 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1485,7 +1485,7 @@
Status AudioPolicyService::listAudioPorts(media::AudioPortRole roleAidl,
media::AudioPortType typeAidl, Int* count,
- std::vector<media::AudioPort>* portsAidl,
+ std::vector<media::AudioPortFw>* portsAidl,
int32_t* _aidl_return) {
audio_port_role_t role = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioPortRole_audio_port_role_t(roleAidl));
@@ -1510,14 +1510,14 @@
numPortsReq = std::min(numPortsReq, num_ports);
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
convertRange(ports.get(), ports.get() + numPortsReq, std::back_inserter(*portsAidl),
- legacy2aidl_audio_port_v7_AudioPort)));
+ legacy2aidl_audio_port_v7_AudioPortFw)));
count->value = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int32_t>(num_ports));
*_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int32_t>(generation));
return Status::ok();
}
Status AudioPolicyService::getAudioPort(int portId,
- media::AudioPort* _aidl_return) {
+ media::AudioPortFw* _aidl_return) {
audio_port_v7 port{ .id = portId };
Mutex::Autolock _l(mLock);
if (mAudioPolicyManager == NULL) {
@@ -1525,14 +1525,15 @@
}
AutoCallerClear acc;
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(mAudioPolicyManager->getAudioPort(&port)));
- *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_port_v7_AudioPort(port));
+ *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_port_v7_AudioPortFw(port));
return Status::ok();
}
-Status AudioPolicyService::createAudioPatch(const media::AudioPatch& patchAidl, int32_t handleAidl,
+Status AudioPolicyService::createAudioPatch(const media::AudioPatchFw& patchAidl,
+ int32_t handleAidl,
int32_t* _aidl_return) {
audio_patch patch = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioPatch_audio_patch(patchAidl));
+ aidl2legacy_AudioPatchFw_audio_patch(patchAidl));
audio_patch_handle_t handle = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_port_handle_t(handleAidl));
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(AudioValidator::validateAudioPatch(patch)));
@@ -1570,7 +1571,7 @@
}
Status AudioPolicyService::listAudioPatches(Int* count,
- std::vector<media::AudioPatch>* patchesAidl,
+ std::vector<media::AudioPatchFw>* patchesAidl,
int32_t* _aidl_return) {
unsigned int num_patches = VALUE_OR_RETURN_BINDER_STATUS(
convertIntegral<unsigned int>(count->value));
@@ -1591,16 +1592,16 @@
numPatchesReq = std::min(numPatchesReq, num_patches);
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
convertRange(patches.get(), patches.get() + numPatchesReq,
- std::back_inserter(*patchesAidl), legacy2aidl_audio_patch_AudioPatch)));
+ std::back_inserter(*patchesAidl), legacy2aidl_audio_patch_AudioPatchFw)));
count->value = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int32_t>(num_patches));
*_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int32_t>(generation));
return Status::ok();
}
-Status AudioPolicyService::setAudioPortConfig(const media::AudioPortConfig& configAidl)
+Status AudioPolicyService::setAudioPortConfig(const media::AudioPortConfigFw& configAidl)
{
audio_port_config config = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioPortConfig_audio_port_config(configAidl));
+ aidl2legacy_AudioPortConfigFw_audio_port_config(configAidl));
RETURN_IF_BINDER_ERROR(
binderStatusFromStatusT(AudioValidator::validateAudioPortConfig(config)));
@@ -1770,11 +1771,11 @@
return binderStatusFromStatusT(mAudioPolicyManager->removeUserIdDeviceAffinities(userId));
}
-Status AudioPolicyService::startAudioSource(const media::AudioPortConfig& sourceAidl,
+Status AudioPolicyService::startAudioSource(const media::AudioPortConfigFw& sourceAidl,
const media::AudioAttributesInternal& attributesAidl,
int32_t* _aidl_return) {
audio_port_config source = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioPortConfig_audio_port_config(sourceAidl));
+ aidl2legacy_AudioPortConfigFw_audio_port_config(sourceAidl));
audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioAttributesInternal_audio_attributes_t(attributesAidl));
audio_port_handle_t portId;
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 21fa82e..281785e 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1733,6 +1733,7 @@
}
bool AudioPolicyService::UidPolicy::isA11yOnTop() {
+ Mutex::Autolock _l(mLock);
for (const auto &uid : mCachedUids) {
if (!isA11yUid(uid.first)) {
continue;
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index a87d871..860bd18 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -172,16 +172,16 @@
const media::AudioAttributesInternal& attributes,
bool* _aidl_return) override;
binder::Status listAudioPorts(media::AudioPortRole role, media::AudioPortType type,
- Int* count, std::vector<media::AudioPort>* ports,
+ Int* count, std::vector<media::AudioPortFw>* ports,
int32_t* _aidl_return) override;
binder::Status getAudioPort(int portId,
- media::AudioPort* _aidl_return) override;
- binder::Status createAudioPatch(const media::AudioPatch& patch, int32_t handle,
+ media::AudioPortFw* _aidl_return) override;
+ binder::Status createAudioPatch(const media::AudioPatchFw& patch, int32_t handle,
int32_t* _aidl_return) override;
binder::Status releaseAudioPatch(int32_t handle) override;
- binder::Status listAudioPatches(Int* count, std::vector<media::AudioPatch>* patches,
+ binder::Status listAudioPatches(Int* count, std::vector<media::AudioPatchFw>* patches,
int32_t* _aidl_return) override;
- binder::Status setAudioPortConfig(const media::AudioPortConfig& config) override;
+ binder::Status setAudioPortConfig(const media::AudioPortConfigFw& config) override;
binder::Status registerClient(const sp<media::IAudioPolicyServiceClient>& client) override;
binder::Status setAudioPortCallbacksEnabled(bool enabled) override;
binder::Status setAudioVolumeGroupCallbacksEnabled(bool enabled) override;
@@ -197,7 +197,7 @@
int32_t userId,
const std::vector<AudioDevice>& devices) override;
binder::Status removeUserIdDeviceAffinities(int32_t userId) override;
- binder::Status startAudioSource(const media::AudioPortConfig& source,
+ binder::Status startAudioSource(const media::AudioPortConfigFw& source,
const media::AudioAttributesInternal& attributes,
int32_t* _aidl_return) override;
binder::Status stopAudioSource(int32_t portId) override;
@@ -475,8 +475,8 @@
Mutex mLock;
ActivityManager mAm;
bool mObserverRegistered = false;
- std::unordered_map<uid_t, std::pair<bool, int>> mOverrideUids;
- std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids;
+ std::unordered_map<uid_t, std::pair<bool, int>> mOverrideUids GUARDED_BY(mLock);
+ std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids GUARDED_BY(mLock);
std::vector<uid_t> mAssistantUids;
std::vector<uid_t> mActiveAssistantUids;
std::vector<uid_t> mA11yUids;
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index b101ae6..60030bd 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -23,6 +23,7 @@
#include <android/media/SpatializationLevel.h>
#include <android/media/SpatializationMode.h>
#include <android/media/SpatializerHeadTrackingMode.h>
+#include <android/media/audio/common/AudioLatencyMode.h>
#include <audio_utils/SimpleLog.h>
#include <math.h>
#include <media/AudioEffect.h>
@@ -168,8 +169,9 @@
static std::string toString(audio_latency_mode_t mode) {
// We convert to the AIDL type to print (eventually the legacy type will be removed).
- const auto result = legacy2aidl_audio_latency_mode_t_LatencyMode(mode);
- return result.has_value() ? media::toString(*result) : "unknown_latency_mode";
+ const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+ return result.has_value() ?
+ media::audio::common::toString(*result) : "unknown_latency_mode";
}
// If the Spatializer is not created, we send the status for metrics purposes.
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index 2e220bc..6813587 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -10,6 +10,10 @@
cc_test {
name: "audiopolicy_tests",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_static",
+ ],
+
include_dirs: [
"frameworks/av/services/audiopolicy",
],
@@ -30,6 +34,7 @@
],
static_libs: [
+ "audioclient-types-aidl-cpp",
"libaudiopolicycomponents",
"libgmock",
],
@@ -56,6 +61,11 @@
cc_test {
name: "audio_health_tests",
+
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+
require_root: true,
shared_libs: [
@@ -65,7 +75,6 @@
"liblog",
"libmedia_helper",
"libutils",
- "android.media.audio.common.types-V1-cpp",
"libaudioclient_aidl_conversion",
"libstagefright_foundation",
"libshmemcompat",
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index 057fa58..96f58d2 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -103,8 +103,12 @@
++mAudioPortListUpdateCount;
}
- status_t setDeviceConnectedState(
- const struct audio_port_v7 *port __unused, bool connected __unused) override {
+ status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) override {
+ if (connected) {
+ mConnectedDevicePorts.push_back(*port);
+ } else {
+ mDisconnectedDevicePorts.push_back(*port);
+ }
return NO_ERROR;
}
@@ -150,6 +154,30 @@
return NO_ERROR;
}
+ size_t getConnectedDevicePortCount() const {
+ return mConnectedDevicePorts.size();
+ }
+
+ const struct audio_port_v7 *getLastConnectedDevicePort() const {
+ if (mConnectedDevicePorts.empty()) {
+ return nullptr;
+ }
+ auto it = --mConnectedDevicePorts.end();
+ return &(*it);
+ }
+
+ size_t getDisconnectedDevicePortCount() const {
+ return mDisconnectedDevicePorts.size();
+ }
+
+ const struct audio_port_v7 *getLastDisconnectedDevicePort() const {
+ if (mDisconnectedDevicePorts.empty()) {
+ return nullptr;
+ }
+ auto it = --mDisconnectedDevicePorts.end();
+ return &(*it);
+ }
+
private:
audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
@@ -158,6 +186,8 @@
std::set<std::string> mAllowedModuleNames;
size_t mAudioPortListUpdateCount = 0;
size_t mRoutingUpdatedUpdateCount = 0;
+ std::vector<struct audio_port_v7> mConnectedDevicePorts;
+ std::vector<struct audio_port_v7> mDisconnectedDevicePorts;
};
} // namespace android
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index 7441f20..2a7a060 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -37,6 +37,7 @@
using AudioPolicyManager::getDirectProfilesForAttributes;
using AudioPolicyManager::setDeviceConnectionState;
using AudioPolicyManager::deviceToAudioPort;
+ using AudioPolicyManager::handleDeviceConfigChange;
uint32_t getAudioPortGeneration() const { return mAudioPortGeneration; }
};
diff --git a/services/audiopolicy/tests/audio_health_tests.cpp b/services/audiopolicy/tests/audio_health_tests.cpp
index 10f8dc0..798332c 100644
--- a/services/audiopolicy/tests/audio_health_tests.cpp
+++ b/services/audiopolicy/tests/audio_health_tests.cpp
@@ -111,7 +111,7 @@
continue;
}
std::string address = "11:22:33:44:55:66";
- media::AudioPort aidlPort;
+ media::AudioPortFw aidlPort;
ASSERT_EQ(OK, manager.deviceToAudioPort(device->type(), address.c_str(), "" /*name*/,
&aidlPort));
ASSERT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 43b1a2a..1c40cfd 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -42,6 +42,32 @@
using testing::UnorderedElementsAre;
using android::content::AttributionSourceState;
+namespace {
+
+AudioMixMatchCriterion createUidCriterion(uint32_t uid, bool exclude = false) {
+ AudioMixMatchCriterion criterion;
+ criterion.mValue.mUid = uid;
+ criterion.mRule = exclude ? RULE_EXCLUDE_UID : RULE_MATCH_UID;
+ return criterion;
+}
+
+AudioMixMatchCriterion createUsageCriterion(audio_usage_t usage, bool exclude = false) {
+ AudioMixMatchCriterion criterion;
+ criterion.mValue.mUsage = usage;
+ criterion.mRule = exclude ? RULE_EXCLUDE_ATTRIBUTE_USAGE : RULE_MATCH_ATTRIBUTE_USAGE;
+ return criterion;
+}
+
+AudioMixMatchCriterion createCapturePresetCriterion(audio_source_t source, bool exclude = false) {
+ AudioMixMatchCriterion criterion;
+ criterion.mValue.mSource = source;
+ criterion.mRule = exclude ?
+ RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET : RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET;
+ return criterion;
+}
+
+} // namespace
+
TEST(AudioPolicyManagerTestInit, EngineFailure) {
AudioPolicyTestClient client;
AudioPolicyTestManager manager(&client);
@@ -420,7 +446,7 @@
sp<AudioProfile> ac3OutputProfile = new AudioProfile(
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, k48000SamplingRate);
sp<AudioProfile> iec958OutputProfile = new AudioProfile(
- AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_OUT_STEREO, k48000SamplingRate);
+ AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_INDEX_MASK_24, k48000SamplingRate);
mMsdOutputDevice->addAudioProfile(pcmOutputProfile);
mMsdOutputDevice->addAudioProfile(ac3OutputProfile);
mMsdOutputDevice->addAudioProfile(iec958OutputProfile);
@@ -493,7 +519,7 @@
// Add HDMI input device with IEC60958 profile for HDMI in -> MSD patching.
mHdmiInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_HDMI);
sp<AudioProfile> iec958InputProfile = new AudioProfile(
- AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate);
+ AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_INDEX_MASK_24, k48000SamplingRate);
mHdmiInputDevice->addAudioProfile(iec958InputProfile);
config.addDevice(mHdmiInputDevice);
sp<InputProfile> hdmiInputProfile = new InputProfile("hdmi input");
@@ -651,8 +677,8 @@
ASSERT_EQ(AUDIO_PORT_ROLE_SINK, patch->mPatch.sinks[0].role);
ASSERT_EQ(AUDIO_FORMAT_IEC60958, patch->mPatch.sources[0].format);
ASSERT_EQ(AUDIO_FORMAT_IEC60958, patch->mPatch.sinks[0].format);
- ASSERT_EQ(AUDIO_CHANNEL_IN_STEREO, patch->mPatch.sources[0].channel_mask);
- ASSERT_EQ(AUDIO_CHANNEL_OUT_STEREO, patch->mPatch.sinks[0].channel_mask);
+ ASSERT_EQ(AUDIO_CHANNEL_INDEX_MASK_24, patch->mPatch.sources[0].channel_mask);
+ ASSERT_EQ(AUDIO_CHANNEL_INDEX_MASK_24, patch->mPatch.sinks[0].channel_mask);
ASSERT_EQ(k48000SamplingRate, patch->mPatch.sources[0].sample_rate);
ASSERT_EQ(k48000SamplingRate, patch->mPatch.sinks[0].sample_rate);
ASSERT_EQ(1, patchCount.deltaFromSnapshot());
@@ -728,7 +754,7 @@
audio_config_base_t msdDirectConfig2 = AUDIO_CONFIG_BASE_INITIALIZER;
msdDirectConfig2.format = AUDIO_FORMAT_IEC60958;
msdDirectConfig2.sample_rate = 48000;
- msdDirectConfig2.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ msdDirectConfig2.channel_mask = AUDIO_CHANNEL_INDEX_MASK_24;
audio_config_base_t msdNonDirectConfig = AUDIO_CONFIG_BASE_INITIALIZER;
msdNonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT;
@@ -795,7 +821,7 @@
audio_config_t msdDirectConfig2 = AUDIO_CONFIG_INITIALIZER;
msdDirectConfig2.format = AUDIO_FORMAT_IEC60958;
msdDirectConfig2.sample_rate = 48000;
- msdDirectConfig2.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ msdDirectConfig2.channel_mask = AUDIO_CHANNEL_INDEX_MASK_24;
audio_config_t msdNonDirectConfig = AUDIO_CONFIG_INITIALIZER;
msdNonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT;
@@ -919,7 +945,29 @@
EXPECT_TRUE(foundVoipTx);
}
-using PolicyMixTuple = std::tuple<audio_usage_t, audio_source_t, uint32_t>;
+TEST_F(AudioPolicyManagerTestWithConfigurationFile, HandleDeviceConfigChange) {
+ {
+ const auto prevCounter = mClient->getRoutingUpdatedCounter();
+
+ EXPECT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ "", "", AUDIO_FORMAT_LDAC));
+ const auto currCounter = mClient->getRoutingUpdatedCounter();
+ EXPECT_GT(currCounter, prevCounter);
+ }
+ {
+ const auto prevCounter = mClient->getRoutingUpdatedCounter();
+ // Update device configuration
+ EXPECT_EQ(NO_ERROR, mManager->handleDeviceConfigChange(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+ "" /*address*/, "" /*name*/,
+ AUDIO_FORMAT_AAC));
+
+ // As mClient marks isReconfigA2dpSupported to false, device state needs to be toggled for
+ // config changes to take effect
+ const auto currCounter = mClient->getRoutingUpdatedCounter();
+ EXPECT_GT(currCounter, prevCounter);
+ }
+}
class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile {
protected:
@@ -927,7 +975,7 @@
status_t addPolicyMix(int mixType, int mixFlag, audio_devices_t deviceType,
std::string mixAddress, const audio_config_t& audioConfig,
- const std::vector<PolicyMixTuple>& rules);
+ const std::vector<AudioMixMatchCriterion>& matchCriteria);
void clearPolicyMix();
Vector<AudioMix> mAudioMixes;
@@ -941,15 +989,8 @@
status_t AudioPolicyManagerTestDynamicPolicy::addPolicyMix(int mixType, int mixFlag,
audio_devices_t deviceType, std::string mixAddress, const audio_config_t& audioConfig,
- const std::vector<PolicyMixTuple>& rules) {
- Vector<AudioMixMatchCriterion> myMixMatchCriteria;
-
- for(const auto &rule: rules) {
- myMixMatchCriteria.add(AudioMixMatchCriterion(
- std::get<0>(rule), std::get<1>(rule), std::get<2>(rule)));
- }
-
- AudioMix myAudioMix(myMixMatchCriteria, mixType, audioConfig, mixFlag,
+ const std::vector<AudioMixMatchCriterion>& matchCriteria = {}) {
+ AudioMix myAudioMix(matchCriteria, mixType, audioConfig, mixFlag,
String8(mixAddress.c_str()), 0);
myAudioMix.mDeviceType = deviceType;
// Clear mAudioMix before add new one to make sure we don't add already exist mixes.
@@ -983,13 +1024,13 @@
// Only capture of playback is allowed in LOOP_BACK &RENDER mode
ret = addPolicyMix(MIX_TYPE_RECORDERS, MIX_ROUTE_FLAG_LOOP_BACK_AND_RENDER,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig);
ASSERT_EQ(INVALID_OPERATION, ret);
// Fail due to the device is already connected.
clearPolicyMix();
ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig);
ASSERT_EQ(INVALID_OPERATION, ret);
// The first time to register policy mixes with valid parameter should succeed.
@@ -998,8 +1039,7 @@
audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
audioConfig.sample_rate = k48000SamplingRate;
ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
- std::vector<PolicyMixTuple>());
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig);
ASSERT_EQ(NO_ERROR, ret);
// Registering the same policy mixes should fail.
ret = mManager->registerPolicyMixes(mAudioMixes);
@@ -1010,19 +1050,19 @@
// This will need to be updated if earpiece is added in the test configuration file.
clearPolicyMix();
ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
- AUDIO_DEVICE_OUT_EARPIECE, "", audioConfig, std::vector<PolicyMixTuple>());
+ AUDIO_DEVICE_OUT_EARPIECE, "", audioConfig);
ASSERT_EQ(INVALID_OPERATION, ret);
// Registration should fail due to output not found.
clearPolicyMix();
ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig);
ASSERT_EQ(INVALID_OPERATION, ret);
// The first time to register valid policy mixes should succeed.
clearPolicyMix();
ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
- AUDIO_DEVICE_OUT_SPEAKER, "", audioConfig, std::vector<PolicyMixTuple>());
+ AUDIO_DEVICE_OUT_SPEAKER, "", audioConfig);
ASSERT_EQ(NO_ERROR, ret);
// Registering the same policy mixes should fail.
ret = mManager->registerPolicyMixes(mAudioMixes);
@@ -1037,8 +1077,7 @@
audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
audioConfig.sample_rate = k48000SamplingRate;
ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
- std::vector<PolicyMixTuple>());
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig);
ASSERT_EQ(NO_ERROR, ret);
// After successfully registering policy mixes, it should be able to unregister.
@@ -1051,6 +1090,37 @@
ASSERT_EQ(INVALID_OPERATION, ret);
}
+TEST_F(AudioPolicyManagerTestDynamicPolicy, RegisterPolicyWithConsistentMixSucceeds) {
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+
+ std::vector<AudioMixMatchCriterion> mixMatchCriteria = {
+ createUidCriterion(/*uid=*/42),
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/true)};
+ status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
+ mixMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+}
+
+TEST_F(AudioPolicyManagerTestDynamicPolicy, RegisterPolicyWithInconsistentMixFails) {
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+
+ std::vector<AudioMixMatchCriterion> mixMatchCriteria = {
+ createUidCriterion(/*uid=*/42),
+ createUidCriterion(/*uid=*/1235, /*exclude=*/true),
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/true)};
+ status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
+ mixMatchCriteria);
+ ASSERT_EQ(INVALID_OPERATION, ret);
+}
+
class AudioPolicyManagerTestForHdmi
: public AudioPolicyManagerTestWithConfigurationFile,
public testing::WithParamInterface<audio_format_t> {
@@ -1275,7 +1345,7 @@
audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
audioConfig.sample_rate = k48000SamplingRate;
ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig);
ASSERT_EQ(INVALID_OPERATION, ret);
ret = mManager->unregisterPolicyMixes(mAudioMixes);
@@ -1290,9 +1360,9 @@
std::unique_ptr<RecordingActivityTracker> mTracker;
- std::vector<PolicyMixTuple> mUsageRules = {
- {AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT, RULE_MATCH_ATTRIBUTE_USAGE},
- {AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT, RULE_MATCH_ATTRIBUTE_USAGE}
+ std::vector<AudioMixMatchCriterion> mUsageRules = {
+ createUsageCriterion(AUDIO_USAGE_MEDIA),
+ createUsageCriterion(AUDIO_USAGE_ALARM)
};
struct audio_port_v7 mInjectionPort;
@@ -1352,9 +1422,10 @@
getOutputForAttr(&playbackRoutedPortId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
k48000SamplingRate, AUDIO_OUTPUT_FLAG_NONE, nullptr /*output*/, nullptr /*portId*/,
attr);
- if (std::find_if(begin(mUsageRules), end(mUsageRules), [&usage](const auto &usageRule) {
- return (std::get<0>(usageRule) == usage) &&
- (std::get<2>(usageRule) == RULE_MATCH_ATTRIBUTE_USAGE);}) != end(mUsageRules) ||
+ if (std::find_if(begin(mUsageRules), end(mUsageRules),
+ [&usage](const AudioMixMatchCriterion &c) {
+ return c.mRule == RULE_MATCH_ATTRIBUTE_USAGE &&
+ c.mValue.mUsage == usage;}) != end(mUsageRules) ||
(strncmp(attr.tags, "addr=", strlen("addr=")) == 0 &&
strncmp(attr.tags + strlen("addr="), mMixAddress.c_str(),
AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0)) {
@@ -1475,10 +1546,10 @@
std::unique_ptr<RecordingActivityTracker> mTracker;
- std::vector<PolicyMixTuple> mSourceRules = {
- {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_CAMCORDER, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET},
- {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_MIC, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET},
- {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_VOICE_COMMUNICATION, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}
+ std::vector<AudioMixMatchCriterion> mSourceRules = {
+ createCapturePresetCriterion(AUDIO_SOURCE_CAMCORDER),
+ createCapturePresetCriterion(AUDIO_SOURCE_MIC),
+ createCapturePresetCriterion(AUDIO_SOURCE_VOICE_COMMUNICATION)
};
struct audio_port_v7 mExtractionPort;
@@ -1538,9 +1609,10 @@
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
getInputForAttr(attr, mTracker->getRiid(), &captureRoutedPortId, AUDIO_FORMAT_PCM_16_BIT,
AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate, AUDIO_INPUT_FLAG_NONE, &portId);
- if (std::find_if(begin(mSourceRules), end(mSourceRules), [&source](const auto &sourceRule) {
- return (std::get<1>(sourceRule) == source) &&
- (std::get<2>(sourceRule) == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET);})
+ if (std::find_if(begin(mSourceRules), end(mSourceRules),
+ [&source](const AudioMixMatchCriterion &c) {
+ return c.mRule == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET &&
+ c.mValue.mSource == source;})
!= end(mSourceRules)) {
EXPECT_EQ(mExtractionPort.id, captureRoutedPortId);
} else {
@@ -1700,6 +1772,45 @@
address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
}
+android::media::audio::common::ExtraAudioDescriptor make_ExtraAudioDescriptor(
+ android::media::audio::common::AudioStandard audioStandard,
+ android::media::audio::common::AudioEncapsulationType audioEncapsulationType) {
+ android::media::audio::common::ExtraAudioDescriptor result;
+ result.standard = audioStandard;
+ result.audioDescriptor = {0xb4, 0xaf, 0x98, 0x1a};
+ result.encapsulationType = audioEncapsulationType;
+ return result;
+}
+
+TEST_P(AudioPolicyManagerTestDeviceConnection, PassingExtraAudioDescriptors) {
+ const audio_devices_t type = std::get<0>(GetParam());
+ if (!audio_device_is_digital(type)) {
+ // EADs are used only for HDMI devices.
+ GTEST_SKIP() << "Not a digital device type: " << audio_device_to_string(type);
+ }
+ const std::string name = std::get<1>(GetParam());
+ const std::string address = std::get<2>(GetParam());
+ android::media::AudioPortFw audioPort;
+ ASSERT_EQ(NO_ERROR,
+ mManager->deviceToAudioPort(type, address.c_str(), name.c_str(), &audioPort));
+ android::media::audio::common::AudioPort& port = audioPort.hal;
+ port.extraAudioDescriptors.push_back(make_ExtraAudioDescriptor(
+ android::media::audio::common::AudioStandard::EDID,
+ android::media::audio::common::AudioEncapsulationType::IEC61937));
+ const size_t lastConnectedDevicePortCount = mClient->getConnectedDevicePortCount();
+ const size_t lastDisconnectedDevicePortCount = mClient->getDisconnectedDevicePortCount();
+ EXPECT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE, port, AUDIO_FORMAT_DEFAULT));
+ EXPECT_EQ(lastConnectedDevicePortCount + 1, mClient->getConnectedDevicePortCount());
+ EXPECT_EQ(lastDisconnectedDevicePortCount, mClient->getDisconnectedDevicePortCount());
+ const audio_port_v7* devicePort = mClient->getLastConnectedDevicePort();
+ EXPECT_EQ(port.extraAudioDescriptors.size(), devicePort->num_extra_audio_descriptors);
+ EXPECT_EQ(AUDIO_STANDARD_EDID, devicePort->extra_audio_descriptors[0].standard);
+ EXPECT_EQ(AUDIO_ENCAPSULATION_TYPE_IEC61937,
+ devicePort->extra_audio_descriptors[0].encapsulation_type);
+ EXPECT_NE(0, devicePort->extra_audio_descriptors[0].descriptor[0]);
+}
+
INSTANTIATE_TEST_CASE_P(
DeviceConnectionState,
AudioPolicyManagerTestDeviceConnection,
@@ -1738,7 +1849,7 @@
audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
const std::string kTestBusMediaOutput = "bus0_media_out";
ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
- AUDIO_DEVICE_OUT_BUS, kTestBusMediaOutput, audioConfig, std::vector<PolicyMixTuple>());
+ AUDIO_DEVICE_OUT_BUS, kTestBusMediaOutput, audioConfig);
ASSERT_EQ(NO_ERROR, ret);
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
index 5e1822a..d342aea 100644
--- a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -71,6 +71,9 @@
<devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"
role="source" address="hfp_client_in">
</devicePort>
+ <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink"
+ encodedFormats="AUDIO_FORMAT_LDAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_AAC AUDIO_FORMAT_SBC">
+ </devicePort>
</devicePorts>
<routes>
<route type="mix" sink="Speaker"
@@ -85,6 +88,8 @@
sources="mixport_bt_hfp_output,voip_rx"/>
<route type="mix" sink="mixport_bt_hfp_input"
sources="BT SCO Headset Mic"/>
+ <route type="mix" sink="BT A2DP Out"
+ sources="primary output"/>
</routes>
</module>
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index d87b630..a7c9bac 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -4023,7 +4023,7 @@
int toggleType __unused, int sensor __unused, bool enabled) {
{
Mutex::Autolock _l(mSensorPrivacyLock);
- mSensorPrivacyEnabled = mSpm.isToggleSensorPrivacyEnabled(SensorPrivacyManager::TOGGLE_SENSOR_CAMERA);
+ mSensorPrivacyEnabled = enabled;
}
// if sensor privacy is enabled then block all clients from accessing the camera
if (enabled) {
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 123cd75..8b2af90 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -953,6 +953,12 @@
false);
if (availableVideoStabilizationModes.count > 1) {
+ for (size_t i = 0; i < availableVideoStabilizationModes.count; i++) {
+ if (availableVideoStabilizationModes.data.u8[i] ==
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_ON) {
+ videoStabilizationOnSupported = true;
+ }
+ }
params.set(CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED,
CameraParameters::TRUE);
} else {
@@ -2373,9 +2379,11 @@
reqCropRegion, 4);
if (res != OK) return res;
- uint8_t reqVstabMode = videoStabilization ?
+ uint8_t reqVstabMode = videoStabilization ? videoStabilizationOnSupported ?
ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_ON :
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION :
ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
+
res = request->update(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
&reqVstabMode, 1);
if (res != OK) return res;
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index cbe62a7..fd18a5d 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -147,6 +147,7 @@
bool recordingHint;
bool videoStabilization;
+ bool videoStabilizationOnSupported = false;
CameraParameters2 params;
String8 paramsFlattened;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 1f86414..dd23c2e 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -947,8 +947,8 @@
std::vector<int> surfaceIds;
bool isDepthCompositeStream =
camera3::DepthCompositeStream::isDepthCompositeStream(surfaces[0]);
- bool isHeicCompisiteStream = camera3::HeicCompositeStream::isHeicCompositeStream(surfaces[0]);
- if (isDepthCompositeStream || isHeicCompisiteStream) {
+ bool isHeicCompositeStream = camera3::HeicCompositeStream::isHeicCompositeStream(surfaces[0]);
+ if (isDepthCompositeStream || isHeicCompositeStream) {
sp<CompositeStream> compositeStream;
if (isDepthCompositeStream) {
compositeStream = new camera3::DepthCompositeStream(mDevice, getRemoteCallback());
@@ -1863,6 +1863,10 @@
mCompositeStreamMap.clear();
mInputStream = {false, 0, 0, 0, 0};
} else {
+ // In case we failed to register the offline client, ensure that it still initialized
+ // so that all failing requests can return back correctly once the object is released.
+ offlineClient->initialize(nullptr /*cameraProviderManager*/, String8()/*monitorTags*/);
+
switch(ret) {
case BAD_VALUE:
return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 0f31c66..52d0020 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -29,6 +29,11 @@
status_t CameraOfflineSessionClient::initialize(sp<CameraProviderManager>, const String8&) {
ATRACE_CALL();
+ if (mFrameProcessor.get() != nullptr) {
+ // Already initialized
+ return OK;
+ }
+
// Verify ops permissions
auto res = startCameraOps();
if (res != OK) {
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index 237ce5e..2cc8e33 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -931,7 +931,7 @@
tempOutputFile.str().c_str(), errno);
return NO_INIT;
}
- inputFrame.muxer = new MediaMuxer(inputFrame.fileFd, MediaMuxer::OUTPUT_FORMAT_HEIF);
+ inputFrame.muxer = MediaMuxer::create(inputFrame.fileFd, MediaMuxer::OUTPUT_FORMAT_HEIF);
if (inputFrame.muxer == nullptr) {
ALOGE("%s: Failed to create MediaMuxer for file fd %d",
__FUNCTION__, inputFrame.fileFd);
@@ -1601,7 +1601,7 @@
return OK;
}
-void HeicCompositeStream::initCopyRowFunction(int32_t width)
+void HeicCompositeStream::initCopyRowFunction([[maybe_unused]] int32_t width)
{
using namespace libyuv;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 43f92a9..5ab7023 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -586,7 +586,11 @@
std::lock_guard<std::mutex> lock(mInterfaceMutex);
mDeviceState = newState;
status_t res = OK;
- for (auto& provider : mProviders) {
+ // Make a copy of mProviders because we unlock mInterfaceMutex temporarily
+ // within the loop. It's possible that during the time mInterfaceMutex is
+ // unlocked, mProviders has changed.
+ auto providers = mProviders;
+ for (auto& provider : providers) {
ALOGV("%s: Notifying %s for new state 0x%" PRIx64,
__FUNCTION__, provider->mProviderName.c_str(), newState);
// b/199240726 Camera providers can for example try to add/remove
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index 67c4841..49bbd07 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -293,7 +293,7 @@
if (link != STATUS_OK) {
ALOGW("%s: Unable to link to provider '%s' death notifications",
__FUNCTION__, mProviderName.c_str());
- mManager->removeProvider(mProviderName);
+ mManager->removeProvider(mProviderInstance);
return nullptr;
}
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
index 630090b..6be0cca 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -388,7 +388,7 @@
__FUNCTION__,
mProviderName.c_str(),
linked.description().c_str());
- mManager->removeProvider(mProviderName);
+ mManager->removeProvider(mProviderInstance);
return nullptr;
} else if (!linked) {
ALOGW("%s: Unable to link to provider '%s' death notifications",
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index d033395..e631f8b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -258,20 +258,28 @@
Mutex::Autolock l(mLock);
if (mStatus == STATUS_UNINITIALIZED) return res;
- if (mStatus == STATUS_ACTIVE ||
- (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
- res = mRequestThread->clearRepeatingRequests();
- if (res != OK) {
- SET_ERR_L("Can't stop streaming");
- // Continue to close device even in case of error
- } else {
- res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
+ if (mRequestThread != NULL) {
+ if (mStatus == STATUS_ACTIVE || mStatus == STATUS_ERROR) {
+ res = mRequestThread->clear();
if (res != OK) {
- SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
- maxExpectedDuration);
+ SET_ERR_L("Can't stop streaming");
// Continue to close device even in case of error
+ } else {
+ res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
+ if (res != OK) {
+ SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
+ maxExpectedDuration);
+ // Continue to close device even in case of error
+ }
}
}
+ // Signal to request thread that we're not expecting any
+ // more requests. This will be true since once we're in
+ // disconnect and we've cleared off the request queue, the
+ // request thread can't receive any new requests through
+ // binder calls - since disconnect holds
+ // mBinderSerialization lock.
+ mRequestThread->setRequestClearing();
}
if (mStatus == STATUS_ERROR) {
@@ -3060,7 +3068,8 @@
}
-status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(/*out*/int64_t *lastFrameNumber) {
+status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(
+ /*out*/int64_t *lastFrameNumber) {
std::vector<int32_t> streamIds;
for (const auto& request : mRepeatingRequests) {
for (const auto& stream : request->mOutputStreams) {
@@ -3085,8 +3094,6 @@
Mutex::Autolock l(mRequestLock);
ALOGV("RequestThread::%s:", __FUNCTION__);
- mRepeatingRequests.clear();
-
// Send errors for all requests pending in the request queue, including
// pending repeating requests
sp<NotificationListener> listener = mListener.promote();
@@ -3124,10 +3131,7 @@
Mutex::Autolock al(mTriggerMutex);
mTriggerMap.clear();
- if (lastFrameNumber != NULL) {
- *lastFrameNumber = mRepeatingLastFrameNumber;
- }
- mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
+ clearRepeatingRequestsLocked(lastFrameNumber);
mRequestClearing = true;
mRequestSignal.signal();
return OK;
@@ -4252,6 +4256,11 @@
return;
}
+void Camera3Device::RequestThread::setRequestClearing() {
+ Mutex::Autolock l(mRequestLock);
+ mRequestClearing = true;
+}
+
sp<Camera3Device::CaptureRequest>
Camera3Device::RequestThread::waitForNextRequestLocked() {
status_t res;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index cd214f6..746205b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -466,6 +466,28 @@
// Verify buffer caches
std::vector<uint64_t> bufIds(offlineStream.circulatingBufferIds.begin(),
offlineStream.circulatingBufferIds.end());
+ {
+ // Due to timing it is possible that we may not have any remaining pending
+ // capture requests that can update the caches on Hal side. This can result in
+ // buffer cache mismatch between the service and the Hal and must be accounted
+ // for.
+ std::lock_guard<std::mutex> l(mFreedBuffersLock);
+ for (const auto& it : mFreedBuffers) {
+ if (it.first == id) {
+ ALOGV("%s: stream ID %d buffer id %" PRIu64 " cache removal still "
+ "pending", __FUNCTION__, id, it.second);
+ const auto& cachedEntry = std::find(bufIds.begin(), bufIds.end(),
+ it.second);
+ if (cachedEntry != bufIds.end()) {
+ bufIds.erase(cachedEntry);
+ } else {
+ ALOGE("%s: stream ID %d buffer id %" PRIu64 " cache removal still "
+ "pending however buffer is no longer in the offline stream "
+ "info!", __FUNCTION__, id, it.second);
+ }
+ }
+ }
+ }
if (!verifyBufferIds(id, bufIds)) {
ALOGE("%s: stream ID %d buffer cache records mismatch!", __FUNCTION__, id);
return UNKNOWN_ERROR;
@@ -848,6 +870,9 @@
*/
void setPaused(bool paused);
+ // set mRequestClearing - no new requests are expected to be queued to RequestThread
+ void setRequestClearing();
+
/**
* Wait until thread processes the capture request with settings'
* android.request.id == requestId.
@@ -1002,7 +1027,7 @@
wp<NotificationListener> mListener;
- const String8& mId; // The camera ID
+ const String8 mId; // The camera ID
int mStatusId; // The RequestThread's component ID for
// status tracking
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
index 7cfa255..1e7bd57 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
@@ -81,7 +81,6 @@
Camera3OfflineSession::~Camera3OfflineSession() {
ATRACE_CALL();
ALOGV("%s: Tearing down offline session for camera id %s", __FUNCTION__, mId.string());
- disconnectImpl();
}
const String8& Camera3OfflineSession::getId() const {
@@ -96,7 +95,6 @@
status_t Camera3OfflineSession::disconnect() {
ATRACE_CALL();
- disconnectSession();
return disconnectImpl();
}
@@ -132,6 +130,8 @@
streams.push_back(mInputStream);
}
+ closeSessionLocked();
+
FlushInflightReqStates states {
mId, mOfflineReqsLock, mOfflineReqs, mUseHalBufManager,
listener, *this, mBufferRecords, *this, mSessionStatsBuilder};
@@ -140,6 +140,7 @@
{
std::lock_guard<std::mutex> lock(mLock);
+ releaseSessionLocked();
mOutputStreams.clear();
mInputStream.clear();
mStatus = STATUS_CLOSED;
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.h b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
index 5ee6ca5..e780043 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
@@ -274,7 +274,12 @@
void setErrorStateLockedV(const char *fmt, va_list args);
status_t disconnectImpl();
- virtual void disconnectSession() = 0;
+
+ // Clients need to ensure that 'mInterfaceLock' is acquired before calling this method
+ virtual void closeSessionLocked() = 0;
+
+ // Clients need to ensure that 'mLock' is acquired before calling this method
+ virtual void releaseSessionLocked() = 0;
}; // class Camera3OfflineSession
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
index 4b1fb1d..3c3db97 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
@@ -48,7 +48,7 @@
AidlCamera3OfflineSession::~AidlCamera3OfflineSession() {
ATRACE_CALL();
ALOGV("%s: Tearing down aidl offline session for camera id %s", __FUNCTION__, mId.string());
- AidlCamera3OfflineSession::disconnectSession();
+ Camera3OfflineSession::disconnectImpl();
}
status_t AidlCamera3OfflineSession::initialize(wp<NotificationListener> listener) {
@@ -247,12 +247,17 @@
return ::ndk::ScopedAStatus::ok();
}
-void AidlCamera3OfflineSession::disconnectSession() {
- std::lock_guard<std::mutex> lock(mLock);
- if (mSession != nullptr) {
- mSession->close();
- }
- mSession.reset();
+void AidlCamera3OfflineSession::closeSessionLocked() {
+ if (mSession != nullptr) {
+ auto err = mSession->close();
+ if (!err.isOk()) {
+ ALOGE("%s: Close transaction error: %s", __FUNCTION__, err.getDescription().c_str());
+ }
+ }
+}
+
+void AidlCamera3OfflineSession::releaseSessionLocked() {
+ mSession.reset();
}
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
index d107af6..b31ffb7 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
@@ -131,7 +131,9 @@
std::shared_ptr<AidlCameraDeviceCallbacks> mCallbacks;
- virtual void disconnectSession() override;
+ virtual void closeSessionLocked() override;
+
+ virtual void releaseSessionLocked() override;
}; // class AidlCamera3OfflineSession
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
index 2bd4660..72343bc 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
@@ -82,9 +82,6 @@
const hardware::hidl_vec<
hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
- // Handle one notify message
- void notify(const hardware::camera::device::V3_2::NotifyMsg& msg);
-
status_t switchToOffline(const std::vector<int32_t>& streamsToKeep,
/*out*/ sp<CameraOfflineSessionBase>* session) override;
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
index 0a6a6f7..28b2b47 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
@@ -39,7 +39,7 @@
HidlCamera3OfflineSession::~HidlCamera3OfflineSession() {
ATRACE_CALL();
ALOGV("%s: Tearing down hidl offline session for camera id %s", __FUNCTION__, mId.string());
- HidlCamera3OfflineSession::disconnectSession();
+ Camera3OfflineSession::disconnectImpl();
}
status_t HidlCamera3OfflineSession::initialize(wp<NotificationListener> listener) {
@@ -229,13 +229,17 @@
return hardware::Void();
}
-void HidlCamera3OfflineSession::disconnectSession() {
- // TODO: Make sure this locking is correct.
- std::lock_guard<std::mutex> lock(mLock);
- if (mSession != nullptr) {
- mSession->close();
- }
- mSession.clear();
+void HidlCamera3OfflineSession::closeSessionLocked() {
+ if (mSession != nullptr) {
+ auto err = mSession->close();
+ if (!err.isOk()) {
+ ALOGE("%s: Close transaction error: %s", __FUNCTION__, err.description().c_str());
+ }
+ }
+}
+
+void HidlCamera3OfflineSession::releaseSessionLocked() {
+ mSession.clear();
}
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
index 597cc5d..d22a447 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
@@ -101,7 +101,9 @@
// FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
std::unique_ptr<ResultMetadataQueue> mResultMetadataQueue;
- virtual void disconnectSession() override;
+ virtual void closeSessionLocked() override;
+
+ virtual void releaseSessionLocked() override;
}; // class Camera3OfflineSession
}; // namespace android
diff --git a/services/mediacodec/Android.bp b/services/mediacodec/Android.bp
index 4488efb..a2f17c2 100644
--- a/services/mediacodec/Android.bp
+++ b/services/mediacodec/Android.bp
@@ -54,6 +54,9 @@
arm64: {
src: "seccomp_policy/mediaswcodec-arm64.policy",
},
+ riscv64: {
+ src: "seccomp_policy/mediaswcodec-riscv64.policy",
+ },
x86: {
src: "seccomp_policy/mediaswcodec-x86.policy",
},
@@ -144,6 +147,9 @@
arm64: {
src: "seccomp_policy/mediacodec-arm64.policy",
},
+ riscv64: {
+ enabled: false,
+ },
x86: {
src: "seccomp_policy/mediacodec-x86.policy",
},
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-riscv64.policy b/services/mediacodec/seccomp_policy/mediaswcodec-riscv64.policy
new file mode 100644
index 0000000..a55c3eb
--- /dev/null
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-riscv64.policy
@@ -0,0 +1,60 @@
+# Copyright (C) 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.
+
+read: 1
+mprotect: 1
+prctl: 1
+openat: 1
+getuid: 1
+getrlimit: 1
+writev: 1
+ioctl: 1
+close: 1
+mmap: 1
+munmap: 1
+fstat: 1
+madvise: 1
+newfstatat: 1
+futex: 1
+faccessat: 1
+lseek: 1
+clone: 1
+sigaltstack: 1
+rt_sigprocmask: 1
+setpriority: 1
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+readlinkat: 1
+fstatfs: 1
+pread64: 1
+mremap: 1
+dup: 1
+set_tid_address: 1
+write: 1
+nanosleep: 1
+sched_setscheduler: 1
+uname: 1
+memfd_create: 1
+ftruncate: 1
+getdents64: 1
+ppoll: 1
+
+# Required by AddressSanitizer
+gettid: 1
+sched_yield: 1
+getpid: 1
+
+@include /apex/com.android.media.swcodec/etc/seccomp_policy/code_coverage.riscv64.policy
diff --git a/services/mediaextractor/Android.bp b/services/mediaextractor/Android.bp
index 85ce110..acafe56 100644
--- a/services/mediaextractor/Android.bp
+++ b/services/mediaextractor/Android.bp
@@ -74,6 +74,9 @@
arm64: {
src: "seccomp_policy/mediaextractor-arm64.policy",
},
+ riscv64: {
+ src: "seccomp_policy/mediaextractor-riscv64.policy",
+ },
x86: {
src: "seccomp_policy/mediaextractor-x86.policy",
},
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-riscv64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-riscv64.policy
new file mode 100644
index 0000000..df143dd
--- /dev/null
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-riscv64.policy
@@ -0,0 +1,48 @@
+# Organized by frequency of systemcall - in descending order for
+# best performance.
+ioctl: 1
+futex: 1
+prctl: 1
+write: 1
+getpriority: 1
+close: 1
+dup: 1
+mmap: 1
+munmap: 1
+openat: 1
+mprotect: 1
+madvise: 1
+getuid: 1
+fstat: 1
+fstatfs: 1
+read: 1
+setpriority: 1
+sigaltstack: 1
+clone: 1
+sched_setscheduler: 1
+lseek: 1
+newfstatat: 1
+faccessat: 1
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+rt_sigprocmask: 1
+getrlimit: 1
+nanosleep: 1
+getrandom: 1
+timer_create: 1
+timer_settime: 1
+timer_delete: 1
+
+# for dynamically loading extractors
+getdents64: 1
+readlinkat: 1
+pread64: 1
+mremap: 1
+
+# Required by Sanitizers
+sched_yield: 1
+
+@include /apex/com.android.media/etc/seccomp_policy/crash_dump.riscv64.policy
+@include /apex/com.android.media/etc/seccomp_policy/code_coverage.riscv64.policy
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
index 11534bb..c90488f 100644
--- a/services/mediametrics/Android.bp
+++ b/services/mediametrics/Android.bp
@@ -138,6 +138,7 @@
"AudioTypes.cpp",
"cleaner.cpp",
"iface_statsd.cpp",
+ "MediaDrmStatsdHelper.cpp",
"MediaMetricsService.cpp",
"statsd_audiopolicy.cpp",
"statsd_audiorecord.cpp",
@@ -169,7 +170,7 @@
"libmemunreachable",
"libprotobuf-cpp-lite",
"libstagefright_foundation",
- "libstatslog",
+ "libstats_media_metrics",
"libstatspull",
"libstatssocket",
"libutils",
@@ -177,6 +178,7 @@
],
export_shared_lib_headers: [
+ "libstats_media_metrics",
"libstatspull",
"libstatssocket",
],
@@ -200,3 +202,33 @@
"libaudioutils_headers",
],
}
+
+cc_library {
+ name: "libstats_media_metrics",
+ generated_sources: ["stats_media_metrics.cpp"],
+ generated_headers: ["stats_media_metrics.h"],
+ export_generated_headers: ["stats_media_metrics.h"],
+ shared_libs: [
+ "libcutils",
+ "libstatspull",
+ "libstatssocket",
+ ],
+}
+
+genrule {
+ name: "stats_media_metrics.h",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --header $(genDir)/stats_media_metrics.h --module media_metrics --namespace android,stats,media_metrics",
+ out: [
+ "stats_media_metrics.h",
+ ],
+}
+
+genrule {
+ name: "stats_media_metrics.cpp",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --cpp $(genDir)/stats_media_metrics.cpp --module media_metrics --namespace android,stats,media_metrics --importHeader stats_media_metrics.h",
+ out: [
+ "stats_media_metrics.cpp",
+ ],
+}
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index b03e418..119bb6c 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -24,7 +24,7 @@
#include <aaudio/AAudio.h> // error codes
#include <audio_utils/clock.h> // clock conversions
#include <cutils/properties.h>
-#include <statslog.h> // statsd
+#include <stats_media_metrics.h> // statsd
#include <system/audio.h>
#include "AudioTypes.h" // string to int conversions
@@ -292,7 +292,7 @@
int result = 0;
#ifdef STATSD_ENABLE
- result = android::util::stats_write(args...);
+ result = stats::media_metrics::stats_write(args...);
#endif
return result;
}
@@ -308,7 +308,7 @@
std::stringstream ss;
#ifdef STATSD_ENABLE
- result = android::util::stats_write(args...);
+ result = stats::media_metrics::stats_write(args...);
ss << "result:" << result;
#endif
ss << " { ";
@@ -607,7 +607,7 @@
const int atom_status = types::lookup<types::STATUS, int32_t>(statusString);
// currently we only send create status events.
- const int32_t event = android::util::
+ const int32_t event = stats::media_metrics::
MEDIAMETRICS_AUDIO_RECORD_STATUS_REPORTED__EVENT__AUDIO_RECORD_EVENT_CREATE;
// The following fields should all be present in a create event.
@@ -647,7 +647,7 @@
__func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_SAMPLERATE);
const auto [ result, str ] = sendToStatsd(AudioRecordStatusFields,
- CONDITION(android::util::MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED)
, atom_status
, message.c_str()
, subCode
@@ -661,7 +661,7 @@
, sampleRate
);
ALOGV("%s: statsd %s", __func__, str.c_str());
- mStatsdLog->log(android::util::MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED, str);
+ mStatsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED, str);
return true;
}
return false;
@@ -679,7 +679,7 @@
const int atom_status = types::lookup<types::STATUS, int32_t>(statusString);
// currently we only send create status events.
- const int32_t event = android::util::
+ const int32_t event = stats::media_metrics::
MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__EVENT__AUDIO_TRACK_EVENT_CREATE;
// The following fields should all be present in a create event.
@@ -734,7 +734,7 @@
__func__,
AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_PLAYBACK_PITCH);
const auto [ result, str ] = sendToStatsd(AudioTrackStatusFields,
- CONDITION(android::util::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED)
, atom_status
, message.c_str()
, subCode
@@ -751,7 +751,7 @@
, (float)pitch
);
ALOGV("%s: statsd %s", __func__, str.c_str());
- mStatsdLog->log(android::util::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED, str);
+ mStatsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED, str);
return true;
}
return false;
@@ -860,7 +860,7 @@
if (clientCalled // only log if client app called AudioRecord.
&& mAudioAnalytics.mDeliverStatistics) {
const auto [ result, str ] = sendToStatsd(AudioRecordDeviceUsageFields,
- CONDITION(android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED)
, ENUM_EXTRACT(inputDeviceStatsd)
, inputDeviceNames.c_str()
, deviceTimeNs
@@ -878,7 +878,7 @@
);
ALOGV("%s: statsd %s", __func__, str.c_str());
mAudioAnalytics.mStatsdLog->log(
- android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED, str);
+ stats::media_metrics::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED, str);
}
} break;
case THREAD: {
@@ -930,7 +930,7 @@
<< ")";
if (mAudioAnalytics.mDeliverStatistics) {
const auto [ result, str ] = sendToStatsd(AudioThreadDeviceUsageFields,
- CONDITION(android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED)
, ENUM_EXTRACT(deviceStatsd)
, deviceNames.c_str()
, deviceTimeNs
@@ -944,7 +944,7 @@
);
ALOGV("%s: statsd %s", __func__, str.c_str());
mAudioAnalytics.mStatsdLog->log(
- android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED, str);
+ stats::media_metrics::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED, str);
}
} break;
case TRACK: {
@@ -1050,7 +1050,7 @@
if (clientCalled // only log if client app called AudioTracks
&& mAudioAnalytics.mDeliverStatistics) {
const auto [ result, str ] = sendToStatsd(AudioTrackDeviceUsageFields,
- CONDITION(android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED)
, ENUM_EXTRACT(outputDeviceStatsd)
, outputDeviceNames.c_str()
, deviceTimeNs
@@ -1074,7 +1074,7 @@
);
ALOGV("%s: statsd %s", __func__, str.c_str());
mAudioAnalytics.mStatsdLog->log(
- android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED, str);
+ stats::media_metrics::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED, str);
}
} break;
}
@@ -1136,7 +1136,7 @@
const long_enum_type_t inputDeviceBits{};
const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
- CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
, ENUM_EXTRACT(inputDeviceBits)
, ENUM_EXTRACT(outputDeviceBits)
, mA2dpDeviceName.c_str()
@@ -1146,7 +1146,7 @@
);
ALOGV("%s: statsd %s", __func__, str.c_str());
mAudioAnalytics.mStatsdLog->log(
- android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
+ stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
}
}
}
@@ -1190,7 +1190,7 @@
<< " deviceName:" << mA2dpDeviceName;
if (mAudioAnalytics.mDeliverStatistics) {
const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
- CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
, ENUM_EXTRACT(inputDeviceBits)
, ENUM_EXTRACT(outputDeviceBits)
, mA2dpDeviceName.c_str()
@@ -1200,7 +1200,7 @@
);
ALOGV("%s: statsd %s", __func__, str.c_str());
mAudioAnalytics.mStatsdLog->log(
- android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
+ stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
}
return;
}
@@ -1217,7 +1217,7 @@
<< " deviceName:" << mA2dpDeviceName;
if (mAudioAnalytics.mDeliverStatistics) {
const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
- CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
, ENUM_EXTRACT(inputDeviceBits)
, ENUM_EXTRACT(outputDeviceBits)
, mA2dpDeviceName.c_str()
@@ -1227,7 +1227,7 @@
);
ALOGV("%s: statsd %s", __func__, str.c_str());
mAudioAnalytics.mStatsdLog->log(
- android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
+ stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
}
}
@@ -1355,10 +1355,10 @@
<< "(" << sharingModeRequestedStr << ")";
if (mAudioAnalytics.mDeliverStatistics) {
- android::util::BytesField bf_serialized(
+ const stats::media_metrics::BytesField bf_serialized(
serializedDeviceTypes.c_str(), serializedDeviceTypes.size());
const auto result = sendToStatsd(
- CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
, path
, direction
, framesPerBurst
@@ -1381,7 +1381,7 @@
std::stringstream ss;
ss << "result:" << result;
const auto fieldsStr = printFields(AAudioStreamFields,
- CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
, path
, direction
, framesPerBurst
@@ -1404,7 +1404,7 @@
ss << " " << fieldsStr;
std::string str = ss.str();
ALOGV("%s: statsd %s", __func__, str.c_str());
- mAudioAnalytics.mStatsdLog->log(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED, str);
+ mAudioAnalytics.mStatsdLog->log(stats::media_metrics::MEDIAMETRICS_AAUDIOSTREAM_REPORTED, str);
}
}
@@ -1544,12 +1544,12 @@
// Classifies the setting event for statsd (use generated statsd enums.proto constants).
static int32_t classifySettingEvent(bool isSetAlready, bool withinBoot) {
if (isSetAlready) {
- return util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_NORMAL;
+ return stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_NORMAL;
}
if (withinBoot) {
- return util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_BOOT;
+ return stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_BOOT;
}
- return util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_FIRST;
+ return stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_FIRST;
}
void AudioAnalytics::Spatializer::onEvent(
@@ -1598,7 +1598,7 @@
types::channelMaskVectorFromString(channelMasks);
const auto [ result, str ] = sendToStatsd(SpatializerCapabilitiesFields,
- CONDITION(android::util::MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED)
, headTrackingModesVector
, levelsVector
, modesVector
@@ -1606,7 +1606,7 @@
);
mAudioAnalytics.mStatsdLog->log(
- android::util::MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED, str);
+ stats::media_metrics::MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED, str);
std::lock_guard lg(mLock);
if (mFirstCreateTimeNs == 0) {
@@ -1655,13 +1655,13 @@
deviceState.enabled = enabled;
const bool enabledStatsd = enabled == "true";
const auto [ result, str ] = sendToStatsd(SpatializerDeviceEnabledFields,
- CONDITION(android::util::MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED)
, deviceTypeStatsd
, settingEventStatsd
, enabledStatsd
);
mAudioAnalytics.mStatsdLog->log(
- android::util::MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED, str);
+ stats::media_metrics::MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED, str);
}
}
if (!hasHeadTracker.empty()) {
@@ -1671,13 +1671,13 @@
deviceState.hasHeadTracker = hasHeadTracker;
const bool supportedStatsd = hasHeadTracker == "true";
const auto [ result, str ] = sendToStatsd(HeadTrackerDeviceSupportedFields,
- CONDITION(android::util::MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED)
, deviceTypeStatsd
, settingEventStatsd
, supportedStatsd
);
mAudioAnalytics.mStatsdLog->log(
- android::util::MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED, str);
+ stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED, str);
}
}
if (!headTrackerEnabled.empty()) {
@@ -1687,13 +1687,13 @@
deviceState.headTrackerEnabled = headTrackerEnabled;
const bool enabledStatsd = headTrackerEnabled == "true";
const auto [ result, str ] = sendToStatsd(HeadTrackerDeviceEnabledFields,
- CONDITION(android::util::MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED)
+ CONDITION(stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED)
, deviceTypeStatsd
, settingEventStatsd
, enabledStatsd
);
mAudioAnalytics.mStatsdLog->log(
- android::util::MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED, str);
+ stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED, str);
}
}
mSimpleLog.log("%s deviceKey: %s item: %s",
diff --git a/services/mediametrics/AudioPowerUsage.cpp b/services/mediametrics/AudioPowerUsage.cpp
index 5787e9e..630a436 100644
--- a/services/mediametrics/AudioPowerUsage.cpp
+++ b/services/mediametrics/AudioPowerUsage.cpp
@@ -26,7 +26,7 @@
#include <string>
#include <audio_utils/clock.h>
#include <cutils/properties.h>
-#include <statslog.h>
+#include <stats_media_metrics.h>
#include <sys/timerfd.h>
#include <system/audio.h>
@@ -164,7 +164,7 @@
const int32_t duration_secs = (int32_t)(duration_ns / NANOS_PER_SECOND);
const int32_t min_volume_duration_secs = (int32_t)(min_volume_duration_ns / NANOS_PER_SECOND);
const int32_t max_volume_duration_secs = (int32_t)(max_volume_duration_ns / NANOS_PER_SECOND);
- const int result = android::util::stats_write(android::util::AUDIO_POWER_USAGE_DATA_REPORTED,
+ const int result = stats::media_metrics::stats_write(stats::media_metrics::AUDIO_POWER_USAGE_DATA_REPORTED,
audio_device,
duration_secs,
(float)volume,
@@ -177,7 +177,7 @@
std::stringstream log;
log << "result:" << result << " {"
<< " mediametrics_audio_power_usage_data_reported:"
- << android::util::AUDIO_POWER_USAGE_DATA_REPORTED
+ << stats::media_metrics::AUDIO_POWER_USAGE_DATA_REPORTED
<< " audio_device:" << audio_device
<< " duration_secs:" << duration_secs
<< " average_volume:" << (float)volume
@@ -187,7 +187,7 @@
<< " max_volume_duration_secs:" << max_volume_duration_secs
<< " max_volume:" << (float)max_volume
<< " }";
- mStatsdLog->log(android::util::AUDIO_POWER_USAGE_DATA_REPORTED, log.str());
+ mStatsdLog->log(stats::media_metrics::AUDIO_POWER_USAGE_DATA_REPORTED, log.str());
}
void AudioPowerUsage::updateMinMaxVolumeAndDuration(
diff --git a/services/mediametrics/AudioTypes.cpp b/services/mediametrics/AudioTypes.cpp
index d2b4aab..353ae12 100644
--- a/services/mediametrics/AudioTypes.cpp
+++ b/services/mediametrics/AudioTypes.cpp
@@ -18,7 +18,7 @@
#include "MediaMetricsConstants.h"
#include "StringUtils.h"
#include <media/TypeConverter.h> // requires libmedia_helper to get the Audio code.
-#include <statslog.h> // statsd
+#include <stats_media_metrics.h> // statsd
namespace android::mediametrics::types {
@@ -184,41 +184,41 @@
const std::unordered_map<std::string, int32_t>& getAudioDeviceInfoTypeMap() {
// DO NOT MODIFY VALUES (OK to add new ones).
static std::unordered_map<std::string, int32_t> map{
- {"unknown", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_UNKNOWN},
- {"earpiece", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUILTIN_EARPIECE},
- {"speaker", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUILTIN_SPEAKER},
- {"headset", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_WIRED_HEADSET},
- {"headphone", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_WIRED_HEADPHONES}, // sic
- {"bt_sco", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_SCO},
- {"bt_sco_hs", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_SCO},
- {"bt_sco_carkit", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_SCO},
- {"bt_a2dp", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_A2DP},
- {"bt_a2dp_hp", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_A2DP},
- {"bt_a2dp_spk", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_A2DP},
- {"aux_digital", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI},
- {"hdmi", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI},
- {"analog_dock", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_DOCK},
- {"digital_dock", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_DOCK},
- {"usb_accessory", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_USB_ACCESSORY},
- {"usb_device", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_USB_DEVICE},
- {"usb_headset", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_USB_HEADSET},
- {"remote_submix", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_REMOTE_SUBMIX},
- {"telephony_tx", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_TELEPHONY},
- {"line", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_LINE_ANALOG},
- {"hdmi_arc", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI_ARC},
- {"hdmi_earc", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI_EARC},
- {"spdif", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_LINE_DIGITAL},
- {"fm_transmitter", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_FM},
- {"aux_line", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_AUX_LINE},
- {"speaker_safe", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUILTIN_SPEAKER_SAFE},
- {"ip", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_IP},
- {"bus", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUS},
- {"proxy", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_UNKNOWN /* AUDIO_DEVICE_INFO_TYPE_PROXY */},
- {"hearing_aid_out", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HEARING_AID},
- {"echo_canceller", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_ECHO_REFERENCE}, // sic
- {"ble_headset", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLE_HEADSET},
- {"ble_speaker", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLE_SPEAKER},
- {"ble_broadcast", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLE_BROADCAST},
+ {"unknown", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_UNKNOWN},
+ {"earpiece", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUILTIN_EARPIECE},
+ {"speaker", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUILTIN_SPEAKER},
+ {"headset", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_WIRED_HEADSET},
+ {"headphone", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_WIRED_HEADPHONES}, // sic
+ {"bt_sco", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_SCO},
+ {"bt_sco_hs", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_SCO},
+ {"bt_sco_carkit", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_SCO},
+ {"bt_a2dp", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_A2DP},
+ {"bt_a2dp_hp", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_A2DP},
+ {"bt_a2dp_spk", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_A2DP},
+ {"aux_digital", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI},
+ {"hdmi", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI},
+ {"analog_dock", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_DOCK},
+ {"digital_dock", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_DOCK},
+ {"usb_accessory", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_USB_ACCESSORY},
+ {"usb_device", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_USB_DEVICE},
+ {"usb_headset", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_USB_HEADSET},
+ {"remote_submix", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_REMOTE_SUBMIX},
+ {"telephony_tx", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_TELEPHONY},
+ {"line", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_LINE_ANALOG},
+ {"hdmi_arc", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI_ARC},
+ {"hdmi_earc", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI_EARC},
+ {"spdif", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_LINE_DIGITAL},
+ {"fm_transmitter", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_FM},
+ {"aux_line", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_AUX_LINE},
+ {"speaker_safe", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUILTIN_SPEAKER_SAFE},
+ {"ip", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_IP},
+ {"bus", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUS},
+ {"proxy", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_UNKNOWN /* AUDIO_DEVICE_INFO_TYPE_PROXY */},
+ {"hearing_aid_out", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HEARING_AID},
+ {"echo_canceller", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_ECHO_REFERENCE}, // sic
+ {"ble_headset", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLE_HEADSET},
+ {"ble_speaker", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLE_SPEAKER},
+ {"ble_broadcast", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLE_BROADCAST},
};
return map;
}
@@ -324,23 +324,23 @@
// DO NOT MODIFY VALUES(OK to add new ones).
static std::unordered_map<std::string, int32_t> map {
{"",
- util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__NO_ERROR},
+ stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__NO_ERROR},
{AMEDIAMETRICS_PROP_STATUS_VALUE_OK,
- util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__NO_ERROR},
+ stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__NO_ERROR},
{AMEDIAMETRICS_PROP_STATUS_VALUE_ARGUMENT,
- util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_ARGUMENT},
+ stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_ARGUMENT},
{AMEDIAMETRICS_PROP_STATUS_VALUE_IO,
- util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_IO},
+ stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_IO},
{AMEDIAMETRICS_PROP_STATUS_VALUE_MEMORY,
- util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_MEMORY},
+ stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_MEMORY},
{AMEDIAMETRICS_PROP_STATUS_VALUE_SECURITY,
- util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_SECURITY},
+ stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_SECURITY},
{AMEDIAMETRICS_PROP_STATUS_VALUE_STATE,
- util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_STATE},
+ stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_STATE},
{AMEDIAMETRICS_PROP_STATUS_VALUE_TIMEOUT,
- util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_TIMEOUT},
+ stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_TIMEOUT},
{AMEDIAMETRICS_PROP_STATUS_VALUE_UNKNOWN,
- util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_UNKNOWN},
+ stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_UNKNOWN},
};
return map;
}
@@ -664,7 +664,7 @@
auto& map = getStatusMap();
auto it = map.find(status);
if (it == map.end()) {
- return util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_UNKNOWN;
+ return stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_UNKNOWN;
}
return it->second;
}
diff --git a/services/mediametrics/MediaDrmStatsdHelper.cpp b/services/mediametrics/MediaDrmStatsdHelper.cpp
new file mode 100644
index 0000000..d762672
--- /dev/null
+++ b/services/mediametrics/MediaDrmStatsdHelper.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2023 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 "MediaDrmStatsdHelper.h"
+#include <tuple>
+#include <map>
+#include <unordered_map>
+
+namespace {
+
+struct UUID {
+ uint64_t msb, lsb; // NOLINT(misc-non-private-member-variables-in-classes)
+ bool operator < (const UUID& that) const {
+ return std::tie(msb, lsb) < std::tie(that.msb, that.lsb);
+ }
+};
+
+// KEEP IN SYNC WITH frameworks/proto_logging/stats/enums/media/drm/enums.proto
+std::map<UUID, int32_t> const kUuidSchemeEnumMap {
+ {{.msb = 0x6DD8B3C345F44A68, .lsb = 0xBF3A64168D01A4A6}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__ABV_MODRM }, // ABV_MODRM
+ {{.msb = 0xF239E769EFA34850, .lsb = 0x9C16A903C6932EFB}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__ADOBE_PRIMETIME }, // ADOBE_PRIMETIME
+ {{.msb = 0x616C746963617374, .lsb = 0x2D50726F74656374}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__ALTICAST }, // ALTICAST
+ {{.msb = 0x94CE86FB07FF4F43, .lsb = 0xADB893D2FA968CA2}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__APPLE_FAIRPLAY }, // APPLE_FAIRPLAY
+ {{.msb = 0x279FE473512C48FE, .lsb = 0xADE8D176FEE6B40F}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__ARRIS_TITANIUM }, // ARRIS_TITANIUM
+ {{.msb = 0x3D5E6D359B9A41E8, .lsb = 0xB843DD3C6E72C42C}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__CHINADRM }, // CHINADRM
+ {{.msb = 0x3EA8778F77424BF9, .lsb = 0xB18BE834B2ACBD47}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__CLEAR_KEY_AES_128 }, // CLEAR_KEY_AES_128
+ {{.msb = 0xBE58615B19C44684, .lsb = 0x88B3C8C57E99E957}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__CLEAR_KEY_SAMPLE_AES }, // CLEAR_KEY_SAMPLE_AES
+ {{.msb = 0xE2719D58A985B3C9, .lsb = 0x781AB030AF78D30E}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__CLEAR_KEY_DASH_IF }, // CLEAR_KEY_DASH_IF
+ {{.msb = 0x644FE7B5260F4FAD, .lsb = 0x949A0762FFB054B4}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__CMLA_OMA }, // CMLA_OMA
+ {{.msb = 0x37C332587B994C7E, .lsb = 0xB15D19AF74482154}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__COMMSCOPE_TITANIUM }, // COMMSCOPE_TITANIUM
+ {{.msb = 0x45D481CB8FE049C0, .lsb = 0xADA9AB2D2455B2F2}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__CORECRYPT }, // CORECRYPT
+ {{.msb = 0xDCF4E3E362F15818, .lsb = 0x7BA60A6FE33FF3DD}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__DIGICAP_SMARTXESS }, // DIGICAP_SMARTXESS
+ {{.msb = 0x35BF197B530E42D7, .lsb = 0x8B651B4BF415070F}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__DIVX }, // DIVX
+ {{.msb = 0x80A6BE7E14484C37, .lsb = 0x9E70D5AEBE04C8D2}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__IRDETO }, // IRDETO
+ {{.msb = 0x5E629AF538DA4063, .lsb = 0x897797FFBD9902D4}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__MARLIN }, // MARLIN
+ {{.msb = 0x9A04F07998404286, .lsb = 0xAB92E65BE0885F95}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__MICROSOFT_PLAYREADY }, // MICROSOFT_PLAYREADY
+ {{.msb = 0x6A99532D869F5922, .lsb = 0x9A91113AB7B1E2F3}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__MOBITV }, // MOBITV
+ {{.msb = 0xADB41C242DBF4A6D, .lsb = 0x958B4457C0D27B95}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__NAGRA_MEDIAACCESS }, // NAGRA_MEDIAACCESS
+ {{.msb = 0x1F83E1E86EE94F0D, .lsb = 0xBA2F5EC4E3ED1A66}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__SECUREMEDIA }, // SECUREMEDIA
+ {{.msb = 0x992C46E6C4374899, .lsb = 0xB6A050FA91AD0E39}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__SECUREMEDIA_STEELKNOT }, // SECUREMEDIA_STEELKNOT
+ {{.msb = 0xA68129D3575B4F1A, .lsb = 0x9CBA3223846CF7C3}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__SYNAMEDIA_VIDEOGUARD }, // SYNAMEDIA_VIDEOGUARD
+ {{.msb = 0xAA11967FCC014A4A, .lsb = 0x8E99C5D3DDDFEA2D}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__UNITEND_UDRM }, // UNITEND_UDRM
+ {{.msb = 0x9A27DD82FDE24725, .lsb = 0x8CBC4234AA06EC09}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__VERIMATRIX_VCAS }, // VERIMATRIX_VCAS
+ {{.msb = 0xB4413586C58CFFB0, .lsb = 0x94A5D4896C1AF6C3}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__VIACCESS_ORCA }, // VIACCESS_ORCA
+ {{.msb = 0x793B79569F944946, .lsb = 0xA94223E7EF7E44B4}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__VISIONCRYPT }, // VISIONCRYPT
+ {{.msb = 0x1077EFECC0B24D02, .lsb = 0xACE33C1E52E2FB4B}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__W3C_COMMON }, // W3C_COMMON
+ {{.msb = 0xEDEF8BA979D64ACE, .lsb = 0xA3C827DCD51D21ED}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__WIDEVINE }, // WIDEVINE
+};
+
+// KEEP IN SYNC WITH frameworks/av/drm/libmediadrm/include/mediadrm/IDrm.h
+// KEEP IN SYNC WITH frameworks/proto_logging/stats/enums/media/drm/enums.proto
+std::unordered_map<std::string, int32_t> const kDrmApiEnumMap {
+ {"initCheck" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_INIT_CHECK },
+ {"isCryptoSchemeSupported" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_IS_CRYPTO_SCHEME_SUPPORTED },
+ {"createPlugin" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_CREATE_PLUGIN },
+ {"destroyPlugin" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_DESTROY_PLUGIN },
+ {"openSession" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_OPEN_SESSION },
+ {"closeSession" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_CLOSE_SESSION },
+ {"getKeyRequest" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_KEY_REQUEST },
+ {"provideKeyResponse" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_PROVIDE_KEY_RESPONSE },
+ {"removeKeys" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_REMOVE_KEYS },
+ {"restoreKeys" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_RESTORE_KEYS },
+ {"queryKeyStatus" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_QUERY_KEY_STATUS },
+ {"getProvisionRequest" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_PROVISION_REQUEST },
+ {"provideProvisionResponse" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_PROVIDE_PROVISION_RESPONSE },
+ {"getSecureStops" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_SECURE_STOPS },
+ {"getSecureStopIds" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_SECURE_STOP_IDS },
+ {"getSecureStop" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_SECURE_STOP },
+ {"releaseSecureStops" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_RELEASE_SECURE_STOPS },
+ {"removeSecureStop" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_REMOVE_SECURE_STOP },
+ {"removeAllSecureStops" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_REMOVE_ALL_SECURE_STOPS },
+ {"getHdcpLevels" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_HDCP_LEVELS },
+ {"getNumberOfSessions" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_NUMBER_OF_SESSIONS },
+ {"getSecurityLevel" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_SECURITY_LEVEL },
+ {"getOfflineLicenseKeySetIds" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_OFFLINE_LICENSE_KEY_SET_IDS },
+ {"removeOfflineLicense" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_REMOVE_OFFLINE_LICENSE },
+ {"getOfflineLicenseState" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_OFFLINE_LICENSE_STATE },
+ {"getPropertyString" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_PROPERTY_STRING },
+ {"getPropertyByteArray" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_PROPERTY_BYTE_ARRAY },
+ {"setPropertyString" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SET_PROPERTY_STRING },
+ {"setPropertyByteArray" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SET_PROPERTY_BYTE_ARRAY },
+ {"getMetrics" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_METRICS },
+ {"setCipherAlgorithm" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SET_CIPHER_ALGORITHM },
+ {"setMacAlgorithm" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SET_MAC_ALGORITHM },
+ {"encrypt" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GENERIC_ENCRYPT },
+ {"decrypt" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GENERIC_DECRYPT },
+ {"sign" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GENERIC_SIGN },
+ {"verify" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GENERIC_VERIFY },
+ {"signRSA" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SIGN_RSA },
+ {"setListener" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SET_LISTENER },
+ {"requiresSecureDecoder" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_REQUIRES_SECURE_DECODER },
+ {"requiresSecureDecoderLevel" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_REQUIRES_SECURE_DECODER_LEVEL },
+ {"setPlaybackId" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SET_PLAYBACK_ID },
+ {"getLogMessages" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_LOG_MESSAGES },
+ {"getSupportedSchemes" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_SUPPORTED_SCHEMES },
+};
+
+} // anonymous namespace
+
+namespace android {
+
+int32_t MediaDrmStatsdHelper::findDrmScheme(const int64_t msb, const int64_t lsb) {
+ auto it = kUuidSchemeEnumMap.find({.msb = static_cast<uint64_t>(msb), .lsb = static_cast<uint64_t>(lsb)});
+ if (it == kUuidSchemeEnumMap.end()) return stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__DRM_SCHEME_OTHER;
+ return it->second;
+}
+
+int32_t MediaDrmStatsdHelper::findDrmApi(const std::string& api) {
+ auto it = kDrmApiEnumMap.find(api);
+ if (it == kDrmApiEnumMap.end()) return stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_UNKNOWN;
+ return it->second;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index 8a7e8a9..adb2217 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -33,7 +33,7 @@
#include <mediautils/MemoryLeakTrackUtil.h>
#include <memunreachable/memunreachable.h>
#include <private/android_filesystem_config.h> // UID
-#include <statslog.h>
+#include <stats_media_metrics.h>
#include <set>
@@ -72,6 +72,7 @@
bool MediaMetricsService::useUidForPackage(
const std::string& package, const std::string& installer)
{
+ // NOLINTBEGIN(bugprone-branch-clone)
if (strchr(package.c_str(), '.') == nullptr) {
return false; // not of form 'com.whatever...'; assume internal and ok
} else if (strncmp(package.c_str(), "android.", 8) == 0) {
@@ -85,6 +86,7 @@
} else {
return true; // we're not sure where it came from, use uid only.
}
+ // NOLINTEND(bugprone-branch-clone)
}
/* static */
@@ -509,6 +511,8 @@
const std::string &key = item->getKey();
if (startsWith(key, "audio.")) return true;
if (startsWith(key, "drm.vendor.")) return true;
+ if (startsWith(key, "mediadrm.")) return true;
+
// the list of allowedKey uses statsd_handlers
// in iface_statsd.cpp as reference
// drmmanager is from a trusted uid, therefore not needed here
@@ -544,7 +548,7 @@
if (mStatsdRegistered.test_and_set()) {
return;
}
- auto tag = android::util::MEDIA_DRM_ACTIVITY_INFO;
+ auto tag = stats::media_metrics::MEDIA_DRM_ACTIVITY_INFO;
auto cb = MediaMetricsService::pullAtomCallback;
AStatsManager_setPullAtomCallback(tag, /* metadata */ nullptr, cb, this);
}
@@ -562,7 +566,7 @@
std::string MediaMetricsService::atomTagToKey(int32_t atomTag)
{
switch (atomTag) {
- case android::util::MEDIA_DRM_ACTIVITY_INFO:
+ case stats::media_metrics::MEDIA_DRM_ACTIVITY_INFO:
return "mediadrm";
}
return {};
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
index 84d494e..8b33f10 100644
--- a/services/mediametrics/fuzzer/Android.bp
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -51,7 +51,7 @@
"libprotobuf-cpp-lite",
"libstagefright",
"libstagefright_foundation",
- "libstatslog",
+ "libstats_media_metrics",
"libstatspull",
"libstatssocket",
"libutils",
diff --git a/services/mediametrics/iface_statsd.cpp b/services/mediametrics/iface_statsd.cpp
index 776f878..7f4e6e8 100644
--- a/services/mediametrics/iface_statsd.cpp
+++ b/services/mediametrics/iface_statsd.cpp
@@ -37,8 +37,6 @@
#include "MediaMetricsService.h"
#include "iface_statsd.h"
-#include <statslog.h>
-
namespace android {
// set of routines that crack a mediametrics::Item
@@ -85,6 +83,9 @@
{ "drmmanager", statsd_drmmanager },
{ "extractor", statsd_extractor },
{ "mediadrm", statsd_mediadrm },
+ { "mediadrm.created", statsd_mediadrm_created },
+ { "mediadrm.errored", statsd_mediadrm_errored },
+ { "mediadrm.session_opened", statsd_mediadrm_session_opened },
{ "mediaparser", statsd_mediaparser },
{ "nuplayer", statsd_nuplayer },
{ "nuplayer2", statsd_nuplayer },
diff --git a/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h b/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h
index b7215e6..6e5a5cf 100644
--- a/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h
+++ b/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h
@@ -50,7 +50,7 @@
*/
std::pair<std::string, int32_t> dump(int32_t lines = INT32_MAX) const;
- // align with message AudioUsageDataReported in frameworks/base/cmds/statsd/src/atoms.proto
+ // align with message AudioPowerUsageDataReported in frameworks/proto_logging/stats/atoms.proto
enum AudioType {
UNKNOWN_TYPE = 0,
VOICE_CALL_TYPE = 1, // voice call
diff --git a/services/mediametrics/include/mediametricsservice/MediaDrmStatsdHelper.h b/services/mediametrics/include/mediametricsservice/MediaDrmStatsdHelper.h
new file mode 100644
index 0000000..2e5e7ff
--- /dev/null
+++ b/services/mediametrics/include/mediametricsservice/MediaDrmStatsdHelper.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_DRM_STATSD_HELPER_H
+#define MEDIA_DRM_STATSD_HELPER_H
+
+#include <cstdint>
+#include <stats_media_metrics.h>
+#include <string>
+namespace android {
+
+class MediaDrmStatsdHelper {
+public:
+ static int32_t findDrmScheme(const int64_t msb, const int64_t lsb);
+ static int32_t findDrmApi(const std::string& api);
+};
+
+} // namespace android
+#endif // MEDIA_DRM_STATSD_HELPER_H
\ No newline at end of file
diff --git a/services/mediametrics/include/mediametricsservice/iface_statsd.h b/services/mediametrics/include/mediametricsservice/iface_statsd.h
index c2a8b3c..5bc293b 100644
--- a/services/mediametrics/include/mediametricsservice/iface_statsd.h
+++ b/services/mediametrics/include/mediametricsservice/iface_statsd.h
@@ -30,13 +30,15 @@
extern statsd_pusher statsd_audiothread;
extern statsd_pusher statsd_audiotrack;
extern statsd_pusher statsd_codec;
+extern statsd_pusher statsd_drmmanager;
extern statsd_pusher statsd_extractor;
+extern statsd_pusher statsd_mediadrm;
+extern statsd_pusher statsd_mediadrm_created;
+extern statsd_pusher statsd_mediadrm_errored;
+extern statsd_pusher statsd_mediadrm_session_opened;
extern statsd_pusher statsd_mediaparser;
-
extern statsd_pusher statsd_nuplayer;
extern statsd_pusher statsd_recorder;
-extern statsd_pusher statsd_mediadrm;
-extern statsd_pusher statsd_drmmanager;
using statsd_puller = bool (const std::shared_ptr<const mediametrics::Item>& item,
AStatsEventList *, const std::shared_ptr<mediametrics::StatsdLog>& statsdLog);
diff --git a/services/mediametrics/statsd_audiopolicy.cpp b/services/mediametrics/statsd_audiopolicy.cpp
index 3d9376e..9a9bc1d 100644
--- a/services/mediametrics/statsd_audiopolicy.cpp
+++ b/services/mediametrics/statsd_audiopolicy.cpp
@@ -29,7 +29,7 @@
#include <sys/types.h>
#include <unistd.h>
-#include <statslog.h>
+#include <stats_media_metrics.h>
#include "MediaMetricsService.h"
#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
@@ -107,15 +107,16 @@
return false;
}
- android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
- int result = android::util::stats_write(android::util::MEDIAMETRICS_AUDIOPOLICY_REPORTED,
+ const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+ const int result = stats::media_metrics::stats_write(
+ stats::media_metrics::MEDIAMETRICS_AUDIOPOLICY_REPORTED,
timestamp_nanos, package_name.c_str(), package_version_code,
media_apex_version,
bf_serialized);
std::stringstream log;
log << "result:" << result << " {"
<< " mediametrics_audiopolicy_reported:"
- << android::util::MEDIAMETRICS_AUDIOPOLICY_REPORTED
+ << stats::media_metrics::MEDIAMETRICS_AUDIOPOLICY_REPORTED
<< " timestamp_nanos:" << timestamp_nanos
<< " package_name:" << package_name
<< " package_version_code:" << package_version_code
@@ -131,7 +132,7 @@
<< " active_session:" << active_session
<< " active_device:" << active_device
<< " }";
- statsdLog->log(android::util::MEDIAMETRICS_AUDIOPOLICY_REPORTED, log.str());
+ statsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIOPOLICY_REPORTED, log.str());
return true;
}
diff --git a/services/mediametrics/statsd_audiorecord.cpp b/services/mediametrics/statsd_audiorecord.cpp
index a7b045e..63c61ec 100644
--- a/services/mediametrics/statsd_audiorecord.cpp
+++ b/services/mediametrics/statsd_audiorecord.cpp
@@ -29,7 +29,7 @@
#include <sys/types.h>
#include <unistd.h>
-#include <statslog.h>
+#include <stats_media_metrics.h>
#include "MediaMetricsService.h"
#include "ValidateId.h"
@@ -99,16 +99,14 @@
}
int32_t error_code = -1;
- if (item->getInt32("android.media.audiorecord.errcode", &error_code)) {
- metrics_proto.set_error_code(error_code);
- } else if (item->getInt32("android.media.audiorecord.lastError.code", &error_code)) {
+ if (item->getInt32("android.media.audiorecord.errcode", &error_code) ||
+ item->getInt32("android.media.audiorecord.lastError.code", &error_code)) {
metrics_proto.set_error_code(error_code);
}
std::string error_function;
- if (item->getString("android.media.audiorecord.errfunc", &error_function)) {
- metrics_proto.set_error_function(error_function);
- } else if (item->getString("android.media.audiorecord.lastError.at", &error_function)) {
+ if (item->getString("android.media.audiorecord.errfunc", &error_function) ||
+ item->getString("android.media.audiorecord.lastError.at", &error_function)) {
metrics_proto.set_error_function(error_function);
}
@@ -149,8 +147,9 @@
(void)item->getString("android.media.audiorecord.logSessionId", &logSessionId);
const auto log_session_id = mediametrics::ValidateId::get()->validateId(logSessionId);
- android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
- int result = android::util::stats_write(android::util::MEDIAMETRICS_AUDIORECORD_REPORTED,
+ const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+ const int result = stats::media_metrics::stats_write(
+ stats::media_metrics::MEDIAMETRICS_AUDIORECORD_REPORTED,
timestamp_nanos, package_name.c_str(), package_version_code,
media_apex_version,
bf_serialized,
@@ -158,7 +157,7 @@
std::stringstream log;
log << "result:" << result << " {"
<< " mediametrics_audiorecord_reported:"
- << android::util::MEDIAMETRICS_AUDIORECORD_REPORTED
+ << stats::media_metrics::MEDIAMETRICS_AUDIORECORD_REPORTED
<< " timestamp_nanos:" << timestamp_nanos
<< " package_name:" << package_name
<< " package_version_code:" << package_version_code
@@ -183,7 +182,7 @@
<< " log_session_id:" << log_session_id
<< " }";
- statsdLog->log(android::util::MEDIAMETRICS_AUDIORECORD_REPORTED, log.str());
+ statsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIORECORD_REPORTED, log.str());
return true;
}
diff --git a/services/mediametrics/statsd_audiothread.cpp b/services/mediametrics/statsd_audiothread.cpp
index e9b6dd6..3056605 100644
--- a/services/mediametrics/statsd_audiothread.cpp
+++ b/services/mediametrics/statsd_audiothread.cpp
@@ -29,7 +29,7 @@
#include <sys/types.h>
#include <unistd.h>
-#include <statslog.h>
+#include <stats_media_metrics.h>
#include "MediaMetricsService.h"
#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
@@ -188,15 +188,16 @@
return false;
}
- android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
- int result = android::util::stats_write(android::util::MEDIAMETRICS_AUDIOTHREAD_REPORTED,
+ const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+ const int result = stats::media_metrics::stats_write(
+ stats::media_metrics::MEDIAMETRICS_AUDIOTHREAD_REPORTED,
timestamp_nanos, package_name.c_str(), package_version_code,
media_apex_version,
bf_serialized);
std::stringstream log;
log << "result:" << result << " {"
<< " mediametrics_audiothread_reported:"
- << android::util::MEDIAMETRICS_AUDIOTHREAD_REPORTED
+ << stats::media_metrics::MEDIAMETRICS_AUDIOTHREAD_REPORTED
<< " timestamp_nanos:" << timestamp_nanos
<< " package_name:" << package_name
<< " package_version_code:" << package_version_code
@@ -231,7 +232,7 @@
<< " latency_mean_millis:" << latency_mean_millis
<< " latency_stddev_millis:" << latency_stddev_millis
<< " }";
- statsdLog->log(android::util::MEDIAMETRICS_AUDIOTHREAD_REPORTED, log.str());
+ statsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIOTHREAD_REPORTED, log.str());
return true;
}
diff --git a/services/mediametrics/statsd_audiotrack.cpp b/services/mediametrics/statsd_audiotrack.cpp
index 67514e9..1fc7fb4 100644
--- a/services/mediametrics/statsd_audiotrack.cpp
+++ b/services/mediametrics/statsd_audiotrack.cpp
@@ -29,7 +29,7 @@
#include <sys/types.h>
#include <unistd.h>
-#include <statslog.h>
+#include <stats_media_metrics.h>
#include "MediaMetricsService.h"
#include "ValidateId.h"
@@ -134,8 +134,9 @@
(void)item->getString("android.media.audiotrack.logSessionId", &logSessionId);
const auto log_session_id = mediametrics::ValidateId::get()->validateId(logSessionId);
- android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
- int result = android::util::stats_write(android::util::MEDIAMETRICS_AUDIOTRACK_REPORTED,
+ const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+ const int result = stats::media_metrics::stats_write(
+ stats::media_metrics::MEDIAMETRICS_AUDIOTRACK_REPORTED,
timestamp_nanos, package_name.c_str(), package_version_code,
media_apex_version,
bf_serialized,
@@ -143,7 +144,7 @@
std::stringstream log;
log << "result:" << result << " {"
<< " mediametrics_audiotrack_reported:"
- << android::util::MEDIAMETRICS_AUDIOTRACK_REPORTED
+ << stats::media_metrics::MEDIAMETRICS_AUDIOTRACK_REPORTED
<< " timestamp_nanos:" << timestamp_nanos
<< " package_name:" << package_name
<< " package_version_code:" << package_version_code
@@ -164,7 +165,7 @@
<< " log_session_id:" << log_session_id
<< " }";
- statsdLog->log(android::util::MEDIAMETRICS_AUDIOTRACK_REPORTED, log.str());
+ statsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIOTRACK_REPORTED, log.str());
return true;
}
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
index a737ba0..c5957e9 100644
--- a/services/mediametrics/statsd_codec.cpp
+++ b/services/mediametrics/statsd_codec.cpp
@@ -29,7 +29,7 @@
#include <sys/types.h>
#include <unistd.h>
-#include <statslog.h>
+#include <stats_media_metrics.h>
#include <stats_event.h>
#include "cleaner.h"
@@ -46,7 +46,7 @@
if (item == nullptr) return false;
AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, android::util::MEDIA_CODEC_REPORTED);
+ AStatsEvent_setAtomId(event, stats::media_metrics::MEDIA_CODEC_REPORTED);
const nsecs_t timestamp_nanos = MediaMetricsService::roundTime(item->getTimestamp());
AStatsEvent_writeInt64(event, timestamp_nanos);
@@ -455,8 +455,8 @@
ALOGE("Failed to serialize codec metrics");
return false;
}
- android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
- int result = android::util::stats_write(android::util::MEDIAMETRICS_CODEC_REPORTED,
+ const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+ const int result = stats::media_metrics::stats_write(stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED,
timestamp_nanos, package_name.c_str(), package_version_code,
media_apex_version,
bf_serialized);
@@ -464,7 +464,7 @@
std::stringstream log;
log << "result:" << result << " {"
<< " mediametrics_codec_reported:"
- << android::util::MEDIAMETRICS_CODEC_REPORTED
+ << stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED
<< " timestamp_nanos:" << timestamp_nanos
<< " package_name:" << package_name
<< " package_version_code:" << package_version_code
@@ -525,7 +525,7 @@
<< " original_qp_b_min:" << qpBMinOri
<< " original_qp_b_max:" << qpBMaxOri
<< " }";
- statsdLog->log(android::util::MEDIAMETRICS_CODEC_REPORTED, log.str());
+ statsdLog->log(stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED, log.str());
return true;
diff --git a/services/mediametrics/statsd_drm.cpp b/services/mediametrics/statsd_drm.cpp
index e06a605..9f08eca 100644
--- a/services/mediametrics/statsd_drm.cpp
+++ b/services/mediametrics/statsd_drm.cpp
@@ -18,8 +18,9 @@
#define LOG_TAG "statsd_drm"
#include <utils/Log.h>
#include <media/stagefright/foundation/base64.h>
+#include <binder/IPCThreadState.h>
-#include <stdint.h>
+#include <cstdint>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -32,10 +33,11 @@
#include <pwd.h>
#include "MediaMetricsService.h"
+#include "MediaDrmStatsdHelper.h"
#include "StringUtils.h"
#include "iface_statsd.h"
-#include <statslog.h>
+#include <stats_media_metrics.h>
#include <array>
#include <string>
@@ -69,8 +71,9 @@
// This field is left here for backward compatibility.
// This field is not used anymore.
const std::string kUnusedField("");
- android::util::BytesField bf_serialized(kUnusedField.c_str(), kUnusedField.size());
- int result = android::util::stats_write(android::util::MEDIAMETRICS_MEDIADRM_REPORTED,
+ const stats::media_metrics::BytesField bf_serialized(kUnusedField.c_str(), kUnusedField.size());
+ const int result = stats::media_metrics::stats_write(
+ stats::media_metrics::MEDIAMETRICS_MEDIADRM_REPORTED,
timestamp_nanos, package_name.c_str(), package_version_code,
media_apex_version,
vendor.c_str(),
@@ -80,7 +83,7 @@
std::stringstream log;
log << "result:" << result << " {"
<< " mediametrics_mediadrm_reported:"
- << android::util::MEDIAMETRICS_MEDIADRM_REPORTED
+ << stats::media_metrics::MEDIAMETRICS_MEDIADRM_REPORTED
<< " timestamp_nanos:" << timestamp_nanos
<< " package_name:" << package_name
<< " package_version_code:" << package_version_code
@@ -90,7 +93,7 @@
<< " description:" << description
// omitting serialized
<< " }";
- statsdLog->log(android::util::MEDIAMETRICS_MEDIADRM_REPORTED, log.str());
+ statsdLog->log(stats::media_metrics::MEDIAMETRICS_MEDIADRM_REPORTED, log.str());
return true;
}
@@ -122,7 +125,8 @@
item->getInt64(("method"s + std::to_string(i)).c_str(), &methodCounts[i]);
}
- const int result = android::util::stats_write(android::util::MEDIAMETRICS_DRMMANAGER_REPORTED,
+ const int result = stats::media_metrics::stats_write(
+ stats::media_metrics::MEDIAMETRICS_DRMMANAGER_REPORTED,
timestamp_nanos, package_name.c_str(), package_version_code,
media_apex_version,
plugin_id.c_str(), description.c_str(),
@@ -136,7 +140,7 @@
std::stringstream log;
log << "result:" << result << " {"
<< " mediametrics_drmmanager_reported:"
- << android::util::MEDIAMETRICS_DRMMANAGER_REPORTED
+ << stats::media_metrics::MEDIAMETRICS_DRMMANAGER_REPORTED
<< " timestamp_nanos:" << timestamp_nanos
<< " package_name:" << package_name
<< " package_version_code:" << package_version_code
@@ -151,7 +155,7 @@
log << " method_" << i << ":" << methodCounts[i];
}
log << " }";
- statsdLog->log(android::util::MEDIAMETRICS_DRMMANAGER_REPORTED, log.str());
+ statsdLog->log(stats::media_metrics::MEDIAMETRICS_DRMMANAGER_REPORTED, log.str());
return true;
}
@@ -207,7 +211,7 @@
// Memory for |event| is internally managed by statsd.
AStatsEvent* event = AStatsEventList_addStatsEvent(out);
- AStatsEvent_setAtomId(event, android::util::MEDIA_DRM_ACTIVITY_INFO);
+ AStatsEvent_setAtomId(event, stats::media_metrics::MEDIA_DRM_ACTIVITY_INFO);
AStatsEvent_writeString(event, item->getPkgName().c_str());
AStatsEvent_writeInt64(event, item->getPkgVersionCode());
AStatsEvent_writeString(event, vendor.c_str());
@@ -219,7 +223,7 @@
std::stringstream log;
log << "pulled:" << " {"
<< " media_drm_activity_info:"
- << android::util::MEDIA_DRM_ACTIVITY_INFO
+ << stats::media_metrics::MEDIA_DRM_ACTIVITY_INFO
<< " package_name:" << item->getPkgName()
<< " package_version_code:" << item->getPkgVersionCode()
<< " vendor:" << vendor
@@ -227,7 +231,146 @@
<< " framework_metrics:" << mediametrics::stringutils::bytesToString(framework_raw, 8)
<< " vendor_metrics:" << mediametrics::stringutils::bytesToString(plugin_raw, 8)
<< " }";
- statsdLog->log(android::util::MEDIA_DRM_ACTIVITY_INFO, log.str());
+ statsdLog->log(stats::media_metrics::MEDIA_DRM_ACTIVITY_INFO, log.str());
+ return true;
+}
+
+bool statsd_mediadrm_created(const std::shared_ptr<const mediametrics::Item>& item,
+ const std::shared_ptr<mediametrics::StatsdLog>& statsdLog)
+{
+ int64_t uuid_lsb = -1;
+ if (!item->getInt64("uuid_lsb", &uuid_lsb)) return false;
+ int64_t uuid_msb = -1;
+ if (!item->getInt64("uuid_msb", &uuid_msb)) return false;
+ const int32_t scheme = MediaDrmStatsdHelper::findDrmScheme(uuid_msb, uuid_lsb);
+ const int32_t uid = IPCThreadState::self()->getCallingUid();
+ int32_t frontend = 0;
+ if (!item->getInt32("frontend", &frontend)) return false;
+
+ // Optional to be included
+ std::string version = "";
+ item->getString("version", &version);
+ const int result = stats_write(stats::media_metrics::MEDIA_DRM_CREATED,
+ scheme, uuid_lsb, uuid_msb, uid, frontend, version.c_str());
+
+ std::stringstream log;
+ log << "result:" << result << " {"
+ << " media_drm_created:"
+ << stats::media_metrics::MEDIA_DRM_CREATED
+ << " scheme:" << scheme
+ << " uuid_lsb:" << uuid_lsb
+ << " uuid_msb:" << uuid_msb
+ << " uid:" << uid
+ << " frontend:" << frontend
+ << " version:" << version
+ << " }";
+ statsdLog->log(stats::media_metrics::MEDIA_DRM_CREATED, log.str());
+ return true;
+}
+
+bool statsd_mediadrm_session_opened(const std::shared_ptr<const mediametrics::Item>& item,
+ const std::shared_ptr<mediametrics::StatsdLog>& statsdLog)
+{
+ int64_t uuid_lsb = -1;
+ if (!item->getInt64("uuid_lsb", &uuid_lsb)) return false;
+ int64_t uuid_msb = -1;
+ if (!item->getInt64("uuid_msb", &uuid_msb)) return false;
+ const int32_t scheme = MediaDrmStatsdHelper::findDrmScheme(uuid_msb, uuid_lsb);
+ std::string object_nonce = "";
+ if (!item->getString("object_nonce", &object_nonce)) return false;
+ const int32_t uid = IPCThreadState::self()->getCallingUid();
+ int32_t frontend = 0;
+ if (!item->getInt32("frontend", &frontend)) return false;
+ int32_t requested_security_level = -1;
+ if (!item->getInt32("requested_security_level", &requested_security_level)) return false;
+ int32_t opened_security_level = -1;
+ if (!item->getInt32("opened_security_level", &opened_security_level)) return false;
+
+ // Optional to be included
+ std::string version = "";
+ item->getString("version", &version);
+ const int result = stats_write(stats::media_metrics::MEDIA_DRM_SESSION_OPENED,
+ scheme, uuid_lsb, uuid_msb, uid, frontend, version.c_str(),
+ object_nonce.c_str(), requested_security_level,
+ opened_security_level);
+
+ std::stringstream log;
+ log << "result:" << result << " {"
+ << " media_drm_session_opened:"
+ << stats::media_metrics::MEDIA_DRM_SESSION_OPENED
+ << " scheme:" << scheme
+ << " uuid_lsb:" << uuid_lsb
+ << " uuid_msb:" << uuid_msb
+ << " uid:" << uid
+ << " frontend:" << frontend
+ << " version:" << version
+ << " object_nonce:" << object_nonce
+ << " requested_security_level:" << requested_security_level
+ << " opened_security_level:" << opened_security_level
+ << " }";
+ statsdLog->log(stats::media_metrics::MEDIA_DRM_SESSION_OPENED, log.str());
+ return true;
+}
+
+bool statsd_mediadrm_errored(const std::shared_ptr<const mediametrics::Item>& item,
+ const std::shared_ptr<mediametrics::StatsdLog>& statsdLog)
+{
+ int64_t uuid_lsb = -1;
+ if (!item->getInt64("uuid_lsb", &uuid_lsb)) return false;
+ int64_t uuid_msb = -1;
+ if (!item->getInt64("uuid_msb", &uuid_msb)) return false;
+ const int32_t scheme = MediaDrmStatsdHelper::findDrmScheme(uuid_msb, uuid_lsb);
+ const int32_t uid = IPCThreadState::self()->getCallingUid();
+ int32_t frontend = 0;
+ if (!item->getInt32("frontend", &frontend)) return false;
+ std::string object_nonce = "";
+ if (!item->getString("object_nonce", &object_nonce)) return false;
+ int32_t security_level = -1;
+ if (!item->getInt32("security_level", &security_level)) return false;
+ std::string api_str = "";
+ if (!item->getString("api", &api_str)) return false;
+ const int32_t api = MediaDrmStatsdHelper::findDrmApi(api_str);
+ int32_t error_code = -1;
+ if (!item->getInt32("error_code", &error_code)) return false;
+
+ // Optional to be included
+ std::string version = "";
+ item->getString("version", &version);
+ std::string session_nonce = "";
+ item->getString("session_nonce", &session_nonce);
+
+ int32_t cdm_err = 0;
+ item->getInt32("cdm_err", &cdm_err);
+ int32_t oem_err = 0;
+ item->getInt32("oem_err", &oem_err);
+ int32_t error_context = -1;
+ item->getInt32("error_context", &error_context);
+
+ const int result = stats_write(stats::media_metrics::MEDIA_DRM_ERRORED, scheme, uuid_lsb,
+ uuid_msb, uid, frontend, version.c_str(), object_nonce.c_str(),
+ session_nonce.c_str(), security_level, api, error_code, cdm_err,
+ oem_err, error_context);
+
+ std::stringstream log;
+ log << "result:" << result << " {"
+ << " media_drm_errored:"
+ << stats::media_metrics::MEDIA_DRM_ERRORED
+ << " scheme:" << scheme
+ << " uuid_lsb:" << uuid_lsb
+ << " uuid_msb:" << uuid_msb
+ << " uid:" << uid
+ << " frontend:" << frontend
+ << " version:" << version
+ << " object_nonce:" << object_nonce
+ << " session_nonce:" << session_nonce
+ << " security_level:" << security_level
+ << " api:" << api
+ << " error_code:" << error_code
+ << " cdm_err:" << cdm_err
+ << " oem_err:" << oem_err
+ << " error_context:" << error_context
+ << " }";
+ statsdLog->log(stats::media_metrics::MEDIA_DRM_ERRORED, log.str());
return true;
}
diff --git a/services/mediametrics/statsd_extractor.cpp b/services/mediametrics/statsd_extractor.cpp
index a8bfeaa..9345df6 100644
--- a/services/mediametrics/statsd_extractor.cpp
+++ b/services/mediametrics/statsd_extractor.cpp
@@ -29,7 +29,7 @@
#include <sys/types.h>
#include <unistd.h>
-#include <statslog.h>
+#include <stats_media_metrics.h>
#include "MediaMetricsService.h"
#include "ValidateId.h"
@@ -96,15 +96,16 @@
return false;
}
- android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
- int result = android::util::stats_write(android::util::MEDIAMETRICS_EXTRACTOR_REPORTED,
+ const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+ const int result = stats::media_metrics::stats_write(
+ stats::media_metrics::MEDIAMETRICS_EXTRACTOR_REPORTED,
timestamp_nanos, package_name.c_str(), package_version_code,
media_apex_version,
bf_serialized);
std::stringstream log;
log << "result:" << result << " {"
<< " mediametrics_extractor_reported:"
- << android::util::MEDIAMETRICS_EXTRACTOR_REPORTED
+ << stats::media_metrics::MEDIAMETRICS_EXTRACTOR_REPORTED
<< " timestamp_nanos:" << timestamp_nanos
<< " package_name:" << package_name
<< " package_version_code:" << package_version_code
@@ -116,7 +117,7 @@
<< " entry_point:" << entry_point_string << "(" << entry_point << ")"
<< " log_session_id:" << log_session_id
<< " }";
- statsdLog->log(android::util::MEDIAMETRICS_EXTRACTOR_REPORTED, log.str());
+ statsdLog->log(stats::media_metrics::MEDIAMETRICS_EXTRACTOR_REPORTED, log.str());
return true;
}
diff --git a/services/mediametrics/statsd_mediaparser.cpp b/services/mediametrics/statsd_mediaparser.cpp
index 67ca874b..458bd32 100644
--- a/services/mediametrics/statsd_mediaparser.cpp
+++ b/services/mediametrics/statsd_mediaparser.cpp
@@ -28,7 +28,7 @@
#include <sys/types.h>
#include <unistd.h>
-#include <statslog.h>
+#include <stats_media_metrics.h>
#include "MediaMetricsService.h"
#include "ValidateId.h"
@@ -83,7 +83,8 @@
item->getString("android.media.mediaparser.logSessionId", &logSessionId);
logSessionId = mediametrics::ValidateId::get()->validateId(logSessionId);
- int result = android::util::stats_write(android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED,
+ const int result = stats::media_metrics::stats_write(
+ stats::media_metrics::MEDIAMETRICS_MEDIAPARSER_REPORTED,
timestamp_nanos,
package_name.c_str(),
package_version_code,
@@ -103,7 +104,7 @@
std::stringstream log;
log << "result:" << result << " {"
<< " mediametrics_mediaparser_reported:"
- << android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED
+ << stats::media_metrics::MEDIAMETRICS_MEDIAPARSER_REPORTED
<< " timestamp_nanos:" << timestamp_nanos
<< " package_name:" << package_name
<< " package_version_code:" << package_version_code
@@ -120,7 +121,7 @@
<< " video_height:" << videoHeight
<< " log_session_id:" << logSessionId
<< " }";
- statsdLog->log(android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED, log.str());
+ statsdLog->log(stats::media_metrics::MEDIAMETRICS_MEDIAPARSER_REPORTED, log.str());
return true;
}
diff --git a/services/mediametrics/statsd_nuplayer.cpp b/services/mediametrics/statsd_nuplayer.cpp
index bdee1f2..fd545f4 100644
--- a/services/mediametrics/statsd_nuplayer.cpp
+++ b/services/mediametrics/statsd_nuplayer.cpp
@@ -29,7 +29,7 @@
#include <sys/types.h>
#include <unistd.h>
-#include <statslog.h>
+#include <stats_media_metrics.h>
#include "MediaMetricsService.h"
#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
@@ -153,8 +153,9 @@
return false;
}
- android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
- int result = android::util::stats_write(android::util::MEDIAMETRICS_NUPLAYER_REPORTED,
+ const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+ const int result = stats::media_metrics::stats_write(
+ stats::media_metrics::MEDIAMETRICS_NUPLAYER_REPORTED,
timestamp_nanos, package_name.c_str(), package_version_code,
media_apex_version,
bf_serialized);
@@ -162,7 +163,7 @@
std::stringstream log;
log << "result:" << result << " {"
<< " mediametrics_nuplayer_reported:"
- << android::util::MEDIAMETRICS_NUPLAYER_REPORTED
+ << stats::media_metrics::MEDIAMETRICS_NUPLAYER_REPORTED
<< " timestamp_nanos:" << timestamp_nanos
<< " package_name:" << package_name
<< " package_version_code:" << package_version_code
@@ -193,7 +194,7 @@
// TODO NuPlayer - add log_session_id
// << " log_session_id:" << log_session_id
<< " }";
- statsdLog->log(android::util::MEDIAMETRICS_NUPLAYER_REPORTED, log.str());
+ statsdLog->log(stats::media_metrics::MEDIAMETRICS_NUPLAYER_REPORTED, log.str());
return true;
}
diff --git a/services/mediametrics/statsd_recorder.cpp b/services/mediametrics/statsd_recorder.cpp
index 5f54a68..efa284b 100644
--- a/services/mediametrics/statsd_recorder.cpp
+++ b/services/mediametrics/statsd_recorder.cpp
@@ -29,7 +29,7 @@
#include <sys/types.h>
#include <unistd.h>
-#include <statslog.h>
+#include <stats_media_metrics.h>
#include "MediaMetricsService.h"
#include "ValidateId.h"
@@ -179,15 +179,16 @@
return false;
}
- android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
- int result = android::util::stats_write(android::util::MEDIAMETRICS_RECORDER_REPORTED,
+ const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+ const int result = stats::media_metrics::stats_write(
+ stats::media_metrics::MEDIAMETRICS_RECORDER_REPORTED,
timestamp_nanos, package_name.c_str(), package_version_code,
media_apex_version,
bf_serialized);
std::stringstream log;
log << "result:" << result << " {"
<< " mediametrics_recorder_reported:"
- << android::util::MEDIAMETRICS_RECORDER_REPORTED
+ << stats::media_metrics::MEDIAMETRICS_RECORDER_REPORTED
<< " timestamp_nanos:" << timestamp_nanos
<< " package_name:" << package_name
<< " package_version_code:" << package_version_code
@@ -218,7 +219,7 @@
<< " iframe_interval:" << iframe_interval
<< " log_session_id:" << log_session_id
<< " }";
- statsdLog->log(android::util::MEDIAMETRICS_RECORDER_REPORTED, log.str());
+ statsdLog->log(stats::media_metrics::MEDIAMETRICS_RECORDER_REPORTED, log.str());
return true;
}
diff --git a/services/mediaresourcemanager/Android.bp b/services/mediaresourcemanager/Android.bp
index 5d80744..2b8245e 100644
--- a/services/mediaresourcemanager/Android.bp
+++ b/services/mediaresourcemanager/Android.bp
@@ -16,6 +16,7 @@
"aidl/android/media/MediaResourceSubType.aidl",
"aidl/android/media/MediaResourceParcel.aidl",
"aidl/android/media/MediaResourcePolicyParcel.aidl",
+ "aidl/android/media/ClientInfoParcel.aidl",
],
path: "aidl",
}
@@ -87,10 +88,15 @@
"libbinder_ndk",
"libutils",
"liblog",
+ "libstats_media_metrics",
+ "libstatspull",
+ "libstatssocket",
+ "libprotobuf-cpp-lite",
],
static_libs: [
"resourceobserver_aidl_interface-V1-ndk",
+ "libplatformprotos",
],
include_dirs: ["frameworks/av/include"],
@@ -101,4 +107,10 @@
],
export_include_dirs: ["."],
+
+ export_shared_lib_headers: [
+ "libstats_media_metrics",
+ "libstatspull",
+ "libstatssocket",
+ ],
}
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index b4610bc..5582528 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -34,6 +34,7 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
+#include <stats_media_metrics.h>
#include "IMediaResourceMonitor.h"
#include "ResourceManagerService.h"
@@ -42,6 +43,14 @@
namespace android {
+using stats::media_metrics::stats_write;
+using stats::media_metrics::MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED;
+using stats::media_metrics::MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
+using stats::media_metrics::\
+ MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
+using stats::media_metrics::\
+ MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
+
//static
std::mutex ResourceManagerService::sCookieLock;
//static
@@ -97,7 +106,8 @@
service->overridePid(mPid, -1);
// thiz is freed in the call below, so it must be last call referring thiz
- service->removeResource(mPid, mClientId, false /*checkValid*/);
+ ClientInfoParcel clientInfo{.pid = mPid, .id = mClientId};
+ service->removeResource(clientInfo, false /*checkValid*/);
}
class OverrideProcessInfoDeathNotifier : public DeathNotifier {
@@ -183,6 +193,7 @@
}
static ResourceInfo& getResourceInfoForEdit(uid_t uid, int64_t clientId,
+ const std::string& name,
const std::shared_ptr<IResourceManagerClient>& client, ResourceInfos& infos) {
ssize_t index = infos.indexOfKey(clientId);
@@ -190,6 +201,7 @@
ResourceInfo info;
info.uid = uid;
info.clientId = clientId;
+ info.name = name;
info.client = client;
info.cookie = 0;
info.pendingRemoval = false;
@@ -262,7 +274,15 @@
result.append(" Processes:\n");
for (size_t i = 0; i < mapCopy.size(); ++i) {
- snprintf(buffer, SIZE, " Pid: %d\n", mapCopy.keyAt(i));
+ int pid = mapCopy.keyAt(i);
+ snprintf(buffer, SIZE, " Pid: %d\n", pid);
+ result.append(buffer);
+ int priority = 0;
+ if (getPriority_l(pid, &priority)) {
+ snprintf(buffer, SIZE, " Priority: %d\n", priority);
+ } else {
+ snprintf(buffer, SIZE, " Priority: <unknown>\n");
+ }
result.append(buffer);
const ResourceInfos &infos = mapCopy.valueAt(i);
@@ -271,10 +291,9 @@
snprintf(buffer, SIZE, " Id: %lld\n", (long long)infos[j].clientId);
result.append(buffer);
- std::string clientName;
- Status status = infos[j].client->getName(&clientName);
- if (!status.isOk()) {
- clientName = "<unknown client>";
+ std::string clientName = "<unknown client>";
+ if (infos[j].client != nullptr) {
+ clientName = infos[j].name;
}
snprintf(buffer, SIZE, " Name: %s\n", clientName.c_str());
result.append(buffer);
@@ -344,7 +363,9 @@
std::shared_ptr<ResourceManagerService> service =
::ndk::SharedRefBase::make<ResourceManagerService>();
binder_status_t status =
- AServiceManager_addService(service->asBinder().get(), getServiceName());
+ AServiceManager_addServiceWithFlags(
+ service->asBinder().get(), getServiceName(),
+ AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED);
if (status != STATUS_OK) {
return;
}
@@ -434,11 +455,15 @@
}
}
-Status ResourceManagerService::addResource(int32_t pid, int32_t uid, int64_t clientId,
+Status ResourceManagerService::addResource(const ClientInfoParcel& clientInfo,
const std::shared_ptr<IResourceManagerClient>& client,
const std::vector<MediaResourceParcel>& resources) {
- String8 log = String8::format("addResource(pid %d, clientId %lld, resources %s)",
- pid, (long long) clientId, getString(resources).string());
+ int32_t pid = clientInfo.pid;
+ int32_t uid = clientInfo.uid;
+ int64_t clientId = clientInfo.id;
+ const std::string& name = clientInfo.name;
+ String8 log = String8::format("addResource(pid %d, uid %d clientId %lld, resources %s)",
+ pid, uid, (long long) clientId, getString(resources).string());
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
@@ -451,7 +476,7 @@
uid = callingUid;
}
ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
- ResourceInfo& info = getResourceInfoForEdit(uid, clientId, client, infos);
+ ResourceInfo& info = getResourceInfoForEdit(uid, clientId, name, client, infos);
ResourceList resourceAdded;
for (size_t i = 0; i < resources.size(); ++i) {
@@ -490,13 +515,50 @@
mObserverService->onResourceAdded(uid, pid, resourceAdded);
}
notifyResourceGranted(pid, resources);
+
+ // Increase the instance count of the resource associated with this client.
+ increaseResourceInstanceCount(clientId, name);
+
return Status::ok();
}
-Status ResourceManagerService::removeResource(int32_t pid, int64_t clientId,
+void ResourceManagerService::increaseResourceInstanceCount(int64_t clientId,
+ const std::string& name) {
+ // Check whether this client has been looked into already.
+ if (mClientIdSet.find(clientId) == mClientIdSet.end()) {
+ mClientIdSet.insert(clientId);
+ // Update the resource instance count.
+ auto found = mConcurrentResourceCountMap.find(name);
+ if (found == mConcurrentResourceCountMap.end()) {
+ mConcurrentResourceCountMap[name] = 1;
+ } else {
+ found->second++;
+ }
+ }
+}
+
+void ResourceManagerService::decreaseResourceInstanceCount(int64_t clientId,
+ const std::string& name) {
+ // Since this client has been removed, remove it from mClientIdSet
+ mClientIdSet.erase(clientId);
+ // Update the resource instance count also.
+ auto found = mConcurrentResourceCountMap.find(name);
+ if (found != mConcurrentResourceCountMap.end()) {
+ if (found->second == 1) {
+ mConcurrentResourceCountMap.erase(found);
+ } else {
+ found->second--;
+ }
+ }
+}
+
+Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo,
const std::vector<MediaResourceParcel>& resources) {
- String8 log = String8::format("removeResource(pid %d, clientId %lld, resources %s)",
- pid, (long long) clientId, getString(resources).string());
+ int32_t pid = clientInfo.pid;
+ int32_t uid = clientInfo.uid;
+ int64_t clientId = clientInfo.id;
+ String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld, resources %s)",
+ pid, uid, (long long) clientId, getString(resources).string());
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
@@ -556,15 +618,17 @@
return Status::ok();
}
-Status ResourceManagerService::removeClient(int32_t pid, int64_t clientId) {
- removeResource(pid, clientId, true /*checkValid*/);
+Status ResourceManagerService::removeClient(const ClientInfoParcel& clientInfo) {
+ removeResource(clientInfo, true /*checkValid*/);
return Status::ok();
}
-Status ResourceManagerService::removeResource(int pid, int64_t clientId, bool checkValid) {
- String8 log = String8::format(
- "removeResource(pid %d, clientId %lld)",
- pid, (long long) clientId);
+Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo, bool checkValid) {
+ int32_t pid = clientInfo.pid;
+ int32_t uid = clientInfo.uid;
+ int64_t clientId = clientInfo.id;
+ String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld)",
+ pid, uid, (long long) clientId);
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
@@ -592,6 +656,10 @@
onLastRemoved(it->second, info);
}
+ // Since this client has been removed, decrease the corresponding
+ // resources instance count.
+ decreaseResourceInstanceCount(clientId, info.name);
+
removeCookieAndUnlink_l(info.client, info.cookie);
if (mObserverService != nullptr && !info.resources.empty()) {
@@ -602,25 +670,30 @@
return Status::ok();
}
-void ResourceManagerService::getClientForResource_l(int callingPid, const MediaResourceParcel *res,
+void ResourceManagerService::getClientForResource_l(int callingPid,
+ const MediaResourceParcel *res,
+ PidUidVector* idVector,
Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
if (res == NULL) {
return;
}
std::shared_ptr<IResourceManagerClient> client;
- if (getLowestPriorityBiggestClient_l(callingPid, res->type, res->subType, &client)) {
+ if (getLowestPriorityBiggestClient_l(callingPid, res->type, res->subType, idVector, &client)) {
clients->push_back(client);
}
}
-Status ResourceManagerService::reclaimResource(int32_t callingPid,
+Status ResourceManagerService::reclaimResource(const ClientInfoParcel& clientInfo,
const std::vector<MediaResourceParcel>& resources, bool* _aidl_return) {
- String8 log = String8::format("reclaimResource(callingPid %d, resources %s)",
- callingPid, getString(resources).string());
+ int32_t callingPid = clientInfo.pid;
+ std::string clientName = clientInfo.name;
+ String8 log = String8::format("reclaimResource(callingPid %d, uid %d resources %s)",
+ callingPid, clientInfo.uid, getString(resources).string());
mServiceLog->add(log);
*_aidl_return = false;
Vector<std::shared_ptr<IResourceManagerClient>> clients;
+ PidUidVector idVector;
{
Mutex::Autolock lock(mLock);
if (!mProcessInfo->isPidTrusted(callingPid)) {
@@ -656,13 +729,13 @@
if (secureCodec != NULL) {
if (!mSupportsMultipleSecureCodecs) {
if (!getAllClients_l(callingPid, MediaResource::Type::kSecureCodec,
- secureCodec->subType, &clients)) {
+ secureCodec->subType, &idVector, &clients)) {
return Status::ok();
}
}
if (!mSupportsSecureWithNonSecureCodec) {
if (!getAllClients_l(callingPid, MediaResource::Type::kNonSecureCodec,
- secureCodec->subType, &clients)) {
+ secureCodec->subType, &idVector, &clients)) {
return Status::ok();
}
}
@@ -670,13 +743,13 @@
if (nonSecureCodec != NULL) {
if (!mSupportsSecureWithNonSecureCodec) {
if (!getAllClients_l(callingPid, MediaResource::Type::kSecureCodec,
- nonSecureCodec->subType, &clients)) {
+ nonSecureCodec->subType, &idVector, &clients)) {
return Status::ok();
}
}
}
if (drmSession != NULL) {
- getClientForResource_l(callingPid, drmSession, &clients);
+ getClientForResource_l(callingPid, drmSession, &idVector, &clients);
if (clients.size() == 0) {
return Status::ok();
}
@@ -684,32 +757,108 @@
if (clients.size() == 0) {
// if no secure/non-secure codec conflict, run second pass to handle other resources.
- getClientForResource_l(callingPid, graphicMemory, &clients);
+ getClientForResource_l(callingPid, graphicMemory, &idVector, &clients);
}
if (clients.size() == 0) {
// if we are here, run the third pass to free one codec with the same type.
- getClientForResource_l(callingPid, secureCodec, &clients);
- getClientForResource_l(callingPid, nonSecureCodec, &clients);
+ getClientForResource_l(callingPid, secureCodec, &idVector, &clients);
+ getClientForResource_l(callingPid, nonSecureCodec, &idVector, &clients);
}
if (clients.size() == 0) {
// if we are here, run the fourth pass to free one codec with the different type.
if (secureCodec != NULL) {
MediaResource temp(MediaResource::Type::kNonSecureCodec, secureCodec->subType, 1);
- getClientForResource_l(callingPid, &temp, &clients);
+ getClientForResource_l(callingPid, &temp, &idVector, &clients);
}
if (nonSecureCodec != NULL) {
MediaResource temp(MediaResource::Type::kSecureCodec, nonSecureCodec->subType, 1);
- getClientForResource_l(callingPid, &temp, &clients);
+ getClientForResource_l(callingPid, &temp, &idVector, &clients);
}
}
}
*_aidl_return = reclaimUnconditionallyFrom(clients);
+
+ // Log Reclaim Pushed Atom to statsd
+ pushReclaimAtom(clientInfo, clients, idVector, *_aidl_return);
+
return Status::ok();
}
+void ResourceManagerService::pushReclaimAtom(const ClientInfoParcel& clientInfo,
+ const Vector<std::shared_ptr<IResourceManagerClient>>& clients,
+ const PidUidVector& idVector, bool reclaimed) {
+ // Construct the metrics for codec reclaim as a pushed atom.
+ // 1. Information about the requester.
+ // - UID and the priority (oom score)
+ int32_t callingPid = clientInfo.pid;
+ int32_t requesterUid = clientInfo.uid;
+ std::string clientName = clientInfo.name;
+ int requesterPriority = -1;
+ getPriority_l(callingPid, &requesterPriority);
+
+ // 2. Information about the codec.
+ // - Name of the codec requested
+ // - Number of concurrent codecs running.
+ int32_t noOfConcurrentCodecs = 0;
+ auto found = mConcurrentResourceCountMap.find(clientName);
+ if (found != mConcurrentResourceCountMap.end()) {
+ noOfConcurrentCodecs = found->second;
+ }
+
+ // 3. Information about the Reclaim:
+ // - Status of reclaim request
+ // - How many codecs are reclaimed
+ // - For each codecs reclaimed, information of the process that it belonged to:
+ // - UID and the Priority (oom score)
+ int32_t reclaimStatus = MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
+ if (!reclaimed) {
+ if (clients.size() == 0) {
+ // No clients to reclaim from
+ reclaimStatus =
+ MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
+ } else {
+ // Couldn't reclaim resources from the clients
+ reclaimStatus =
+ MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
+ }
+ }
+ int32_t noOfCodecsReclaimed = clients.size();
+ int32_t targetIndex = 1;
+ for (const auto& id : idVector) {
+ int32_t targetUid = id.second;
+ int targetPriority = -1;
+ getPriority_l(id.first, &targetPriority);
+ // Post the pushed atom
+ int result = stats_write(
+ MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED,
+ requesterUid,
+ requesterPriority,
+ clientName.c_str(),
+ noOfConcurrentCodecs,
+ reclaimStatus,
+ noOfCodecsReclaimed,
+ targetIndex,
+ targetUid,
+ targetPriority);
+ ALOGI("%s: Pushed MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED atom: "
+ "Requester[pid(%d): uid(%d): priority(%d)] "
+ "Codec: [%s] "
+ "No of concurrent codecs: %d "
+ "Reclaim Status: %d "
+ "No of codecs reclaimed: %d "
+ "Target[%d][pid(%d): uid(%d): priority(%d)] "
+ "Atom Size: %d",
+ __func__, callingPid, requesterUid, requesterPriority,
+ clientName.c_str(), noOfConcurrentCodecs,
+ reclaimStatus, noOfCodecsReclaimed,
+ targetIndex, id.first, targetUid, targetPriority, result);
+ targetIndex++;
+ }
+}
+
bool ResourceManagerService::reclaimUnconditionallyFrom(
const Vector<std::shared_ptr<IResourceManagerClient>> &clients) {
if (clients.size() == 0) {
@@ -869,7 +1018,9 @@
mProcessInfoOverrideMap.erase(pid);
}
-Status ResourceManagerService::markClientForPendingRemoval(int32_t pid, int64_t clientId) {
+Status ResourceManagerService::markClientForPendingRemoval(const ClientInfoParcel& clientInfo) {
+ int32_t pid = clientInfo.pid;
+ int64_t clientId = clientInfo.id;
String8 log = String8::format(
"markClientForPendingRemoval(pid %d, clientId %lld)",
pid, (long long) clientId);
@@ -927,7 +1078,8 @@
MediaResource::SubType::kVideoCodec,
MediaResource::SubType::kImageCodec}) {
std::shared_ptr<IResourceManagerClient> client;
- if (getBiggestClientPendingRemoval_l(pid, type, subType, &client)) {
+ uid_t uid = 0;
+ if (getBiggestClientPendingRemoval_l(pid, type, subType, uid, &client)) {
clients.add(client);
continue;
}
@@ -936,8 +1088,9 @@
// Non-codec resources are shared by audio, video and image codecs (no subtype).
default:
std::shared_ptr<IResourceManagerClient> client;
+ uid_t uid = 0;
if (getBiggestClientPendingRemoval_l(pid, type,
- MediaResource::SubType::kUnspecifiedSubType, &client)) {
+ MediaResource::SubType::kUnspecifiedSubType, uid, &client)) {
clients.add(client);
}
break;
@@ -964,8 +1117,12 @@
}
bool ResourceManagerService::getAllClients_l(int callingPid, MediaResource::Type type,
- MediaResource::SubType subType, Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
+ MediaResource::SubType subType,
+ PidUidVector* idVector,
+ Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
Vector<std::shared_ptr<IResourceManagerClient>> temp;
+ PidUidVector tempIdList;
+
for (size_t i = 0; i < mMap.size(); ++i) {
ResourceInfos &infos = mMap.editValueAt(i);
for (size_t j = 0; j < infos.size(); ++j) {
@@ -978,6 +1135,7 @@
return false;
}
temp.push_back(infos[j].client);
+ tempIdList.emplace_back(mMap.keyAt(i), infos[j].uid);
}
}
}
@@ -986,19 +1144,24 @@
return true;
}
clients->appendVector(temp);
+ idVector->insert(std::end(*idVector), std::begin(tempIdList), std::end(tempIdList));
return true;
}
bool ResourceManagerService::getLowestPriorityBiggestClient_l(int callingPid,
- MediaResource::Type type, MediaResource::SubType subType,
+ MediaResource::Type type,
+ MediaResource::SubType subType,
+ PidUidVector* idVector,
std::shared_ptr<IResourceManagerClient> *client) {
int lowestPriorityPid;
int lowestPriority;
int callingPriority;
+ uid_t uid = 0;
// Before looking into other processes, check if we have clients marked for
// pending removal in the same process.
- if (getBiggestClientPendingRemoval_l(callingPid, type, subType, client)) {
+ if (getBiggestClientPendingRemoval_l(callingPid, type, subType, uid, client)) {
+ idVector->emplace_back(callingPid, uid);
return true;
}
if (!getPriority_l(callingPid, &callingPriority)) {
@@ -1015,9 +1178,11 @@
return false;
}
- if (!getBiggestClient_l(lowestPriorityPid, type, subType, client)) {
+ if (!getBiggestClient_l(lowestPriorityPid, type, subType, uid, client)) {
return false;
}
+
+ idVector->emplace_back(lowestPriorityPid, uid);
return true;
}
@@ -1069,12 +1234,14 @@
}
bool ResourceManagerService::getBiggestClientPendingRemoval_l(int pid, MediaResource::Type type,
- MediaResource::SubType subType, std::shared_ptr<IResourceManagerClient> *client) {
- return getBiggestClient_l(pid, type, subType, client, true /* pendingRemovalOnly */);
+ MediaResource::SubType subType, uid_t& uid,
+ std::shared_ptr<IResourceManagerClient> *client) {
+ return getBiggestClient_l(pid, type, subType, uid, client, true /* pendingRemovalOnly */);
}
bool ResourceManagerService::getBiggestClient_l(int pid, MediaResource::Type type,
- MediaResource::SubType subType, std::shared_ptr<IResourceManagerClient> *client,
+ MediaResource::SubType subType, uid_t& uid,
+ std::shared_ptr<IResourceManagerClient> *client,
bool pendingRemovalOnly) {
ssize_t index = mMap.indexOfKey(pid);
if (index < 0) {
@@ -1097,6 +1264,7 @@
if (resource.value > largestValue) {
largestValue = resource.value;
clientTemp = infos[i].client;
+ uid = infos[i].uid;
}
}
}
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index c636a0f..0016a19 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -19,7 +19,9 @@
#define ANDROID_MEDIA_RESOURCEMANAGERSERVICE_H
#include <map>
+#include <set>
#include <mutex>
+#include <string>
#include <aidl/android/media/BnResourceManagerService.h>
#include <arpa/inet.h>
@@ -43,20 +45,24 @@
using ::aidl::android::media::BnResourceManagerService;
using ::aidl::android::media::MediaResourceParcel;
using ::aidl::android::media::MediaResourcePolicyParcel;
+using ::aidl::android::media::ClientInfoParcel;
typedef std::map<std::tuple<
MediaResource::Type, MediaResource::SubType, std::vector<uint8_t>>,
MediaResourceParcel> ResourceList;
struct ResourceInfo {
- int64_t clientId;
uid_t uid;
+ int64_t clientId;
+ std::string name;
std::shared_ptr<IResourceManagerClient> client;
uintptr_t cookie{0};
ResourceList resources;
bool pendingRemoval{false};
};
+typedef std::vector<std::pair<int32_t, uid_t>> PidUidVector;
+
// TODO: convert these to std::map
typedef KeyedVector<int64_t, ResourceInfo> ResourceInfos;
typedef KeyedVector<int, ResourceInfos> PidResourceInfosMap;
@@ -85,31 +91,32 @@
// IResourceManagerService interface
Status config(const std::vector<MediaResourcePolicyParcel>& policies) override;
- Status addResource(int32_t pid, int32_t uid, int64_t clientId,
- const std::shared_ptr<IResourceManagerClient>& client,
- const std::vector<MediaResourceParcel>& resources) override;
+ Status addResource(const ClientInfoParcel& clientInfo,
+ const std::shared_ptr<IResourceManagerClient>& client,
+ const std::vector<MediaResourceParcel>& resources) override;
- Status removeResource(int32_t pid, int64_t clientId,
- const std::vector<MediaResourceParcel>& resources) override;
+ Status removeResource(const ClientInfoParcel& clientInfo,
+ const std::vector<MediaResourceParcel>& resources) override;
- Status removeClient(int32_t pid, int64_t clientId) override;
+ Status removeClient(const ClientInfoParcel& clientInfo) override;
// Tries to reclaim resource from processes with lower priority than the calling process
// according to the requested resources.
// Returns true if any resource has been reclaimed, otherwise returns false.
- Status reclaimResource(int32_t callingPid, const std::vector<MediaResourceParcel>& resources,
- bool* _aidl_return) override;
+ Status reclaimResource(const ClientInfoParcel& clientInfo,
+ const std::vector<MediaResourceParcel>& resources,
+ bool* _aidl_return) override;
- Status overridePid(int originalPid, int newPid) override;
+ Status overridePid(int32_t originalPid, int32_t newPid) override;
- Status overrideProcessInfo(const std::shared_ptr<IResourceManagerClient>& client, int pid,
- int procState, int oomScore) override;
+ Status overrideProcessInfo(const std::shared_ptr<IResourceManagerClient>& client,
+ int32_t pid, int32_t procState, int32_t oomScore) override;
- Status markClientForPendingRemoval(int32_t pid, int64_t clientId) override;
+ Status markClientForPendingRemoval(const ClientInfoParcel& clientInfo) override;
Status reclaimResourcesFromClientsPendingRemoval(int32_t pid) override;
- Status removeResource(int pid, int64_t clientId, bool checkValid);
+ Status removeResource(const ClientInfoParcel& clientInfo, bool checkValid);
private:
friend class ResourceManagerServiceTest;
@@ -124,13 +131,15 @@
// Returns false if any client belongs to a process with higher priority than the
// calling process. The clients will remain unchanged if returns false.
bool getAllClients_l(int callingPid, MediaResource::Type type, MediaResource::SubType subType,
+ PidUidVector* idList,
Vector<std::shared_ptr<IResourceManagerClient>> *clients);
// Gets the client who owns specified resource type from lowest possible priority process.
// Returns false if the calling process priority is not higher than the lowest process
// priority. The client will remain unchanged if returns false.
bool getLowestPriorityBiggestClient_l(int callingPid, MediaResource::Type type,
- MediaResource::SubType subType, std::shared_ptr<IResourceManagerClient> *client);
+ MediaResource::SubType subType, PidUidVector* idList,
+ std::shared_ptr<IResourceManagerClient> *client);
// Gets lowest priority process that has the specified resource type.
// Returns false if failed. The output parameters will remain unchanged if failed.
@@ -141,17 +150,19 @@
// Returns false with no change to client if there are no clients holdiing resources of thisi
// type.
bool getBiggestClient_l(int pid, MediaResource::Type type, MediaResource::SubType subType,
- std::shared_ptr<IResourceManagerClient> *client,
+ uid_t& uid, std::shared_ptr<IResourceManagerClient> *client,
bool pendingRemovalOnly = false);
// Same method as above, but with pendingRemovalOnly as true.
bool getBiggestClientPendingRemoval_l(int pid, MediaResource::Type type,
- MediaResource::SubType subType, std::shared_ptr<IResourceManagerClient> *client);
+ MediaResource::SubType subType, uid_t& uid,
+ std::shared_ptr<IResourceManagerClient> *client);
bool isCallingPriorityHigher_l(int callingPid, int pid);
// A helper function basically calls getLowestPriorityBiggestClient_l and add
// the result client to the given Vector.
void getClientForResource_l(int callingPid, const MediaResourceParcel *res,
+ PidUidVector* idList,
Vector<std::shared_ptr<IResourceManagerClient>> *clients);
void onFirstAdded(const MediaResourceParcel& res, const ResourceInfo& clientInfo);
@@ -171,6 +182,15 @@
void removeCookieAndUnlink_l(const std::shared_ptr<IResourceManagerClient>& client,
uintptr_t cookie);
+ // To increase/decrease the number of instances of a given resource
+ // associated with a client.
+ void increaseResourceInstanceCount(int64_t clientId, const std::string& name);
+ void decreaseResourceInstanceCount(int64_t clientId, const std::string& name);
+
+ void pushReclaimAtom(const ClientInfoParcel& clientInfo,
+ const Vector<std::shared_ptr<IResourceManagerClient>>& clients,
+ const PidUidVector& idList, bool reclaimed);
+
mutable Mutex mLock;
sp<ProcessInfoInterface> mProcessInfo;
sp<SystemCallbackInterface> mSystemCB;
@@ -191,6 +211,11 @@
static std::map<uintptr_t, sp<DeathNotifier> > sCookieToDeathNotifierMap
GUARDED_BY(sCookieLock);
std::shared_ptr<ResourceObserverService> mObserverService;
+
+ // List of active clients
+ std::set<int64_t> mClientIdSet;
+ // Map of resources (name) and number of concurrent instances
+ std::map<std::string, int> mConcurrentResourceCountMap;
};
// ----------------------------------------------------------------------------
diff --git a/services/mediaresourcemanager/ResourceObserverService.cpp b/services/mediaresourcemanager/ResourceObserverService.cpp
index 4e97406..ebe3903 100644
--- a/services/mediaresourcemanager/ResourceObserverService.cpp
+++ b/services/mediaresourcemanager/ResourceObserverService.cpp
@@ -100,8 +100,10 @@
std::shared_ptr<ResourceObserverService> ResourceObserverService::instantiate() {
std::shared_ptr<ResourceObserverService> observerService =
::ndk::SharedRefBase::make<ResourceObserverService>();
- binder_status_t status = AServiceManager_addService(observerService->asBinder().get(),
- ResourceObserverService::getServiceName());
+ binder_status_t status = AServiceManager_addServiceWithFlags(
+ observerService->asBinder().get(),ResourceObserverService::getServiceName(),
+ AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED);
+
if (status != STATUS_OK) {
return nullptr;
}
diff --git a/services/mediaresourcemanager/aidl/android/media/ClientInfoParcel.aidl b/services/mediaresourcemanager/aidl/android/media/ClientInfoParcel.aidl
new file mode 100644
index 0000000..eb4bc42
--- /dev/null
+++ b/services/mediaresourcemanager/aidl/android/media/ClientInfoParcel.aidl
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2023, 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.
+ */
+
+package android.media;
+
+/**
+ * Description of a Client(codec) information.
+ *
+ * {@hide}
+ */
+parcelable ClientInfoParcel {
+ /**
+ * The PID of the client process.
+ */
+ int pid = -1;
+
+ /**
+ * The UID of the client process.
+ */
+ int uid = -1;
+
+ /**
+ * The ID of the client.
+ */
+ long id = 0;
+
+ /**
+ * Name of the resource associated with the client.
+ */
+ @utf8InCpp String name;
+}
diff --git a/services/mediaresourcemanager/aidl/android/media/IResourceManagerService.aidl b/services/mediaresourcemanager/aidl/android/media/IResourceManagerService.aidl
index 7a0a50f..30ad41b 100644
--- a/services/mediaresourcemanager/aidl/android/media/IResourceManagerService.aidl
+++ b/services/mediaresourcemanager/aidl/android/media/IResourceManagerService.aidl
@@ -19,6 +19,7 @@
import android.media.IResourceManagerClient;
import android.media.MediaResourceParcel;
import android.media.MediaResourcePolicyParcel;
+import android.media.ClientInfoParcel;
/**
* ResourceManagerService interface that keeps track of media resource
@@ -44,46 +45,40 @@
/**
* Add a client to a process with a list of resources.
*
- * @param pid pid of the client.
- * @param uid uid of the client.
- * @param clientId an identifier that uniquely identifies the client within the pid.
+ * @param clientInfo info of the calling client.
* @param client interface for the ResourceManagerService to call the client.
* @param resources an array of resources to be added.
*/
void addResource(
- int pid,
- int uid,
- long clientId,
+ in ClientInfoParcel clientInfo,
IResourceManagerClient client,
in MediaResourceParcel[] resources);
/**
* Remove the listed resources from a client.
*
- * @param pid pid from which the list of resources will be removed.
- * @param clientId clientId within the pid from which the list of resources will be removed.
+ * @param clientInfo info of the calling client.
* @param resources an array of resources to be removed from the client.
*/
- void removeResource(int pid, long clientId, in MediaResourceParcel[] resources);
+ void removeResource(in ClientInfoParcel clientInfo, in MediaResourceParcel[] resources);
/**
* Remove all resources from a client.
*
- * @param pid pid from which the client's resources will be removed.
- * @param clientId clientId within the pid that will be removed.
+ * @param clientInfo info of the calling client.
*/
- void removeClient(int pid, long clientId);
+ void removeClient(in ClientInfoParcel clientInfo);
/**
* Tries to reclaim resource from processes with lower priority than the
* calling process according to the requested resources.
*
- * @param callingPid pid of the calling process.
+ * @param clientInfo info of the calling client.
* @param resources an array of resources to be reclaimed.
*
* @return true if the reclaim was successful and false otherwise.
*/
- boolean reclaimResource(int callingPid, in MediaResourceParcel[] resources);
+ boolean reclaimResource(in ClientInfoParcel clientInfo, in MediaResourceParcel[] resources);
/**
* Override the pid of original calling process with the pid of the process
@@ -120,10 +115,9 @@
/**
* Mark a client for pending removal
*
- * @param pid pid from which the client's resources will be removed.
- * @param clientId clientId within the pid that will be removed.
+ * @param clientInfo info of the calling client.
*/
- void markClientForPendingRemoval(int pid, long clientId);
+ void markClientForPendingRemoval(in ClientInfoParcel clientInfo);
/**
* Reclaim resources from clients pending removal, if any.
diff --git a/services/mediaresourcemanager/fuzzer/Android.bp b/services/mediaresourcemanager/fuzzer/Android.bp
index 81c85e5..1d7f14f 100644
--- a/services/mediaresourcemanager/fuzzer/Android.bp
+++ b/services/mediaresourcemanager/fuzzer/Android.bp
@@ -41,6 +41,9 @@
"libbinder_ndk",
"libmedia",
"libutils",
+ "libstats_media_metrics",
+ "libstatspull",
+ "libstatssocket",
],
fuzz_config: {
cc: [
diff --git a/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
index e4aaea0..5c2fef9 100644
--- a/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
+++ b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
@@ -135,11 +135,15 @@
};
struct TestClient : public BnResourceManagerClient {
- TestClient(int pid, const shared_ptr<ResourceManagerService>& service)
- : mReclaimed(false), mPid(pid), mService(service) {}
+ TestClient(int pid, int uid, const shared_ptr<ResourceManagerService>& service)
+ : mReclaimed(false), mPid(pid), mUid(uid), mService(service) {}
Status reclaimResource(bool* aidlReturn) override {
- mService->removeClient(mPid, getId(ref<TestClient>()));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(ref<TestClient>()),
+ .name = ""};
+ mService->removeClient(clientInfo);
mReclaimed = true;
*aidlReturn = true;
return Status::ok();
@@ -155,6 +159,7 @@
private:
bool mReclaimed;
int mPid;
+ int mUid;
shared_ptr<ResourceManagerService> mService;
DISALLOW_EVIL_CONSTRUCTORS(TestClient);
};
@@ -176,9 +181,12 @@
static void* addResource(void* arg) {
resourceThreadArgs* tArgs = (resourceThreadArgs*)arg;
if (tArgs) {
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(tArgs->pid),
+ .uid = static_cast<int32_t>(tArgs->uid),
+ .id = tArgs->testClientId,
+ .name = ""};
(tArgs->service)
- ->addResource(tArgs->pid, tArgs->uid, tArgs->testClientId, tArgs->testClient,
- tArgs->mediaResource);
+ ->addResource(clientInfo, tArgs->testClient, tArgs->mediaResource);
}
return nullptr;
}
@@ -187,10 +195,14 @@
resourceThreadArgs* tArgs = (resourceThreadArgs*)arg;
if (tArgs) {
bool result;
- (tArgs->service)->markClientForPendingRemoval(tArgs->pid, tArgs->testClientId);
- (tArgs->service)->removeResource(tArgs->pid, tArgs->testClientId, tArgs->mediaResource);
- (tArgs->service)->reclaimResource(tArgs->pid, tArgs->mediaResource, &result);
- (tArgs->service)->removeClient(tArgs->pid, tArgs->testClientId);
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(tArgs->pid),
+ .uid = static_cast<int32_t>(tArgs->uid),
+ .id = tArgs->testClientId,
+ .name = ""};
+ (tArgs->service)->markClientForPendingRemoval(clientInfo);
+ (tArgs->service)->removeResource(clientInfo, tArgs->mediaResource);
+ (tArgs->service)->reclaimResource(clientInfo, tArgs->mediaResource, &result);
+ (tArgs->service)->removeClient(clientInfo);
(tArgs->service)->overridePid(tArgs->pid, tArgs->pid - 1);
}
return nullptr;
@@ -240,7 +252,8 @@
uint64_t mediaResourceValue = mFuzzedDataProvider->ConsumeIntegral<uint64_t>();
threadArgs[k].service = mService;
shared_ptr<IResourceManagerClient> testClient =
- ::ndk::SharedRefBase::make<TestClient>(threadArgs[k].pid, mService);
+ ::ndk::SharedRefBase::make<TestClient>(threadArgs[k].pid, threadArgs[k].uid,
+ mService);
threadArgs[k].testClient = testClient;
threadArgs[k].testClientId = getId(testClient);
mediaResource[k].push_back(MediaResource(static_cast<MedResType>(mediaResourceType),
@@ -258,7 +271,7 @@
// No resource was added with pid = 0
int32_t pidZero = 0;
shared_ptr<IResourceManagerClient> testClient =
- ::ndk::SharedRefBase::make<TestClient>(pidZero, mService);
+ ::ndk::SharedRefBase::make<TestClient>(pidZero, 0, mService);
int32_t mediaResourceType =
mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(kMinResourceType, kMaxResourceType);
int32_t mediaResourceSubType =
@@ -269,9 +282,13 @@
static_cast<MedResSubType>(mediaResourceSubType),
mediaResourceValue));
bool result;
- mService->reclaimResource(pidZero, mediaRes, &result);
- mService->removeResource(pidZero, getId(testClient), mediaRes);
- mService->removeClient(pidZero, getId(testClient));
+ ClientInfoParcel pidZeroClient{.pid = static_cast<int32_t>(pidZero),
+ .uid = static_cast<int32_t>(0),
+ .id = getId(testClient),
+ .name = ""};
+ mService->reclaimResource(pidZeroClient, mediaRes, &result);
+ mService->removeResource(pidZeroClient, mediaRes);
+ mService->removeClient(pidZeroClient);
}
void ResourceManagerServiceFuzzer::setServiceLog() {
diff --git a/services/mediaresourcemanager/test/Android.bp b/services/mediaresourcemanager/test/Android.bp
index 618626f..60bb8c3 100644
--- a/services/mediaresourcemanager/test/Android.bp
+++ b/services/mediaresourcemanager/test/Android.bp
@@ -19,6 +19,9 @@
"liblog",
"libmedia",
"libutils",
+ "libstats_media_metrics",
+ "libstatspull",
+ "libstatssocket",
],
include_dirs: [
"frameworks/av/include",
@@ -64,6 +67,9 @@
"liblog",
"libmedia",
"libutils",
+ "libstats_media_metrics",
+ "libstatspull",
+ "libstatssocket",
],
include_dirs: [
"frameworks/av/include",
diff --git a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
index 5bf44ce..8194e23 100644
--- a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
+++ b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
@@ -122,11 +122,15 @@
struct TestClient : public BnResourceManagerClient {
- TestClient(int pid, const std::shared_ptr<ResourceManagerService> &service)
- : mPid(pid), mService(service) {}
+ TestClient(int pid, int uid, const std::shared_ptr<ResourceManagerService> &service)
+ : mPid(pid), mUid(uid), mService(service) {}
Status reclaimResource(bool* _aidl_return) override {
- mService->removeClient(mPid, getId(ref<TestClient>()));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(ref<TestClient>()),
+ .name = "none"};
+ mService->removeClient(clientInfo);
mWasReclaimResourceCalled = true;
*_aidl_return = true;
return Status::ok();
@@ -148,6 +152,7 @@
private:
bool mWasReclaimResourceCalled = false;
int mPid;
+ int mUid;
std::shared_ptr<ResourceManagerService> mService;
DISALLOW_EVIL_CONSTRUCTORS(TestClient);
};
@@ -196,13 +201,13 @@
: mSystemCB(new TestSystemCallback()),
mService(::ndk::SharedRefBase::make<ResourceManagerService>(
new TestProcessInfo, mSystemCB)),
- mTestClient1(::ndk::SharedRefBase::make<TestClient>(kTestPid1, mService)),
- mTestClient2(::ndk::SharedRefBase::make<TestClient>(kTestPid2, mService)),
- mTestClient3(::ndk::SharedRefBase::make<TestClient>(kTestPid2, mService)) {
+ mTestClient1(::ndk::SharedRefBase::make<TestClient>(kTestPid1, kTestUid1, mService)),
+ mTestClient2(::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, mService)),
+ mTestClient3(::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, mService)) {
}
- std::shared_ptr<IResourceManagerClient> createTestClient(int pid) {
- return ::ndk::SharedRefBase::make<TestClient>(pid, mService);
+ std::shared_ptr<IResourceManagerClient> createTestClient(int pid, int uid) {
+ return ::ndk::SharedRefBase::make<TestClient>(pid, uid, mService);
}
sp<TestSystemCallback> mSystemCB;
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index 8739c3b..41cccb8 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -98,24 +98,36 @@
// kTestPid1 mTestClient1
std::vector<MediaResourceParcel> resources1;
resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ mService->addResource(client1Info, mTestClient1, resources1);
resources1.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
std::vector<MediaResourceParcel> resources11;
resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
+ mService->addResource(client1Info, mTestClient1, resources11);
// kTestPid2 mTestClient2
std::vector<MediaResourceParcel> resources2;
resources2.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
resources2.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 300));
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+ mService->addResource(client2Info, mTestClient2, resources2);
// kTestPid2 mTestClient3
std::vector<MediaResourceParcel> resources3;
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
+ mService->addResource(client3Info, mTestClient3, resources3);
resources3.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
resources3.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 100));
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
+ mService->addResource(client3Info, mTestClient3, resources3);
const PidResourceInfosMap &map = mService->mMap;
EXPECT_EQ(2u, map.size());
@@ -138,7 +150,11 @@
std::vector<MediaResourceParcel> resources1;
resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, -100));
resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, -100));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ mService->addResource(client1Info, mTestClient1, resources1);
// Expected result:
// 1) the client should have been added;
@@ -155,11 +171,11 @@
resources1.clear();
resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MAX));
resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MAX));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
resources1.clear();
resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, 10));
resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 10));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
// Expected result:
// Both values should saturate to INT64_MAX
@@ -170,7 +186,7 @@
resources1.clear();
resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, -10));
resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, -10));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
// Expected result:
// 1) DrmSession resource should allow negative value addition, and value should drop accordingly
@@ -182,7 +198,7 @@
resources1.clear();
resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MIN));
expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MIN));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
// Expected result:
// 1) DrmSession resource value should drop to 0, but the entry shouldn't be removed.
@@ -228,11 +244,15 @@
// kTestPid1 mTestClient1
std::vector<MediaResourceParcel> resources1;
resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ mService->addResource(client1Info, mTestClient1, resources1);
std::vector<MediaResourceParcel> resources11;
resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
+ mService->addResource(client1Info, mTestClient1, resources11);
const PidResourceInfosMap &map = mService->mMap;
EXPECT_EQ(1u, map.size());
@@ -243,7 +263,7 @@
// test adding existing types to combine values
resources1.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 100));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
std::vector<MediaResourceParcel> expected;
expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 2));
@@ -253,7 +273,7 @@
// test adding new types (including types that differs only in subType)
resources11.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
resources11.push_back(MediaResource(MediaResource::Type::kSecureCodec, MediaResource::SubType::kVideoCodec, 1));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
+ mService->addResource(client1Info, mTestClient1, resources11);
expected.clear();
expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 2));
@@ -267,11 +287,15 @@
// kTestPid1 mTestClient1
std::vector<MediaResourceParcel> resources1;
resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ mService->addResource(client1Info, mTestClient1, resources1);
std::vector<MediaResourceParcel> resources11;
resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
+ mService->addResource(client1Info, mTestClient1, resources11);
const PidResourceInfosMap &map = mService->mMap;
EXPECT_EQ(1u, map.size());
@@ -282,7 +306,7 @@
// test partial removal
resources11[0].value = 100;
- mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
+ mService->removeResource(client1Info, resources11);
std::vector<MediaResourceParcel> expected;
expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
@@ -291,13 +315,13 @@
// test removal request with negative value, should be ignored
resources11[0].value = -10000;
- mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
+ mService->removeResource(client1Info, resources11);
expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
// test complete removal with overshoot value
resources11[0].value = 1000;
- mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
+ mService->removeResource(client1Info, resources11);
expected.clear();
expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
@@ -317,19 +341,35 @@
mService->mSupportsSecureWithNonSecureCodec = true;
// priority too low to reclaim resource
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = 0,
+ .name = "none"};
+ CHECK_STATUS_FALSE(mService->reclaimResource(clientInfo, resources, &result));
// override Low Priority Pid with High Priority Pid
mService->overridePid(kLowPriorityPid, kHighPriorityPid);
- CHECK_STATUS_TRUE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(clientInfo, resources, &result));
// restore Low Priority Pid
mService->overridePid(kLowPriorityPid, -1);
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(clientInfo, resources, &result));
}
}
void testMarkClientForPendingRemoval() {
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
{
addResource();
mService->mSupportsSecureWithNonSecureCodec = true;
@@ -338,24 +378,24 @@
resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
// Remove low priority clients
- mService->removeClient(kTestPid1, getId(mTestClient1));
+ mService->removeClient(client1Info);
// no lower priority client
- CHECK_STATUS_FALSE(mService->reclaimResource(kTestPid2, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(client2Info, resources, &result));
EXPECT_EQ(false, toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
- mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
+ mService->markClientForPendingRemoval(client2Info);
// client marked for pending removal from the same process got reclaimed
- CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(client2Info, resources, &result));
EXPECT_EQ(false, toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_EQ(true, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// clean up client 3 which still left
- mService->removeClient(kTestPid2, getId(mTestClient3));
+ mService->removeClient(client3Info);
}
{
@@ -365,30 +405,30 @@
std::vector<MediaResourceParcel> resources;
resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
- mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
+ mService->markClientForPendingRemoval(client2Info);
// client marked for pending removal from the same process got reclaimed
// first, even though there are lower priority process
- CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(client2Info, resources, &result));
EXPECT_EQ(false, toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_EQ(true, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// lower priority client got reclaimed
- CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(client2Info, resources, &result));
EXPECT_EQ(true, toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// clean up client 3 which still left
- mService->removeClient(kTestPid2, getId(mTestClient3));
+ mService->removeClient(client3Info);
}
{
addResource();
mService->mSupportsSecureWithNonSecureCodec = true;
- mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
+ mService->markClientForPendingRemoval(client2Info);
// client marked for pending removal got reclaimed
EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
@@ -402,7 +442,7 @@
EXPECT_EQ(false, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
- mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient3));
+ mService->markClientForPendingRemoval(client3Info);
// client marked for pending removal got reclaimed
EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
@@ -411,14 +451,18 @@
EXPECT_EQ(true, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// clean up client 1 which still left
- mService->removeClient(kTestPid1, getId(mTestClient1));
+ mService->removeClient(client1Info);
}
}
void testRemoveClient() {
addResource();
- mService->removeClient(kTestPid2, getId(mTestClient2));
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+ mService->removeClient(client2Info);
const PidResourceInfosMap &map = mService->mMap;
EXPECT_EQ(2u, map.size());
@@ -437,11 +481,12 @@
MediaResource::SubType subType = MediaResource::SubType::kUnspecifiedSubType;
Vector<std::shared_ptr<IResourceManagerClient> > clients;
- EXPECT_FALSE(mService->getAllClients_l(kLowPriorityPid, type, subType, &clients));
+ PidUidVector idList;
+ EXPECT_FALSE(mService->getAllClients_l(kLowPriorityPid, type, subType, &idList, &clients));
// some higher priority process (e.g. kTestPid2) owns the resource, so getAllClients_l
// will fail.
- EXPECT_FALSE(mService->getAllClients_l(kMidPriorityPid, type, subType, &clients));
- EXPECT_TRUE(mService->getAllClients_l(kHighPriorityPid, type, subType, &clients));
+ EXPECT_FALSE(mService->getAllClients_l(kMidPriorityPid, type, subType, &idList, &clients));
+ EXPECT_TRUE(mService->getAllClients_l(kHighPriorityPid, type, subType, &idList, &clients));
EXPECT_EQ(2u, clients.size());
// (OK to require ordering in clients[], as the pid map is sorted)
@@ -454,6 +499,19 @@
resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
resources.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 150));
+ ClientInfoParcel lowPriorityClient{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ ClientInfoParcel midPriorityClient{.pid = static_cast<int32_t>(kMidPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+
// ### secure codec can't coexist and secure codec can coexist with non-secure codec ###
{
addResource();
@@ -461,23 +519,23 @@
mService->mSupportsSecureWithNonSecureCodec = true;
// priority too low
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
- CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(midPriorityClient, resources, &result));
// reclaim all secure codecs
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim one largest graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// nothing left
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
}
// ### secure codecs can't coexist and secure codec can't coexist with non-secure codec ###
@@ -487,17 +545,17 @@
mService->mSupportsSecureWithNonSecureCodec = false;
// priority too low
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
- CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(midPriorityClient, resources, &result));
// reclaim all secure and non-secure codecs
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// nothing left
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
}
@@ -508,29 +566,29 @@
mService->mSupportsSecureWithNonSecureCodec = false;
// priority too low
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
- CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(midPriorityClient, resources, &result));
// reclaim all non-secure codecs
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim one largest graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim another largest graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// nothing left
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
}
// ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
@@ -540,28 +598,28 @@
mService->mSupportsSecureWithNonSecureCodec = true;
// priority too low
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
// one largest graphic memory from lowest process got reclaimed
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim another graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim another graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// nothing left
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
}
// ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
@@ -573,20 +631,20 @@
std::vector<MediaResourceParcel> resources;
resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
// secure codec from lowest process got reclaimed
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim another secure codec from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// no more secure codec, non-secure codec will be reclaimed.
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
@@ -598,29 +656,42 @@
resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
resources.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 150));
+ ClientInfoParcel lowPriorityClient{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ ClientInfoParcel midPriorityClient{.pid = static_cast<int32_t>(kMidPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+
// ### secure codec can't coexist with non-secure codec ###
{
addResource();
mService->mSupportsSecureWithNonSecureCodec = false;
// priority too low
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
- CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(midPriorityClient, resources, &result));
// reclaim all secure codecs
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim one graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// nothing left
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
}
@@ -630,28 +701,28 @@
mService->mSupportsSecureWithNonSecureCodec = true;
// priority too low
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
// one largest graphic memory from lowest process got reclaimed
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim another graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim another graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// nothing left
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
}
// ### secure codec can coexist with non-secure codec ###
@@ -662,20 +733,24 @@
std::vector<MediaResourceParcel> resources;
resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
// one non secure codec from lowest process got reclaimed
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// no more non-secure codec, secure codec from lowest priority process will be reclaimed
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// clean up client 3 which still left
- mService->removeClient(kTestPid2, getId(mTestClient3));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
+ mService->removeClient(clientInfo);
}
}
@@ -683,15 +758,16 @@
MediaResource::Type type = MediaResource::Type::kGraphicMemory;
MediaResource::SubType subType = MediaResource::SubType::kUnspecifiedSubType;
std::shared_ptr<IResourceManagerClient> client;
+ PidUidVector idList;
EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, subType,
- &client));
+ &idList, &client));
addResource();
EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kLowPriorityPid, type, subType,
- &client));
+ &idList, &client));
EXPECT_TRUE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, subType,
- &client));
+ &idList, &client));
// kTestPid1 is the lowest priority process with MediaResource::Type::kGraphicMemory.
// mTestClient1 has the largest MediaResource::Type::kGraphicMemory within kTestPid1.
@@ -737,33 +813,41 @@
// new client request should cause VIDEO_ON
std::vector<MediaResourceParcel> resources1;
resources1.push_back(MediaResource(MediaResource::Type::kBattery, MediaResource::SubType::kVideoCodec, 1));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ mService->addResource(client1Info, mTestClient1, resources1);
EXPECT_EQ(2u, mSystemCB->eventCount());
EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid1}), mSystemCB->lastEvent());
// each client should only cause 1 VIDEO_ON
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
EXPECT_EQ(2u, mSystemCB->eventCount());
// new client request should cause VIDEO_ON
std::vector<MediaResourceParcel> resources2;
resources2.push_back(MediaResource(MediaResource::Type::kBattery, MediaResource::SubType::kVideoCodec, 2));
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+ mService->addResource(client2Info, mTestClient2, resources2);
EXPECT_EQ(3u, mSystemCB->eventCount());
EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid2}), mSystemCB->lastEvent());
// partially remove mTestClient1's request, shouldn't be any VIDEO_OFF
- mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
+ mService->removeResource(client1Info, resources1);
EXPECT_EQ(3u, mSystemCB->eventCount());
// remove mTestClient1's request, should be VIDEO_OFF for kTestUid1
// (use resource2 to test removing more instances than previously requested)
- mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
+ mService->removeResource(client1Info, resources2);
EXPECT_EQ(4u, mSystemCB->eventCount());
EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid1}), mSystemCB->lastEvent());
// remove mTestClient2, should be VIDEO_OFF for kTestUid2
- mService->removeClient(kTestPid2, getId(mTestClient2));
+ mService->removeClient(client2Info);
EXPECT_EQ(5u, mSystemCB->eventCount());
EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid2}), mSystemCB->lastEvent());
}
@@ -776,32 +860,40 @@
// new client request should cause CPUSET_ENABLE
std::vector<MediaResourceParcel> resources1;
resources1.push_back(MediaResource(MediaResource::Type::kCpuBoost, 1));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ mService->addResource(client1Info, mTestClient1, resources1);
EXPECT_EQ(2u, mSystemCB->eventCount());
EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
// each client should only cause 1 CPUSET_ENABLE
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
EXPECT_EQ(2u, mSystemCB->eventCount());
// new client request should cause CPUSET_ENABLE
std::vector<MediaResourceParcel> resources2;
resources2.push_back(MediaResource(MediaResource::Type::kCpuBoost, 2));
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+ mService->addResource(client2Info, mTestClient2, resources2);
EXPECT_EQ(3u, mSystemCB->eventCount());
EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
// remove mTestClient2 should not cause CPUSET_DISABLE, mTestClient1 still active
- mService->removeClient(kTestPid2, getId(mTestClient2));
+ mService->removeClient(client2Info);
EXPECT_EQ(3u, mSystemCB->eventCount());
// remove 1 cpuboost from mTestClient1, should not be CPUSET_DISABLE (still 1 left)
- mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
+ mService->removeResource(client1Info, resources1);
EXPECT_EQ(3u, mSystemCB->eventCount());
// remove 2 cpuboost from mTestClient1, should be CPUSET_DISABLE
// (use resource2 to test removing more than previously requested)
- mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
+ mService->removeResource(client1Info, resources2);
EXPECT_EQ(4u, mSystemCB->eventCount());
EXPECT_EQ(EventType::CPUSET_DISABLE, mSystemCB->lastEventType());
}
@@ -814,22 +906,32 @@
std::vector<MediaResourceParcel> audioImageResources;
audioImageResources.push_back(createNonSecureAudioCodecResource());
audioImageResources.push_back(createNonSecureImageCodecResource());
- mService->addResource(kLowPriorityPid, kTestUid1, getId(audioImageTestClient),
- audioImageTestClient, audioImageResources);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(audioImageTestClient),
+ .name = "none"};
+ mService->addResource(client1Info, audioImageTestClient, audioImageResources);
// Fail to reclaim a video codec resource
std::vector<MediaResourceParcel> reclaimResources;
reclaimResources.push_back(createNonSecureVideoCodecResource());
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Now add a video codec resource
std::vector<MediaResourceParcel> videoResources;
videoResources.push_back(createNonSecureVideoCodecResource());
- mService->addResource(kLowPriorityPid, kTestUid1, getId(videoTestClient), videoTestClient,
- videoResources);
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(videoTestClient),
+ .name = "none"};
+ mService->addResource(client2Info, videoTestClient, videoResources);
// Verify that the newly-created video codec resource can be reclaimed
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Verify that the audio and image resources are untouched
EXPECT_FALSE(toTestClient(audioImageTestClient)->checkIfReclaimedAndReset());
@@ -845,22 +947,32 @@
std::vector<MediaResourceParcel> videoImageResources;
videoImageResources.push_back(createNonSecureVideoCodecResource());
videoImageResources.push_back(createNonSecureImageCodecResource());
- mService->addResource(kLowPriorityPid, kTestUid1, getId(videoImageTestClient),
- videoImageTestClient, videoImageResources);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(videoImageTestClient),
+ .name = "none"};
+ mService->addResource(client1Info, videoImageTestClient, videoImageResources);
// Fail to reclaim an audio codec resource
std::vector<MediaResourceParcel> reclaimResources;
reclaimResources.push_back(createNonSecureAudioCodecResource());
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Now add an audio codec resource
std::vector<MediaResourceParcel> audioResources;
audioResources.push_back(createNonSecureAudioCodecResource());
- mService->addResource(kLowPriorityPid, kTestUid2, getId(audioTestClient), audioTestClient,
- audioResources);
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(audioTestClient),
+ .name = "none"};
+ mService->addResource(client2Info, audioTestClient, audioResources);
// Verify that the newly-created audio codec resource can be reclaimed
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Verify that the video and image resources are untouched
EXPECT_FALSE(toTestClient(videoImageTestClient)->checkIfReclaimedAndReset());
@@ -876,22 +988,32 @@
std::vector<MediaResourceParcel> videoAudioResources;
videoAudioResources.push_back(createNonSecureVideoCodecResource());
videoAudioResources.push_back(createNonSecureAudioCodecResource());
- mService->addResource(kLowPriorityPid, kTestUid1, getId(videoAudioTestClient),
- videoAudioTestClient, videoAudioResources);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(videoAudioTestClient),
+ .name = "none"};
+ mService->addResource(client1Info, videoAudioTestClient, videoAudioResources);
// Fail to reclaim an image codec resource
std::vector<MediaResourceParcel> reclaimResources;
reclaimResources.push_back(createNonSecureImageCodecResource());
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Now add an image codec resource
std::vector<MediaResourceParcel> imageResources;
imageResources.push_back(createNonSecureImageCodecResource());
- mService->addResource(kLowPriorityPid, kTestUid2, getId(imageTestClient), imageTestClient,
- imageResources);
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(imageTestClient),
+ .name = "none"};
+ mService->addResource(client2Info, imageTestClient, imageResources);
// Verify that the newly-created image codec resource can be reclaimed
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Verify that the video and audio resources are untouched
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
@@ -901,20 +1023,27 @@
void testReclaimResources_whenPartialResourceMatch_reclaims() {
const int onlyUid = kTestUid1;
- const auto onlyClient = createTestClient(kLowPriorityPid);
+ const auto onlyClient = createTestClient(kLowPriorityPid, onlyUid);
std::vector<MediaResourceParcel> ownedResources;
ownedResources.push_back(createNonSecureVideoCodecResource());
ownedResources.push_back(createGraphicMemoryResource(100));
- mService->addResource(kLowPriorityPid, onlyUid, getId(onlyClient), onlyClient,
- ownedResources);
+ ClientInfoParcel onlyClientInfo{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(onlyClient),
+ .name = "none"};
+ mService->addResource(onlyClientInfo, onlyClient, ownedResources);
// Reclaim an image codec instead of the video codec that is owned, but also reclaim
// graphics memory, which will trigger the reclaim.
std::vector<MediaResourceParcel> reclaimResources;
reclaimResources.push_back(createNonSecureImageCodecResource());
reclaimResources.push_back(createGraphicMemoryResource(100));
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Verify that the video codec resources (including the needed graphic memory) is reclaimed
EXPECT_TRUE(toTestClient(onlyClient)->checkIfReclaimedAndReset());
@@ -926,200 +1055,278 @@
const int onlyUid = kTestUid1;
// secure video codec
- const auto smallSecureVideoMarkedClient = createTestClient(onlyPid);
- const auto largeSecureVideoMarkedClient = createTestClient(onlyPid);
- const auto largestSecureVideoActiveClient = createTestClient(onlyPid);
+ const auto smallSecureVideoMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeSecureVideoMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestSecureVideoActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientA{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallSecureVideoMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientB{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeSecureVideoMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientC{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestSecureVideoActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createSecureVideoCodecResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallSecureVideoMarkedClient),
- smallSecureVideoMarkedClient, resources);
+ mService->addResource(clientA, smallSecureVideoMarkedClient, resources);
resources.clear();
resources.push_back(createSecureVideoCodecResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeSecureVideoMarkedClient),
- largeSecureVideoMarkedClient, resources);
+ mService->addResource(clientB, largeSecureVideoMarkedClient, resources);
resources.clear();
resources.push_back(createSecureVideoCodecResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestSecureVideoActiveClient),
- largestSecureVideoActiveClient, resources);
+ mService->addResource(clientC, largestSecureVideoActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallSecureVideoMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeSecureVideoMarkedClient));
+ mService->markClientForPendingRemoval(clientA);
+ mService->markClientForPendingRemoval(clientB);
// don't mark the largest client
// non-secure video codec
- const auto smallNonSecureVideoMarkedClient = createTestClient(onlyPid);
- const auto largeNonSecureVideoMarkedClient = createTestClient(onlyPid);
- const auto largestNonSecureVideoActiveClient = createTestClient(onlyPid);
+ const auto smallNonSecureVideoMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeNonSecureVideoMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestNonSecureVideoActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientD{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallNonSecureVideoMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientE{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeNonSecureVideoMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientF{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestNonSecureVideoActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createNonSecureVideoCodecResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallNonSecureVideoMarkedClient),
- smallNonSecureVideoMarkedClient, resources);
+ mService->addResource(clientD, smallNonSecureVideoMarkedClient, resources);
resources.clear();
resources.push_back(createNonSecureVideoCodecResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeNonSecureVideoMarkedClient),
- largeNonSecureVideoMarkedClient, resources);
+ mService->addResource(clientE, largeNonSecureVideoMarkedClient, resources);
resources.clear();
resources.push_back(createNonSecureVideoCodecResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestNonSecureVideoActiveClient),
- largestNonSecureVideoActiveClient, resources);
+ mService->addResource(clientF, largestNonSecureVideoActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallNonSecureVideoMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeNonSecureVideoMarkedClient));
+ mService->markClientForPendingRemoval(clientD);
+ mService->markClientForPendingRemoval(clientE);
// don't mark the largest client
// secure audio codec
- const auto smallSecureAudioMarkedClient = createTestClient(onlyPid);
- const auto largeSecureAudioMarkedClient = createTestClient(onlyPid);
- const auto largestSecureAudioActiveClient = createTestClient(onlyPid);
+ const auto smallSecureAudioMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeSecureAudioMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestSecureAudioActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientG{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallSecureAudioMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientH{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeSecureAudioMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientI{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestSecureVideoActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createSecureAudioCodecResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallSecureAudioMarkedClient),
- smallSecureAudioMarkedClient, resources);
+ mService->addResource(clientG, smallSecureAudioMarkedClient, resources);
resources.clear();
resources.push_back(createSecureAudioCodecResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeSecureAudioMarkedClient),
- largeSecureAudioMarkedClient, resources);
+ mService->addResource(clientH, largeSecureAudioMarkedClient, resources);
resources.clear();
resources.push_back(createSecureAudioCodecResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestSecureVideoActiveClient),
- largestSecureVideoActiveClient, resources);
+ mService->addResource(clientI, largestSecureVideoActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallSecureAudioMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeSecureAudioMarkedClient));
+ mService->markClientForPendingRemoval(clientG);
+ mService->markClientForPendingRemoval(clientH);
// don't mark the largest client
// non-secure audio codec
- const auto smallNonSecureAudioMarkedClient = createTestClient(onlyPid);
- const auto largeNonSecureAudioMarkedClient = createTestClient(onlyPid);
- const auto largestNonSecureAudioActiveClient = createTestClient(onlyPid);
+ const auto smallNonSecureAudioMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeNonSecureAudioMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestNonSecureAudioActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientJ{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallNonSecureAudioMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientK{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeNonSecureAudioMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientL{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestNonSecureAudioActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createNonSecureAudioCodecResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallNonSecureAudioMarkedClient),
- smallNonSecureAudioMarkedClient, resources);
+ mService->addResource(clientJ, smallNonSecureAudioMarkedClient, resources);
resources.clear();
resources.push_back(createNonSecureAudioCodecResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeNonSecureAudioMarkedClient),
- largeNonSecureAudioMarkedClient, resources);
+ mService->addResource(clientK, largeNonSecureAudioMarkedClient, resources);
resources.clear();
resources.push_back(createNonSecureAudioCodecResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestNonSecureAudioActiveClient),
- largestNonSecureAudioActiveClient, resources);
+ mService->addResource(clientL, largestNonSecureAudioActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallNonSecureAudioMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeNonSecureAudioMarkedClient));
+ mService->markClientForPendingRemoval(clientJ);
+ mService->markClientForPendingRemoval(clientK);
// don't mark the largest client
// secure image codec
- const auto smallSecureImageMarkedClient = createTestClient(onlyPid);
- const auto largeSecureImageMarkedClient = createTestClient(onlyPid);
- const auto largestSecureImageActiveClient = createTestClient(onlyPid);
+ const auto smallSecureImageMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeSecureImageMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestSecureImageActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientM{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallSecureImageMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientN{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeSecureImageMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientO{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestSecureImageActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createSecureImageCodecResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallSecureImageMarkedClient),
- smallSecureImageMarkedClient, resources);
+ mService->addResource(clientM, smallSecureImageMarkedClient, resources);
resources.clear();
resources.push_back(createSecureImageCodecResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeSecureImageMarkedClient),
- largeSecureImageMarkedClient, resources);
+ mService->addResource(clientN, largeSecureImageMarkedClient, resources);
resources.clear();
resources.push_back(createSecureImageCodecResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestSecureImageActiveClient),
- largestSecureImageActiveClient, resources);
+ mService->addResource(clientO, largestSecureImageActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallSecureImageMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeSecureImageMarkedClient));
+ mService->markClientForPendingRemoval(clientM);
+ mService->markClientForPendingRemoval(clientN);
// don't mark the largest client
// non-secure image codec
- const auto smallNonSecureImageMarkedClient = createTestClient(onlyPid);
- const auto largeNonSecureImageMarkedClient = createTestClient(onlyPid);
- const auto largestNonSecureImageActiveClient = createTestClient(onlyPid);
+ const auto smallNonSecureImageMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeNonSecureImageMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestNonSecureImageActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientP{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallNonSecureImageMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientQ{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeNonSecureImageMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientR{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestNonSecureImageActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createNonSecureImageCodecResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallNonSecureImageMarkedClient),
- smallNonSecureImageMarkedClient, resources);
+ mService->addResource(clientP, smallNonSecureImageMarkedClient, resources);
resources.clear();
resources.push_back(createNonSecureImageCodecResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeNonSecureImageMarkedClient),
- largeNonSecureImageMarkedClient, resources);
+ mService->addResource(clientQ, largeNonSecureImageMarkedClient, resources);
resources.clear();
resources.push_back(createNonSecureImageCodecResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestNonSecureImageActiveClient),
- largestNonSecureImageActiveClient, resources);
+ mService->addResource(clientR, largestNonSecureImageActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallNonSecureImageMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeNonSecureImageMarkedClient));
+ mService->markClientForPendingRemoval(clientP);
+ mService->markClientForPendingRemoval(clientQ);
// don't mark the largest client
// graphic memory
- const auto smallGraphicMemoryMarkedClient = createTestClient(onlyPid);
- const auto largeGraphicMemoryMarkedClient = createTestClient(onlyPid);
- const auto largestGraphicMemoryActiveClient = createTestClient(onlyPid);
+ const auto smallGraphicMemoryMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeGraphicMemoryMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestGraphicMemoryActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientS{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallGraphicMemoryMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientT{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeGraphicMemoryMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientU{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestGraphicMemoryActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createGraphicMemoryResource(100));
- mService->addResource(onlyPid, onlyUid, getId(smallGraphicMemoryMarkedClient),
- smallGraphicMemoryMarkedClient, resources);
+ mService->addResource(clientS, smallGraphicMemoryMarkedClient, resources);
resources.clear();
resources.push_back(createGraphicMemoryResource(200));
- mService->addResource(onlyPid, onlyUid, getId(largeGraphicMemoryMarkedClient),
- largeGraphicMemoryMarkedClient, resources);
+ mService->addResource(clientT, largeGraphicMemoryMarkedClient, resources);
resources.clear();
resources.push_back(createGraphicMemoryResource(300));
- mService->addResource(onlyPid, onlyUid, getId(largestGraphicMemoryActiveClient),
- largestGraphicMemoryActiveClient, resources);
+ mService->addResource(clientU, largestGraphicMemoryActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallGraphicMemoryMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeGraphicMemoryMarkedClient));
+ mService->markClientForPendingRemoval(clientS);
+ mService->markClientForPendingRemoval(clientT);
// don't mark the largest client
// DRM session
- const auto smallDrmSessionMarkedClient = createTestClient(onlyPid);
- const auto largeDrmSessionMarkedClient = createTestClient(onlyPid);
- const auto largestDrmSessionActiveClient = createTestClient(onlyPid);
+ const auto smallDrmSessionMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeDrmSessionMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestDrmSessionActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientV{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallDrmSessionMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientW{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeDrmSessionMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientX{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestDrmSessionActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createDrmSessionResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallDrmSessionMarkedClient),
- smallDrmSessionMarkedClient, resources);
+ mService->addResource(clientV, smallDrmSessionMarkedClient, resources);
resources.clear();
resources.push_back(createDrmSessionResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeDrmSessionMarkedClient),
- largeDrmSessionMarkedClient, resources);
+ mService->addResource(clientW, largeDrmSessionMarkedClient, resources);
resources.clear();
resources.push_back(createDrmSessionResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestDrmSessionActiveClient),
- largestDrmSessionActiveClient, resources);
+ mService->addResource(clientX, largestDrmSessionActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallDrmSessionMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeDrmSessionMarkedClient));
+ mService->markClientForPendingRemoval(clientV);
+ mService->markClientForPendingRemoval(clientW);
// don't mark the largest client
// battery
- const auto batteryMarkedClient = createTestClient(onlyPid);
+ const auto batteryMarkedClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientY{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(batteryMarkedClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createBatteryResource());
- mService->addResource(onlyPid, onlyUid, getId(batteryMarkedClient),
- batteryMarkedClient, resources);
+ mService->addResource(clientY, batteryMarkedClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(batteryMarkedClient));
+ mService->markClientForPendingRemoval(clientY);
// CPU boost
- const auto cpuBoostMarkedClient = createTestClient(onlyPid);
+ const auto cpuBoostMarkedClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientZ{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(cpuBoostMarkedClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createCpuBoostResource());
- mService->addResource(onlyPid, onlyUid, getId(cpuBoostMarkedClient),
- cpuBoostMarkedClient, resources);
+ mService->addResource(clientZ, cpuBoostMarkedClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(cpuBoostMarkedClient));
+ mService->markClientForPendingRemoval(clientZ);
// now we expect that we only reclaim resources from the biggest marked client
EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(onlyPid).isOk());
diff --git a/services/mediaresourcemanager/test/ResourceObserverService_test.cpp b/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
index 003569d..a0d728c 100644
--- a/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
@@ -251,17 +251,31 @@
observables3 = {{MediaObservableType::kVideoSecureCodec, 1},
{MediaObservableType::kVideoNonSecureCodec, 1}};
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
std::vector<MediaResourceParcel> resources;
// Add secure video codec.
resources = {createSecureVideoCodecResource()};
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources);
+ mService->addResource(client1Info, mTestClient1, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
// Add non-secure video codec.
resources = {createNonSecureVideoCodecResource()};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources);
+ mService->addResource(client2Info, mTestClient2, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
@@ -269,7 +283,7 @@
// Add secure & non-secure video codecs.
resources = {createSecureVideoCodecResource(),
createNonSecureVideoCodecResource()};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+ mService->addResource(client3Info, mTestClient3, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3));
@@ -277,7 +291,7 @@
// Add additional audio codecs, should be ignored.
resources.push_back(createSecureAudioCodecResource());
resources.push_back(createNonSecureAudioCodecResource());
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources);
+ mService->addResource(client1Info, mTestClient1, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables3));
@@ -303,7 +317,11 @@
observables2 = {{MediaObservableType::kVideoNonSecureCodec, 3}};
observables3 = {{MediaObservableType::kVideoSecureCodec, 2},
{MediaObservableType::kVideoNonSecureCodec, 3}};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
+ mService->addResource(client3Info, mTestClient3, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3));
@@ -318,47 +336,61 @@
observables3 = {{MediaObservableType::kVideoSecureCodec, 1},
{MediaObservableType::kVideoNonSecureCodec, 1}};
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
std::vector<MediaResourceParcel> resources;
// Add secure video codec to client1.
resources = {createSecureVideoCodecResource()};
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources);
+ mService->addResource(client1Info, mTestClient1, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
// Remove secure video codec. observer 1&3 should receive updates.
- mService->removeResource(kTestPid1, getId(mTestClient1), resources);
+ mService->removeResource(client1Info, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Idle(kTestUid1, kTestPid1, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid1, kTestPid1, observables1));
// Remove secure video codec again, should have no event.
- mService->removeResource(kTestPid1, getId(mTestClient1), resources);
+ mService->removeResource(client1Info, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
// Remove client1, should have no event.
- mService->removeClient(kTestPid1, getId(mTestClient1));
+ mService->removeClient(client1Info);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
// Add non-secure video codec to client2.
resources = {createNonSecureVideoCodecResource()};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources);
+ mService->addResource(client2Info, mTestClient2, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
// Remove client2, observer 2&3 should receive updates.
- mService->removeClient(kTestPid2, getId(mTestClient2));
+ mService->removeClient(client2Info);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
// Remove non-secure codec after client2 removed, should have no event.
- mService->removeResource(kTestPid2, getId(mTestClient2), resources);
+ mService->removeResource(client2Info, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
// Remove client2 again, should have no event.
- mService->removeClient(kTestPid2, getId(mTestClient2));
+ mService->removeClient(client2Info);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
@@ -368,13 +400,13 @@
createNonSecureVideoCodecResource(),
createSecureAudioCodecResource(),
createNonSecureAudioCodecResource()};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+ mService->addResource(client3Info, mTestClient3, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3));
// Remove one audio codec, should have no event.
resources = {createSecureAudioCodecResource()};
- mService->removeResource(kTestPid2, getId(mTestClient3), resources);
+ mService->removeResource(client3Info, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
@@ -382,12 +414,12 @@
// removal should be reported.
resources = {createNonSecureAudioCodecResource(),
createSecureVideoCodecResource()};
- mService->removeResource(kTestPid2, getId(mTestClient3), resources);
+ mService->removeResource(client3Info, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables1));
// Remove client3 entirely. Non-secure video codec removal should be reported.
- mService->removeClient(kTestPid2, getId(mTestClient3));
+ mService->removeClient(client3Info);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
@@ -410,7 +442,12 @@
createNonSecureVideoCodecResource(4),
createSecureAudioCodecResource(),
createNonSecureAudioCodecResource()};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
+ mService->addResource(client3Info, mTestClient3, resources);
observables1 = {{MediaObservableType::kVideoSecureCodec, 1}};
observables2 = {{MediaObservableType::kVideoNonSecureCodec, 4}};
observables3 = {{MediaObservableType::kVideoSecureCodec, 1},
@@ -424,7 +461,7 @@
createSecureVideoCodecResource(),
createSecureVideoCodecResource(),
createNonSecureVideoCodecResource(2)};
- mService->removeResource(kTestPid2, getId(mTestClient3), resources);
+ mService->removeResource(client3Info, resources);
observables1 = {{MediaObservableType::kVideoSecureCodec, 1}};
observables2 = {{MediaObservableType::kVideoNonSecureCodec, 2}};
observables3 = {{MediaObservableType::kVideoSecureCodec, 1},
@@ -433,7 +470,7 @@
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables3));
// Remove client3 entirely. 2 non-secure video codecs removal should be reported.
- mService->removeClient(kTestPid2, getId(mTestClient3));
+ mService->removeClient(client3Info);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
@@ -465,13 +502,27 @@
// Add secure & non-secure video codecs.
resources = {createSecureVideoCodecResource(),
createNonSecureVideoCodecResource()};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
+ mService->addResource(client3Info, mTestClient3, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
// Remove secure & non-secure video codecs.
- mService->removeResource(kTestPid2, getId(mTestClient3), resources);
+ mService->removeResource(client3Info, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables1));
diff --git a/services/oboeservice/Android.bp b/services/oboeservice/Android.bp
index 80e4296..5076239 100644
--- a/services/oboeservice/Android.bp
+++ b/services/oboeservice/Android.bp
@@ -25,6 +25,10 @@
name: "libaaudioservice",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+
srcs: [
"AAudioClientTracker.cpp",
"AAudioCommandQueue.cpp",
@@ -70,7 +74,6 @@
"framework-permission-aidl-cpp",
"libaudioclient_aidl_conversion",
"packagemanager_aidl-cpp",
- "android.media.audio.common.types-V1-cpp",
],
export_shared_lib_headers: [
diff --git a/services/tuner/hidl/TunerHidlDvr.cpp b/services/tuner/hidl/TunerHidlDvr.cpp
index 1a619d5..3ea1eb1 100644
--- a/services/tuner/hidl/TunerHidlDvr.cpp
+++ b/services/tuner/hidl/TunerHidlDvr.cpp
@@ -72,7 +72,7 @@
AidlMQDesc aidlMQDesc;
unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(dvrMQDesc, &aidlMQDesc);
- *_aidl_return = move(aidlMQDesc);
+ *_aidl_return = std::move(aidlMQDesc);
return ::ndk::ScopedAStatus::ok();
}
diff --git a/services/tuner/hidl/TunerHidlFilter.cpp b/services/tuner/hidl/TunerHidlFilter.cpp
index fe74a5c..c82732b 100644
--- a/services/tuner/hidl/TunerHidlFilter.cpp
+++ b/services/tuner/hidl/TunerHidlFilter.cpp
@@ -139,7 +139,7 @@
AidlMQDesc aidlMQDesc;
unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(filterMQDesc, &aidlMQDesc);
- *_aidl_return = move(aidlMQDesc);
+ *_aidl_return = std::move(aidlMQDesc);
return ::ndk::ScopedAStatus::ok();
}
@@ -1084,8 +1084,8 @@
}
DemuxFilterEvent filterEvent;
- filterEvent.set<DemuxFilterEvent::media>(move(media));
- res.push_back(move(filterEvent));
+ filterEvent.set<DemuxFilterEvent::media>(std::move(media));
+ res.push_back(std::move(filterEvent));
}
}
@@ -1101,8 +1101,8 @@
section.dataLength = static_cast<int64_t>(sectionEvent.dataLength);
DemuxFilterEvent filterEvent;
- filterEvent.set<DemuxFilterEvent::section>(move(section));
- res.push_back(move(filterEvent));
+ filterEvent.set<DemuxFilterEvent::section>(std::move(section));
+ res.push_back(std::move(filterEvent));
}
}
@@ -1117,8 +1117,8 @@
pes.mpuSequenceNumber = static_cast<int32_t>(pesEvent.mpuSequenceNumber);
DemuxFilterEvent filterEvent;
- filterEvent.set<DemuxFilterEvent::pes>(move(pes));
- res.push_back(move(filterEvent));
+ filterEvent.set<DemuxFilterEvent::pes>(std::move(pes));
+ res.push_back(std::move(filterEvent));
}
}
@@ -1167,8 +1167,8 @@
}
DemuxFilterEvent filterEvent;
- filterEvent.set<DemuxFilterEvent::tsRecord>(move(tsRecord));
- res.push_back(move(filterEvent));
+ filterEvent.set<DemuxFilterEvent::tsRecord>(std::move(tsRecord));
+ res.push_back(std::move(filterEvent));
}
}
@@ -1194,8 +1194,8 @@
}
DemuxFilterEvent filterEvent;
- filterEvent.set<DemuxFilterEvent::mmtpRecord>(move(mmtpRecord));
- res.push_back(move(filterEvent));
+ filterEvent.set<DemuxFilterEvent::mmtpRecord>(std::move(mmtpRecord));
+ res.push_back(std::move(filterEvent));
}
}
@@ -1213,8 +1213,8 @@
download.dataLength = static_cast<int32_t>(downloadEvent.dataLength);
DemuxFilterEvent filterEvent;
- filterEvent.set<DemuxFilterEvent::download>(move(download));
- res.push_back(move(filterEvent));
+ filterEvent.set<DemuxFilterEvent::download>(std::move(download));
+ res.push_back(std::move(filterEvent));
}
}
@@ -1227,8 +1227,8 @@
ipPayload.dataLength = static_cast<int32_t>(ipPayloadEvent.dataLength);
DemuxFilterEvent filterEvent;
- filterEvent.set<DemuxFilterEvent::ipPayload>(move(ipPayload));
- res.push_back(move(filterEvent));
+ filterEvent.set<DemuxFilterEvent::ipPayload>(std::move(ipPayload));
+ res.push_back(std::move(filterEvent));
}
}
@@ -1245,8 +1245,8 @@
copy(descrData.begin(), descrData.end(), temi.descrData.begin());
DemuxFilterEvent filterEvent;
- filterEvent.set<DemuxFilterEvent::temi>(move(temi));
- res.push_back(move(filterEvent));
+ filterEvent.set<DemuxFilterEvent::temi>(std::move(temi));
+ res.push_back(std::move(filterEvent));
}
}
@@ -1268,15 +1268,15 @@
}
DemuxFilterEvent filterEvent;
- filterEvent.set<DemuxFilterEvent::monitorEvent>(move(monitor));
- res.push_back(move(filterEvent));
+ filterEvent.set<DemuxFilterEvent::monitorEvent>(std::move(monitor));
+ res.push_back(std::move(filterEvent));
}
void TunerHidlFilter::FilterCallback::getRestartEvent(
const vector<HidlDemuxFilterEventExt::Event>& eventsExt, vector<DemuxFilterEvent>& res) {
DemuxFilterEvent filterEvent;
filterEvent.set<DemuxFilterEvent::startId>(static_cast<int32_t>(eventsExt[0].startId()));
- res.push_back(move(filterEvent));
+ res.push_back(std::move(filterEvent));
}
} // namespace tuner
diff --git a/tools/OWNERS b/tools/OWNERS
new file mode 100644
index 0000000..7598c6f
--- /dev/null
+++ b/tools/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 1344
+essick@google.com
+
+# reliability builds mainline trains, so needs to manage these scripts
+include platform/frameworks/av/:/media/janitors/reliability_mainline_OWNERS
diff --git a/tools/mainline_hook_partial.sh b/tools/mainline_hook_partial.sh
index bd82315..cd3e579 100755
--- a/tools/mainline_hook_partial.sh
+++ b/tools/mainline_hook_partial.sh
Binary files differ
diff --git a/tools/mainline_hook_project.sh b/tools/mainline_hook_project.sh
index cb5fc44..1cc3b2b 100755
--- a/tools/mainline_hook_project.sh
+++ b/tools/mainline_hook_project.sh
@@ -17,7 +17,7 @@
# tunables
DEV_BRANCH=master
-MAINLINE_BRANCH=sc-mainline-prod
+MAINLINE_BRANCH=tm-mainline-prod
###
RED=$(tput setaf 1)