Merge "Revert "Use headers library for libvibrator""
diff --git a/OWNERS b/OWNERS
index 9989bf0..7f523a2 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,5 +1,7 @@
+chz@google.com
elaurent@google.com
etalvala@google.com
+hkuang@google.com
lajos@google.com
marcone@google.com
diff --git a/apex/Android.bp b/apex/Android.bp
index 6ba9cb9..bf91bf7 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -32,15 +32,21 @@
"liboggextractor",
"libwavextractor",
],
+ // Transcoding service only run with primary ABI.
+ binaries: [
+ "mediatranscoding",
+ ],
},
},
// JNI
native_shared_libs: ["libmediaparser-jni"],
compile_multilib: "both",
prebuilts: [
- "mediaextractor.policy",
"code_coverage.policy",
+ "com.android.media-mediatranscoding.rc",
"crash_dump.policy",
+ "mediaextractor.policy",
+ "media-linker-config",
],
key: "com.android.media.key",
certificate: ":com.android.media.certificate",
@@ -62,9 +68,6 @@
name: "com.android.media",
manifest: "manifest.json",
defaults: ["com.android.media-defaults"],
- prebuilts: [
- "media-linker-config",
- ],
}
linker_config {
@@ -89,6 +92,9 @@
binaries: [
"mediaswcodec",
],
+ native_shared_libs: [
+ "libstagefright_foundation",
+ ],
prebuilts: [
"com.android.media.swcodec-mediaswcodec.rc",
"com.android.media.swcodec-ld.config.txt",
@@ -97,7 +103,6 @@
"crash_dump.policy",
"mediaswcodec.xml",
],
- use_vendor: true,
key: "com.android.media.swcodec.key",
certificate: ":com.android.media.swcodec.certificate",
@@ -115,6 +120,13 @@
}
prebuilt_etc {
+ name: "com.android.media-mediatranscoding.rc",
+ src: "mediatranscoding.rc",
+ filename: "init.rc",
+ installable: false,
+}
+
+prebuilt_etc {
name: "com.android.media.swcodec-mediaswcodec.rc",
src: "mediaswcodec.rc",
filename: "init.rc",
diff --git a/apex/manifest.json b/apex/manifest.json
index f1f69f4..b7d8fc8 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,4 +1,10 @@
{
"name": "com.android.media",
- "version": 309999900
+ "version": 309999900,
+ "requireNativeLibs": [
+ "libandroid.so",
+ "libbinder_ndk.so",
+ "libmediandk.so",
+ ":sphal"
+ ]
}
diff --git a/apex/mediatranscoding.rc b/apex/mediatranscoding.rc
new file mode 100644
index 0000000..fa4acf8
--- /dev/null
+++ b/apex/mediatranscoding.rc
@@ -0,0 +1,10 @@
+# media.transcoding service is defined on com.android.media apex which goes back
+# to API29, but we only want it started on API31+ devices. So we declare it as
+# "disabled" and start it explicitly on boot.
+service media.transcoding /apex/com.android.media/bin/mediatranscoding
+ class main
+ user media
+ group media
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh HighPerformance
+ disabled
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 08c88ce..dd652c7 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -1367,31 +1367,11 @@
it->second.isSequenceCompleted = true;
}
- if (it->second.isSequenceCompleted && hasCallback) {
- auto cbIt = mSequenceCallbackMap.find(sequenceId);
- CallbackHolder cbh = cbIt->second;
-
- // send seq complete callback
- sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
- msg->setPointer(kContextKey, cbh.mContext);
- msg->setObject(kSessionSpKey, cbh.mSession);
- msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
- msg->setInt32(kSequenceIdKey, sequenceId);
- msg->setInt64(kFrameNumberKey, lastFrameNumber);
-
- // Clear the session sp before we send out the message
- // This will guarantee the rare case where the message is processed
- // before cbh goes out of scope and causing we call the session
- // destructor while holding device lock
- cbh.mSession.clear();
- postSessionMsgAndCleanup(msg);
- }
}
if (it->second.isSequenceCompleted && it->second.isInflightCompleted) {
- if (mSequenceCallbackMap.find(sequenceId) != mSequenceCallbackMap.end()) {
- mSequenceCallbackMap.erase(sequenceId);
- }
+ sendCaptureSequenceCompletedLocked(sequenceId, lastFrameNumber);
+
it = mSequenceLastFrameNumberMap.erase(it);
ALOGV("%s: Remove holder for sequenceId %d", __FUNCTION__, sequenceId);
} else {
@@ -1418,13 +1398,7 @@
lastCompletedRegularFrameNumber);
if (lastFrameNumber <= lastCompletedRegularFrameNumber) {
if (it->second.isSequenceCompleted) {
- // Check if there is callback for this sequence
- // This should not happen because we always register callback (with nullptr inside)
- if (mSequenceCallbackMap.count(sequenceId) == 0) {
- ALOGW("No callback found for sequenceId %d", sequenceId);
- } else {
- mSequenceCallbackMap.erase(sequenceId);
- }
+ sendCaptureSequenceCompletedLocked(sequenceId, lastFrameNumber);
it = mSequenceLastFrameNumberMap.erase(it);
ALOGV("%s: Remove holder for sequenceId %d", __FUNCTION__, sequenceId);
@@ -1715,5 +1689,33 @@
return ret;
}
+void
+CameraDevice::sendCaptureSequenceCompletedLocked(int sequenceId, int64_t lastFrameNumber) {
+ auto cbIt = mSequenceCallbackMap.find(sequenceId);
+ if (cbIt != mSequenceCallbackMap.end()) {
+ CallbackHolder cbh = cbIt->second;
+ mSequenceCallbackMap.erase(cbIt);
+
+ // send seq complete callback
+ sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
+ msg->setObject(kSessionSpKey, cbh.mSession);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
+ msg->setInt32(kSequenceIdKey, sequenceId);
+ msg->setInt64(kFrameNumberKey, lastFrameNumber);
+
+ // Clear the session sp before we send out the message
+ // This will guarantee the rare case where the message is processed
+ // before cbh goes out of scope and causing we call the session
+ // destructor while holding device lock
+ cbh.mSession.clear();
+ postSessionMsgAndCleanup(msg);
+ } else {
+ // Check if there is callback for this sequence
+ // This should not happen because we always register callback (with nullptr inside)
+ ALOGW("No callback found for sequenceId %d", sequenceId);
+ }
+}
+
} // namespace acam
} // namespace android
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 125e6e3..344d964 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -354,6 +354,7 @@
void checkRepeatingSequenceCompleteLocked(const int sequenceId, const int64_t lastFrameNumber);
void checkAndFireSequenceCompleteLocked();
void removeCompletedCallbackHolderLocked(int64_t lastCompletedRegularFrameNumber);
+ void sendCaptureSequenceCompletedLocked(int sequenceId, int64_t lastFrameNumber);
// Misc variables
int32_t mShadingMapSize[2]; // const after constructor
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 2d54bd1..c7c3dd5 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -816,7 +816,7 @@
* </ul></p>
*
* <p>This control is only effective if ACAMERA_CONTROL_MODE is AUTO.</p>
- * <p>When set to the ON mode, the camera device's auto-white balance
+ * <p>When set to the AUTO mode, the camera device's auto-white balance
* routine is enabled, overriding the application's selected
* ACAMERA_COLOR_CORRECTION_TRANSFORM, ACAMERA_COLOR_CORRECTION_GAINS and
* ACAMERA_COLOR_CORRECTION_MODE. Note that when ACAMERA_CONTROL_AE_MODE
@@ -1957,7 +1957,10 @@
* explicitly set ACAMERA_CONTROL_ZOOM_RATIO, its value defaults to 1.0.</p>
* <p>One limitation of controlling zoom using zoomRatio is that the ACAMERA_SCALER_CROP_REGION
* must only be used for letterboxing or pillarboxing of the sensor active array, and no
- * FREEFORM cropping can be used with ACAMERA_CONTROL_ZOOM_RATIO other than 1.0.</p>
+ * FREEFORM cropping can be used with ACAMERA_CONTROL_ZOOM_RATIO other than 1.0. If
+ * ACAMERA_CONTROL_ZOOM_RATIO is not 1.0, and ACAMERA_SCALER_CROP_REGION is set to be
+ * windowboxing, the camera framework will override the ACAMERA_SCALER_CROP_REGION to be
+ * the active array.</p>
*
* @see ACAMERA_CONTROL_AE_REGIONS
* @see ACAMERA_CONTROL_ZOOM_RATIO
@@ -3651,7 +3654,9 @@
* </ol>
* </li>
* <li>Setting ACAMERA_CONTROL_ZOOM_RATIO to values different than 1.0 and
- * ACAMERA_SCALER_CROP_REGION to be windowboxing at the same time is undefined behavior.</li>
+ * ACAMERA_SCALER_CROP_REGION to be windowboxing at the same time are not supported. In this
+ * case, the camera framework will override the ACAMERA_SCALER_CROP_REGION to be the active
+ * array.</li>
* </ul>
* <p>LEGACY capability devices will only support CENTER_ONLY cropping.</p>
*
@@ -8517,10 +8522,10 @@
* respective color channel provided in
* ACAMERA_SENSOR_TEST_PATTERN_DATA.</p>
* <p>For example:</p>
- * <pre><code>android.testPatternData = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0]
+ * <pre><code>android.control.testPatternData = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0]
* </code></pre>
* <p>All green pixels are 100% green. All red/blue pixels are black.</p>
- * <pre><code>android.testPatternData = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0]
+ * <pre><code>android.control.testPatternData = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0]
* </code></pre>
* <p>All red pixels are 100% red. Only the odd green pixels
* are 100% green. All blue pixels are 100% black.</p>
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index f4b8164..e000633 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -272,7 +272,7 @@
status_t SimplePlayer::onPrepare() {
CHECK_EQ(mState, UNPREPARED);
- mExtractor = new NuMediaExtractor;
+ mExtractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
status_t err = mExtractor->setDataSource(
NULL /* httpService */, mPath.c_str());
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index c26e0b9..33c4663 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -79,7 +79,7 @@
static int64_t kTimeout = 500ll;
- sp<NuMediaExtractor> extractor = new NuMediaExtractor;
+ sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
fprintf(stderr, "unable to instantiate extractor.\n");
return 1;
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
index b894545..ca058ab 100644
--- a/cmds/stagefright/mediafilter.cpp
+++ b/cmds/stagefright/mediafilter.cpp
@@ -319,7 +319,8 @@
static int64_t kTimeout = 500ll;
- sp<NuMediaExtractor> extractor = new NuMediaExtractor;
+ sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
+
if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
fprintf(stderr, "unable to instantiate extractor.\n");
return 1;
diff --git a/cmds/stagefright/muxer.cpp b/cmds/stagefright/muxer.cpp
index 4a83a4a..bc7e41e 100644
--- a/cmds/stagefright/muxer.cpp
+++ b/cmds/stagefright/muxer.cpp
@@ -62,7 +62,7 @@
int trimEndTimeMs,
int rotationDegrees,
MediaMuxer::OutputFormat container = MediaMuxer::OUTPUT_FORMAT_MPEG_4) {
- sp<NuMediaExtractor> extractor = new NuMediaExtractor;
+ sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
fprintf(stderr, "unable to instantiate extractor. %s\n", path);
return 1;
diff --git a/drm/TEST_MAPPING b/drm/TEST_MAPPING
index 9f6a532..aa8a7d8 100644
--- a/drm/TEST_MAPPING
+++ b/drm/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "presubmit": [
+ "presubmit-large": [
// The following tests validate codec and drm path.
{
"name": "GtsMediaTestCases",
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 1700a95..55a32ae 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -11,7 +11,7 @@
}
-cc_library_shared {
+cc_library {
name: "libmediadrm",
srcs: [
diff --git a/drm/libmediadrm/fuzzer/Android.bp b/drm/libmediadrm/fuzzer/Android.bp
new file mode 100644
index 0000000..6f2d054
--- /dev/null
+++ b/drm/libmediadrm/fuzzer/Android.bp
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_fuzz {
+ name: "mediadrm_fuzzer",
+ srcs: [
+ "mediadrm_fuzzer.cpp",
+ ],
+ static_libs: [
+ "libmediadrm",
+ "liblog",
+ "resourcemanager_aidl_interface-ndk_platform",
+ ],
+ header_libs: [
+ "libmedia_headers",
+ "libmediadrm_headers",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libutils",
+ "libbinder_ndk",
+ "libcutils",
+ "libdl",
+ "libmedia",
+ "libmediadrmmetrics_lite",
+ "libmediametrics#1",
+ "libmediautils",
+ "libstagefright_foundation",
+ "android.hardware.drm@1.0",
+ "android.hardware.drm@1.1",
+ "android.hardware.drm@1.2",
+ "android.hardware.drm@1.3",
+ "libhidlallocatorutils",
+ "libhidlbase",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
diff --git a/drm/libmediadrm/fuzzer/README.md b/drm/libmediadrm/fuzzer/README.md
new file mode 100644
index 0000000..3c95cd7
--- /dev/null
+++ b/drm/libmediadrm/fuzzer/README.md
@@ -0,0 +1,56 @@
+# Fuzzer for libmediadrm
+
+## Plugin Design Considerations
+The fuzzer plugin for libmediadrm is designed based on the understanding of the
+library and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+libmediadrm supports the following parameters:
+1. Security Level (parameter name: `securityLevel`)
+2. Mime Type (parameter name: `mimeType`)
+3. Key Type (parameter name: `keyType`)
+4. Crypto Mode (parameter name: `cryptoMode`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `securityLevel` | 0.`DrmPlugin::kSecurityLevelUnknown` 1.`DrmPlugin::kSecurityLevelMax` 2.`DrmPlugin::kSecurityLevelSwSecureCrypto` 3.`DrmPlugin::kSecurityLevelSwSecureDecode` 4.`DrmPlugin::kSecurityLevelHwSecureCrypto` 5.`DrmPlugin::kSecurityLevelHwSecureDecode` 6.`DrmPlugin::kSecurityLevelHwSecureAll`| Value obtained from FuzzedDataProvider in the range 0 to 6|
+| `mimeType` | 0.`video/mp4` 1.`video/mpeg` 2.`video/x-flv` 3.`video/mj2` 4.`video/3gp2` 5.`video/3gpp` 6.`video/3gpp2` 7.`audio/mp4` 8.`audio/mpeg` 9.`audio/aac` 10.`audio/3gp2` 11.`audio/3gpp` 12.`audio/3gpp2` 13.`video/unknown`| Value obtained from FuzzedDataProvider in the range 0 to 13|
+| `keyType` | 0.`DrmPlugin::kKeyType_Offline` 1.`DrmPlugin::kKeyType_Streaming` 2.`DrmPlugin::kKeyType_Release` | Value obtained from FuzzedDataProvider in the range 0 to 2|
+| `cryptoMode` | 0.`CryptoPlugin::kMode_Unencrypted` 1.`CryptoPlugin::kMode_AES_CTR` 2.`CryptoPlugin::kMode_AES_WV` 3.`CryptoPlugin::kMode_AES_CBC` | Value obtained from FuzzedDataProvider in the range 0 to 3|
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the drm module.
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build mediadrm_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) mediadrm_fuzzer
+```
+#### Steps to run
+Create a directory CORPUS_DIR
+```
+ $ adb shell mkdir CORPUS_DIR
+```
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/${TARGET_ARCH}/mediadrm_fuzzer/mediadrm_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp b/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
new file mode 100644
index 0000000..8df0477
--- /dev/null
+++ b/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
@@ -0,0 +1,458 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include <binder/MemoryDealer.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <mediadrm/CryptoHal.h>
+#include <mediadrm/DrmHal.h>
+#include <utils/String8.h>
+#include "fuzzer/FuzzedDataProvider.h"
+
+#define AES_BLOCK_SIZE 16
+#define UNUSED_PARAM __attribute__((unused))
+
+using namespace std;
+using namespace android;
+using android::hardware::fromHeap;
+using ::android::os::PersistableBundle;
+using drm::V1_0::BufferType;
+
+enum {
+ INVALID_UUID = 0,
+ PSSH_BOX_UUID,
+ CLEARKEY_UUID,
+};
+
+static const uint8_t kInvalidUUID[16] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
+ 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};
+
+static const uint8_t kCommonPsshBoxUUID[16] = {0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02,
+ 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B};
+
+static const uint8_t kClearKeyUUID[16] = {0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
+ 0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
+
+static const uint32_t kUUID[] = {INVALID_UUID, PSSH_BOX_UUID, CLEARKEY_UUID};
+
+const DrmPlugin::SecurityLevel kSecurityLevel[] = {
+ DrmPlugin::kSecurityLevelUnknown, DrmPlugin::kSecurityLevelMax,
+ DrmPlugin::kSecurityLevelSwSecureCrypto, DrmPlugin::kSecurityLevelSwSecureDecode,
+ DrmPlugin::kSecurityLevelHwSecureCrypto, DrmPlugin::kSecurityLevelHwSecureDecode,
+ DrmPlugin::kSecurityLevelHwSecureAll};
+
+const char *kMimeType[] = {"video/mp4", "video/mpeg", "video/x-flv", "video/mj2",
+ "video/3gp2", "video/3gpp", "video/3gpp2", "audio/mp4",
+ "audio/mpeg", "audio/aac", "audio/3gp2", "audio/3gpp",
+ "audio/3gpp2", "video/unknown", "audio/unknown"};
+
+const DrmPlugin::KeyType kKeyType[] = {DrmPlugin::kKeyType_Offline, DrmPlugin::kKeyType_Streaming,
+ DrmPlugin::kKeyType_Release};
+
+const CryptoPlugin::Mode kCryptoMode[] = {CryptoPlugin::kMode_Unencrypted,
+ CryptoPlugin::kMode_AES_CTR, CryptoPlugin::kMode_AES_WV,
+ CryptoPlugin::kMode_AES_CBC};
+
+const char *kCipherAlgorithm[] = {"AES/CBC/NoPadding", ""};
+const char *kMacAlgorithm[] = {"HmacSHA256", ""};
+const char *kRSAAlgorithm[] = {"RSASSA-PSS-SHA1", ""};
+const size_t kNumSecurityLevel = size(kSecurityLevel);
+const size_t kNumMimeType = size(kMimeType);
+const size_t kNumKeyType = size(kKeyType);
+const size_t kNumCryptoMode = size(kCryptoMode);
+const size_t kNumUUID = size(kUUID);
+const size_t kMaxStringLength = 100;
+const size_t kMaxSubSamples = 10;
+const size_t kMaxNumBytes = 1000;
+
+struct DrmListener : virtual public IDrmClient {
+ public:
+ void sendEvent(DrmPlugin::EventType eventType UNUSED_PARAM,
+ const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM,
+ const hardware::hidl_vec<uint8_t> &data UNUSED_PARAM) override {}
+
+ void sendExpirationUpdate(const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM,
+ int64_t expiryTimeInMS UNUSED_PARAM) override {}
+
+ void sendKeysChange(const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM,
+ const std::vector<DrmKeyStatus> &keyStatusList UNUSED_PARAM,
+ bool hasNewUsableKey UNUSED_PARAM) override {}
+
+ void sendSessionLostState(const hardware::hidl_vec<uint8_t> &) override {}
+ DrmListener() {}
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(DrmListener);
+};
+
+class DrmFuzzer {
+ public:
+ void process(const uint8_t *data, size_t size);
+
+ private:
+ void invokeDrm(const uint8_t *data, size_t size);
+ bool initDrm();
+ void invokeDrmCreatePlugin();
+ void invokeDrmOpenSession();
+ void invokeDrmSetListener();
+ void invokeDrmSetAlgorithmAPI();
+ void invokeDrmPropertyAPI();
+ void invokeDrmDecryptEncryptAPI(const uint8_t *data, size_t size);
+ void invokeDrmSecureStopAPI();
+ void invokeDrmOfflineLicenseAPI();
+ void invokeDrmCloseSession();
+ void invokeDrmDestroyPlugin();
+ void invokeCrypto(const uint8_t *data);
+ bool initCrypto();
+ void invokeCryptoCreatePlugin();
+ void invokeCryptoDecrypt(const uint8_t *data);
+ void invokeCryptoDestroyPlugin();
+ sp<DrmHal> mDrm = nullptr;
+ sp<CryptoHal> mCrypto = nullptr;
+ Vector<uint8_t> mSessionId = {};
+ FuzzedDataProvider *mFuzzedDataProvider = nullptr;
+};
+
+bool DrmFuzzer::initDrm() {
+ mDrm = new DrmHal();
+ if (!mDrm) {
+ return false;
+ }
+ return true;
+}
+
+void DrmFuzzer::invokeDrmCreatePlugin() {
+ mDrm->initCheck();
+ String8 packageName(mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str());
+ uint32_t uuidEnum = kUUID[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumUUID - 1)];
+ switch (uuidEnum) {
+ case INVALID_UUID:
+ mDrm->createPlugin(kInvalidUUID, packageName);
+ break;
+ case PSSH_BOX_UUID:
+ mDrm->createPlugin(kCommonPsshBoxUUID, packageName);
+ break;
+ case CLEARKEY_UUID:
+ mDrm->createPlugin(kClearKeyUUID, packageName);
+ break;
+ default:
+ break;
+ }
+}
+
+void DrmFuzzer::invokeDrmDestroyPlugin() { mDrm->destroyPlugin(); }
+
+void DrmFuzzer::invokeDrmOpenSession() {
+ DrmPlugin::SecurityLevel securityLevel;
+ bool shouldPassRandomSecurityLevel = mFuzzedDataProvider->ConsumeBool();
+ if (shouldPassRandomSecurityLevel) {
+ securityLevel =
+ static_cast<DrmPlugin::SecurityLevel>(mFuzzedDataProvider->ConsumeIntegral<size_t>());
+ } else {
+ securityLevel = kSecurityLevel[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+ 0, kNumSecurityLevel - 1)];
+ }
+ mDrm->openSession(securityLevel, mSessionId);
+}
+
+void DrmFuzzer::invokeDrmCloseSession() { mDrm->closeSession(mSessionId); }
+
+void DrmFuzzer::invokeDrmSetListener() {
+ sp<DrmListener> listener = new DrmListener();
+ mDrm->setListener(listener);
+}
+
+void DrmFuzzer::invokeDrmSetAlgorithmAPI() {
+ mDrm->setCipherAlgorithm(mSessionId,
+ String8(kCipherAlgorithm[mFuzzedDataProvider->ConsumeBool()]));
+ mDrm->setMacAlgorithm(mSessionId, String8(kMacAlgorithm[mFuzzedDataProvider->ConsumeBool()]));
+}
+
+void DrmFuzzer::invokeDrmPropertyAPI() {
+ mDrm->setPropertyString(String8("property"), String8("value"));
+ String8 stringValue;
+ mDrm->getPropertyString(String8("property"), stringValue);
+ Vector<uint8_t> value = {};
+ mDrm->setPropertyByteArray(String8("property"), value);
+ Vector<uint8_t> byteValue;
+ mDrm->getPropertyByteArray(String8("property"), byteValue);
+}
+
+void DrmFuzzer::invokeDrmDecryptEncryptAPI(const uint8_t *data, size_t size) {
+ uint32_t openSessions = 0;
+ uint32_t maxSessions = 0;
+ mDrm->getNumberOfSessions(&openSessions, &maxSessions);
+
+ DrmPlugin::HdcpLevel connected;
+ DrmPlugin::HdcpLevel max;
+ mDrm->getHdcpLevels(&connected, &max);
+
+ DrmPlugin::SecurityLevel securityLevel;
+ mDrm->getSecurityLevel(mSessionId, &securityLevel);
+
+ // isCryptoSchemeSupported() shall fill isSupported
+ bool isSupported;
+ String8 mimeType(
+ kMimeType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumMimeType - 1)]);
+ mDrm->isCryptoSchemeSupported(kClearKeyUUID, mimeType, securityLevel, &isSupported);
+
+ // getProvisionRequest() shall fill legacyRequest and legacyDefaultUrl
+ String8 certificateType(
+ mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str());
+ String8 certAuthority(mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str());
+ Vector<uint8_t> legacyRequest = {};
+ String8 legacyDefaultUrl;
+ mDrm->getProvisionRequest(certificateType, certAuthority, legacyRequest, legacyDefaultUrl);
+
+ // provideProvisionResponse() shall fill certificate and wrappedKey
+ Vector<uint8_t> provisionResponse = {};
+ Vector<uint8_t> certificate = {};
+ Vector<uint8_t> wrappedKey = {};
+ mDrm->provideProvisionResponse(provisionResponse, certificate, wrappedKey);
+
+ // getKeyRequest() shall fill keyRequest, defaultUrl and keyRequestType
+ Vector<uint8_t> initData = {};
+ initData.appendArray(data, size);
+ DrmPlugin::KeyType keyType;
+ bool shouldPassRandomKeyType = mFuzzedDataProvider->ConsumeBool();
+ if (shouldPassRandomKeyType) {
+ keyType = static_cast<DrmPlugin::KeyType>(mFuzzedDataProvider->ConsumeIntegral<size_t>());
+ } else {
+ keyType = kKeyType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumKeyType - 1)];
+ }
+ KeyedVector<String8, String8> mdOptionalParameters = {};
+ Vector<uint8_t> keyRequest = {};
+ String8 defaultUrl;
+ DrmPlugin::KeyRequestType keyRequestType;
+ mDrm->getKeyRequest(mSessionId, initData, mimeType, keyType, mdOptionalParameters, keyRequest,
+ defaultUrl, &keyRequestType);
+
+ // provideKeyResponse() shall fill keySetId
+ Vector<uint8_t> keyResponse = {};
+ keyResponse.appendArray(data, size);
+ Vector<uint8_t> keySetId = {};
+ mDrm->provideKeyResponse(mSessionId, keyResponse, keySetId);
+
+ // restoreKeys
+ mDrm->restoreKeys(mSessionId, keySetId);
+
+ // queryKeyStatus() shall fill infoMap
+ KeyedVector<String8, String8> infoMap = {};
+ mDrm->queryKeyStatus(mSessionId, infoMap);
+
+ // decrypt() shall fill outputVec
+ Vector<uint8_t> keyIdVec = {};
+ keyIdVec.appendArray(data, size);
+
+ Vector<uint8_t> inputVec = {};
+ inputVec.appendArray(data, size);
+
+ Vector<uint8_t> ivVec = {};
+ ivVec.appendArray(data, size);
+
+ Vector<uint8_t> outputVec = {};
+ mDrm->decrypt(mSessionId, keyIdVec, inputVec, ivVec, outputVec);
+
+ // encrypt() shall fill outputVec
+ mDrm->encrypt(mSessionId, keyIdVec, inputVec, ivVec, outputVec);
+
+ // sign() shall fill signature
+ Vector<uint8_t> message = {};
+ message.appendArray(data, size);
+ Vector<uint8_t> signature = {};
+ mDrm->sign(mSessionId, keyIdVec, message, signature);
+
+ // verify() shall fill match
+ bool match;
+ mDrm->verify(mSessionId, keyIdVec, message, signature, match);
+
+ // signRSA() shall fill signature
+ mDrm->signRSA(mSessionId, String8(kRSAAlgorithm[mFuzzedDataProvider->ConsumeBool()]), message,
+ wrappedKey, signature);
+
+ mDrm->removeKeys(mSessionId);
+}
+
+void DrmFuzzer::invokeDrmSecureStopAPI() {
+ // getSecureStops() shall fill secureStops
+ List<Vector<uint8_t>> secureStops = {};
+ mDrm->getSecureStops(secureStops);
+
+ // getSecureStopIds() shall fill secureStopIds
+ List<Vector<uint8_t>> secureStopIds = {};
+ mDrm->getSecureStopIds(secureStopIds);
+
+ // getSecureStop() shall fill secureStop
+ Vector<uint8_t> ssid = {};
+ Vector<uint8_t> secureStop = {};
+ mDrm->getSecureStop(ssid, secureStop);
+
+ mDrm->removeSecureStop(ssid);
+
+ mDrm->releaseSecureStops(ssid);
+
+ mDrm->removeAllSecureStops();
+}
+
+void DrmFuzzer::invokeDrmOfflineLicenseAPI() {
+ // getOfflineLicenseKeySetIds() shall keySetIds
+ List<Vector<uint8_t>> keySetIds = {};
+ mDrm->getOfflineLicenseKeySetIds(keySetIds);
+
+ // getOfflineLicenseState() shall fill state
+ Vector<uint8_t> const keySetIdOfflineLicense = {};
+ DrmPlugin::OfflineLicenseState state;
+ mDrm->getOfflineLicenseState(keySetIdOfflineLicense, &state);
+
+ mDrm->removeOfflineLicense(keySetIdOfflineLicense);
+}
+
+bool DrmFuzzer::initCrypto() {
+ mCrypto = new CryptoHal();
+ if (!mCrypto) {
+ return false;
+ }
+ return true;
+}
+
+void DrmFuzzer::invokeCryptoCreatePlugin() {
+ mCrypto->initCheck();
+
+ mCrypto->isCryptoSchemeSupported(kClearKeyUUID);
+ mCrypto->createPlugin(kClearKeyUUID, NULL, 0);
+}
+
+void DrmFuzzer::invokeCryptoDestroyPlugin() { mCrypto->destroyPlugin(); }
+
+void DrmFuzzer::invokeCryptoDecrypt(const uint8_t *data) {
+ mCrypto->requiresSecureDecoderComponent(
+ kMimeType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumMimeType - 1)]);
+
+ uint32_t width = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+ uint32_t height = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+ mCrypto->notifyResolution(width, height);
+
+ mCrypto->setMediaDrmSession(mSessionId);
+
+ const CryptoPlugin::Pattern pattern = {0, 0};
+
+ size_t totalSize = 0;
+ size_t numSubSamples = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(1, kMaxSubSamples);
+
+ CryptoPlugin::SubSample subSamples[numSubSamples];
+
+ for (size_t i = 0; i < numSubSamples; ++i) {
+ uint32_t clearBytes =
+ mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxNumBytes);
+ uint32_t encryptedBytes =
+ mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxNumBytes);
+ subSamples[i].mNumBytesOfClearData = clearBytes;
+ subSamples[i].mNumBytesOfEncryptedData = encryptedBytes;
+ totalSize += subSamples[i].mNumBytesOfClearData;
+ totalSize += subSamples[i].mNumBytesOfEncryptedData;
+ }
+
+ size_t heapSize = totalSize * 2;
+ sp<MemoryDealer> dealer = new MemoryDealer(heapSize, "DrmFuzzerMemory");
+ if (!dealer) {
+ return;
+ }
+
+ sp<HidlMemory> heap = fromHeap(dealer->getMemoryHeap());
+ if (!heap) {
+ return;
+ }
+ int heapSeqNum = mCrypto->setHeap(heap);
+ if (heapSeqNum < 0) {
+ return;
+ }
+
+ const size_t segmentIndex = 0;
+ const uint8_t keyId[AES_BLOCK_SIZE] = {};
+ memcpy((void *)keyId, data, AES_BLOCK_SIZE);
+
+ const uint8_t iv[AES_BLOCK_SIZE] = {};
+ memset((void *)iv, 0, AES_BLOCK_SIZE);
+
+ const SharedBuffer sourceBuffer = {.bufferId = segmentIndex, .offset = 0, .size = totalSize};
+
+ const DestinationBuffer destBuffer = {
+ .type = BufferType::SHARED_MEMORY,
+ {.bufferId = segmentIndex, .offset = totalSize, .size = totalSize},
+ .secureMemory = nullptr};
+
+ const uint64_t offset = 0;
+ AString *errorDetailMsg = nullptr;
+ CryptoPlugin::Mode mode;
+ bool shouldPassRandomCryptoMode = mFuzzedDataProvider->ConsumeBool();
+ if (shouldPassRandomCryptoMode) {
+ mode = static_cast<CryptoPlugin::Mode>(mFuzzedDataProvider->ConsumeIntegral<size_t>());
+ } else {
+ mode =
+ kCryptoMode[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumCryptoMode - 1)];
+ }
+ mCrypto->decrypt(keyId, iv, mode, pattern, sourceBuffer, offset, subSamples, numSubSamples,
+ destBuffer, errorDetailMsg);
+
+ if (heapSeqNum >= 0) {
+ mCrypto->unsetHeap(heapSeqNum);
+ }
+ heap.clear();
+}
+
+void DrmFuzzer::invokeDrm(const uint8_t *data, size_t size) {
+ if (!initDrm()) {
+ return;
+ }
+ invokeDrmCreatePlugin();
+ invokeDrmOpenSession();
+ invokeDrmSetAlgorithmAPI();
+ invokeDrmSetListener();
+ invokeDrmPropertyAPI();
+ invokeDrmDecryptEncryptAPI(data, size);
+ invokeDrmSecureStopAPI();
+ invokeDrmOfflineLicenseAPI();
+ invokeDrmCloseSession();
+ invokeDrmDestroyPlugin();
+}
+
+void DrmFuzzer::invokeCrypto(const uint8_t *data) {
+ if (!initCrypto()) {
+ return;
+ }
+ invokeCryptoCreatePlugin();
+ invokeCryptoDecrypt(data);
+ invokeCryptoDestroyPlugin();
+}
+
+void DrmFuzzer::process(const uint8_t *data, size_t size) {
+ mFuzzedDataProvider = new FuzzedDataProvider(data, size);
+ invokeDrm(data, size);
+ invokeCrypto(data);
+ delete mFuzzedDataProvider;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < AES_BLOCK_SIZE) {
+ return 0;
+ }
+ DrmFuzzer drmFuzzer;
+ drmFuzzer.process(data, size);
+ return 0;
+}
diff --git a/include/media/MicrophoneInfo.h b/include/media/MicrophoneInfo.h
index e89401a..a5045b9 100644
--- a/include/media/MicrophoneInfo.h
+++ b/include/media/MicrophoneInfo.h
@@ -208,6 +208,21 @@
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
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
index 50facfb..80e0924 100644
--- a/media/TEST_MAPPING
+++ b/media/TEST_MAPPING
@@ -1,6 +1,6 @@
// for frameworks/av/media
{
- "presubmit": [
+ "presubmit-large": [
// runs whenever we change something in this tree
{
"name": "CtsMediaTestCases",
@@ -17,7 +17,9 @@
"include-filter": "android.media.cts.DecodeEditEncodeTest"
}
]
- },
+ }
+ ],
+ "presubmit": [
{
"name": "GtsMediaTestCases",
"options" : [
diff --git a/media/bufferpool/2.0/AccessorImpl.cpp b/media/bufferpool/2.0/AccessorImpl.cpp
index 6111fea..1d2562e 100644
--- a/media/bufferpool/2.0/AccessorImpl.cpp
+++ b/media/bufferpool/2.0/AccessorImpl.cpp
@@ -39,6 +39,8 @@
static constexpr size_t kMinAllocBytesForEviction = 1024*1024*15;
static constexpr size_t kMinBufferCountForEviction = 25;
+ static constexpr size_t kMaxUnusedBufferCount = 64;
+ static constexpr size_t kUnusedBufferCountTarget = kMaxUnusedBufferCount - 16;
static constexpr nsecs_t kEvictGranularityNs = 1000000000; // 1 sec
static constexpr nsecs_t kEvictDurationNs = 5000000000; // 5 secs
@@ -724,9 +726,11 @@
}
void Accessor::Impl::BufferPool::cleanUp(bool clearCache) {
- if (clearCache || mTimestampUs > mLastCleanUpUs + kCleanUpDurationUs) {
+ if (clearCache || mTimestampUs > mLastCleanUpUs + kCleanUpDurationUs ||
+ mStats.buffersNotInUse() > kMaxUnusedBufferCount) {
mLastCleanUpUs = mTimestampUs;
- if (mTimestampUs > mLastLogUs + kLogDurationUs) {
+ if (mTimestampUs > mLastLogUs + kLogDurationUs ||
+ mStats.buffersNotInUse() > kMaxUnusedBufferCount) {
mLastLogUs = mTimestampUs;
ALOGD("bufferpool2 %p : %zu(%zu size) total buffers - "
"%zu(%zu size) used buffers - %zu/%zu (recycle/alloc) - "
@@ -737,8 +741,9 @@
mStats.mTotalFetches, mStats.mTotalTransfers);
}
for (auto freeIt = mFreeBuffers.begin(); freeIt != mFreeBuffers.end();) {
- if (!clearCache && (mStats.mSizeCached < kMinAllocBytesForEviction
- || mBuffers.size() < kMinBufferCountForEviction)) {
+ if (!clearCache && mStats.buffersNotInUse() <= kUnusedBufferCountTarget &&
+ (mStats.mSizeCached < kMinAllocBytesForEviction ||
+ mBuffers.size() < kMinBufferCountForEviction)) {
break;
}
auto it = mBuffers.find(*freeIt);
diff --git a/media/bufferpool/2.0/AccessorImpl.h b/media/bufferpool/2.0/AccessorImpl.h
index cd1b4d0..3d39941 100644
--- a/media/bufferpool/2.0/AccessorImpl.h
+++ b/media/bufferpool/2.0/AccessorImpl.h
@@ -193,6 +193,12 @@
: mSizeCached(0), mBuffersCached(0), mSizeInUse(0), mBuffersInUse(0),
mTotalAllocations(0), mTotalRecycles(0), mTotalTransfers(0), mTotalFetches(0) {}
+ /// # of currently unused buffers
+ size_t buffersNotInUse() const {
+ ALOG_ASSERT(mBuffersCached >= mBuffersInUse);
+ return mBuffersCached - mBuffersInUse;
+ }
+
/// A new buffer is allocated on an allocation request.
void onBufferAllocated(size_t allocSize) {
mSizeCached += allocSize;
diff --git a/media/bufferpool/2.0/BufferPoolClient.cpp b/media/bufferpool/2.0/BufferPoolClient.cpp
index 342fef6..9308b81 100644
--- a/media/bufferpool/2.0/BufferPoolClient.cpp
+++ b/media/bufferpool/2.0/BufferPoolClient.cpp
@@ -32,6 +32,8 @@
static constexpr int64_t kReceiveTimeoutUs = 1000000; // 100ms
static constexpr int kPostMaxRetry = 3;
static constexpr int kCacheTtlUs = 1000000; // TODO: tune
+static constexpr size_t kMaxCachedBufferCount = 64;
+static constexpr size_t kCachedBufferCountTarget = kMaxCachedBufferCount - 16;
class BufferPoolClient::Impl
: public std::enable_shared_from_this<BufferPoolClient::Impl> {
@@ -136,6 +138,10 @@
--mActive;
mLastChangeUs = getTimestampNow();
}
+
+ int cachedBufferCount() const {
+ return mBuffers.size() - mActive;
+ }
} mCache;
// FMQ - release notifier
@@ -668,10 +674,12 @@
// should have mCache.mLock
void BufferPoolClient::Impl::evictCaches(bool clearCache) {
int64_t now = getTimestampNow();
- if (now >= mLastEvictCacheUs + kCacheTtlUs || clearCache) {
+ if (now >= mLastEvictCacheUs + kCacheTtlUs ||
+ clearCache || mCache.cachedBufferCount() > kMaxCachedBufferCount) {
size_t evicted = 0;
for (auto it = mCache.mBuffers.begin(); it != mCache.mBuffers.end();) {
- if (!it->second->hasCache() && (it->second->expire() || clearCache)) {
+ if (!it->second->hasCache() && (it->second->expire() ||
+ clearCache || mCache.cachedBufferCount() > kCachedBufferCountTarget)) {
it = mCache.mBuffers.erase(it);
++evicted;
} else {
diff --git a/media/bufferpool/2.0/tests/Android.bp b/media/bufferpool/2.0/tests/Android.bp
index 8492939..56bda89 100644
--- a/media/bufferpool/2.0/tests/Android.bp
+++ b/media/bufferpool/2.0/tests/Android.bp
@@ -25,7 +25,7 @@
static_libs: [
"android.hardware.media.bufferpool@2.0",
"libcutils",
- "libstagefright_bufferpool@2.0",
+ "libstagefright_bufferpool@2.0.1",
],
shared_libs: [
"libfmq",
@@ -44,10 +44,30 @@
static_libs: [
"android.hardware.media.bufferpool@2.0",
"libcutils",
- "libstagefright_bufferpool@2.0",
+ "libstagefright_bufferpool@2.0.1",
],
shared_libs: [
"libfmq",
],
compile_multilib: "both",
}
+
+cc_test {
+ name: "VtsVndkHidlBufferpoolV2_0TargetCondTest",
+ test_suites: ["device-tests"],
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "allocator.cpp",
+ "cond.cpp",
+ ],
+ static_libs: [
+ "android.hardware.media.bufferpool@2.0",
+ "libcutils",
+ "libstagefright_bufferpool@2.0.1",
+ ],
+ shared_libs: [
+ "libhidlbase",
+ "libfmq",
+ ],
+ compile_multilib: "both",
+}
diff --git a/media/bufferpool/2.0/tests/allocator.cpp b/media/bufferpool/2.0/tests/allocator.cpp
index 843f7ea..25b08ef 100644
--- a/media/bufferpool/2.0/tests/allocator.cpp
+++ b/media/bufferpool/2.0/tests/allocator.cpp
@@ -120,6 +120,24 @@
}
+void IpcMutex::init() {
+ pthread_mutexattr_t mattr;
+ pthread_mutexattr_init(&mattr);
+ pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
+ pthread_mutex_init(&lock, &mattr);
+ pthread_mutexattr_destroy(&mattr);
+
+ pthread_condattr_t cattr;
+ pthread_condattr_init(&cattr);
+ pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
+ pthread_cond_init(&cond, &cattr);
+ pthread_condattr_destroy(&cattr);
+}
+
+IpcMutex *IpcMutex::Import(void *pMutex) {
+ return reinterpret_cast<IpcMutex *>(pMutex);
+}
+
ResultStatus TestBufferPoolAllocator::allocate(
const std::vector<uint8_t> ¶ms,
@@ -201,9 +219,33 @@
return false;
}
+bool TestBufferPoolAllocator::MapMemoryForMutex(const native_handle_t *handle, void **mem) {
+ if (!HandleAshmem::isValid(handle)) {
+ return false;
+ }
+ const HandleAshmem *o = static_cast<const HandleAshmem*>(handle);
+ *mem = mmap(
+ NULL, o->size(), PROT_READ|PROT_WRITE, MAP_SHARED, o->ashmemFd(), 0);
+ if (*mem == MAP_FAILED || *mem == nullptr) {
+ return false;
+ }
+ return true;
+}
+
+bool TestBufferPoolAllocator::UnmapMemoryForMutex(void *mem) {
+ munmap(mem, sizeof(IpcMutex));
+ return true;
+}
+
void getTestAllocatorParams(std::vector<uint8_t> *params) {
constexpr static int kAllocationSize = 1024 * 10;
Params ashmemParams(kAllocationSize);
params->assign(ashmemParams.array, ashmemParams.array + sizeof(ashmemParams));
}
+
+void getIpcMutexParams(std::vector<uint8_t> *params) {
+ Params ashmemParams(sizeof(IpcMutex));
+
+ params->assign(ashmemParams.array, ashmemParams.array + sizeof(ashmemParams));
+}
diff --git a/media/bufferpool/2.0/tests/allocator.h b/media/bufferpool/2.0/tests/allocator.h
index 5281dc3..862d1a5 100644
--- a/media/bufferpool/2.0/tests/allocator.h
+++ b/media/bufferpool/2.0/tests/allocator.h
@@ -17,6 +17,7 @@
#ifndef VNDK_HIDL_BUFFERPOOL_V2_0_ALLOCATOR_H
#define VNDK_HIDL_BUFFERPOOL_V2_0_ALLOCATOR_H
+#include <pthread.h>
#include <bufferpool/BufferPoolTypes.h>
using android::hardware::media::bufferpool::V2_0::ResultStatus;
@@ -25,6 +26,17 @@
using android::hardware::media::bufferpool::V2_0::implementation::
BufferPoolAllocator;
+struct IpcMutex {
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+ int counter = 0;
+ bool signalled = false;
+
+ void init();
+
+ static IpcMutex *Import(void *mem);
+};
+
// buffer allocator for the tests
class TestBufferPoolAllocator : public BufferPoolAllocator {
public:
@@ -43,9 +55,14 @@
static bool Verify(const native_handle_t *handle, const unsigned char val);
+ static bool MapMemoryForMutex(const native_handle_t *handle, void **mem);
+
+ static bool UnmapMemoryForMutex(void *mem);
};
// retrieve buffer allocator paramters
void getTestAllocatorParams(std::vector<uint8_t> *params);
+void getIpcMutexParams(std::vector<uint8_t> *params);
+
#endif // VNDK_HIDL_BUFFERPOOL_V2_0_ALLOCATOR_H
diff --git a/media/bufferpool/2.0/tests/cond.cpp b/media/bufferpool/2.0/tests/cond.cpp
new file mode 100644
index 0000000..21beea8
--- /dev/null
+++ b/media/bufferpool/2.0/tests/cond.cpp
@@ -0,0 +1,269 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "buffferpool_unit_test"
+
+#include <gtest/gtest.h>
+
+#include <android-base/logging.h>
+#include <binder/ProcessState.h>
+#include <bufferpool/ClientManager.h>
+#include <errno.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+#include <hidl/Status.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <iostream>
+#include <memory>
+#include <vector>
+#include "allocator.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::hidl_handle;
+using android::hardware::media::bufferpool::V2_0::IClientManager;
+using android::hardware::media::bufferpool::V2_0::ResultStatus;
+using android::hardware::media::bufferpool::V2_0::implementation::BufferId;
+using android::hardware::media::bufferpool::V2_0::implementation::ClientManager;
+using android::hardware::media::bufferpool::V2_0::implementation::ConnectionId;
+using android::hardware::media::bufferpool::V2_0::implementation::TransactionId;
+using android::hardware::media::bufferpool::BufferPoolData;
+
+namespace {
+
+// communication message types between processes.
+enum PipeCommand : int32_t {
+ INIT_OK = 0,
+ INIT_ERROR,
+ SEND,
+ RECEIVE_OK,
+ RECEIVE_ERROR,
+};
+
+// communication message between processes.
+union PipeMessage {
+ struct {
+ int32_t command;
+ BufferId bufferId;
+ ConnectionId connectionId;
+ TransactionId transactionId;
+ int64_t timestampUs;
+ } data;
+ char array[0];
+};
+
+constexpr int kSignalInt = 200;
+
+// media.bufferpool test setup
+class BufferpoolMultiTest : public ::testing::Test {
+ public:
+ virtual void SetUp() override {
+ ResultStatus status;
+ mReceiverPid = -1;
+ mConnectionValid = false;
+
+ ASSERT_TRUE(pipe(mCommandPipeFds) == 0);
+ ASSERT_TRUE(pipe(mResultPipeFds) == 0);
+
+ mReceiverPid = fork();
+ ASSERT_TRUE(mReceiverPid >= 0);
+
+ if (mReceiverPid == 0) {
+ doReceiver();
+ // In order to ignore gtest behaviour, wait for being killed from
+ // tearDown
+ pause();
+ }
+
+ mManager = ClientManager::getInstance();
+ ASSERT_NE(mManager, nullptr);
+
+ mAllocator = std::make_shared<TestBufferPoolAllocator>();
+ ASSERT_TRUE((bool)mAllocator);
+
+ status = mManager->create(mAllocator, &mConnectionId);
+ ASSERT_TRUE(status == ResultStatus::OK);
+ mConnectionValid = true;
+ }
+
+ virtual void TearDown() override {
+ if (mReceiverPid > 0) {
+ kill(mReceiverPid, SIGKILL);
+ int wstatus;
+ wait(&wstatus);
+ }
+
+ if (mConnectionValid) {
+ mManager->close(mConnectionId);
+ }
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ android::sp<ClientManager> mManager;
+ std::shared_ptr<BufferPoolAllocator> mAllocator;
+ bool mConnectionValid;
+ ConnectionId mConnectionId;
+ pid_t mReceiverPid;
+ int mCommandPipeFds[2];
+ int mResultPipeFds[2];
+
+ bool sendMessage(int *pipes, const PipeMessage &message) {
+ int ret = write(pipes[1], message.array, sizeof(PipeMessage));
+ return ret == sizeof(PipeMessage);
+ }
+
+ bool receiveMessage(int *pipes, PipeMessage *message) {
+ int ret = read(pipes[0], message->array, sizeof(PipeMessage));
+ return ret == sizeof(PipeMessage);
+ }
+
+ void doReceiver() {
+ configureRpcThreadpool(1, false);
+ PipeMessage message;
+ mManager = ClientManager::getInstance();
+ if (!mManager) {
+ message.data.command = PipeCommand::INIT_ERROR;
+ sendMessage(mResultPipeFds, message);
+ return;
+ }
+ android::status_t status = mManager->registerAsService();
+ if (status != android::OK) {
+ message.data.command = PipeCommand::INIT_ERROR;
+ sendMessage(mResultPipeFds, message);
+ return;
+ }
+ message.data.command = PipeCommand::INIT_OK;
+ sendMessage(mResultPipeFds, message);
+
+ int val = 0;
+ receiveMessage(mCommandPipeFds, &message);
+ {
+ native_handle_t *rhandle = nullptr;
+ std::shared_ptr<BufferPoolData> rbuffer;
+ void *mem = nullptr;
+ IpcMutex *mutex = nullptr;
+ ResultStatus status = mManager->receive(
+ message.data.connectionId, message.data.transactionId,
+ message.data.bufferId, message.data.timestampUs, &rhandle, &rbuffer);
+ mManager->close(message.data.connectionId);
+ if (status != ResultStatus::OK) {
+ message.data.command = PipeCommand::RECEIVE_ERROR;
+ sendMessage(mResultPipeFds, message);
+ return;
+ }
+ if (!TestBufferPoolAllocator::MapMemoryForMutex(rhandle, &mem)) {
+ message.data.command = PipeCommand::RECEIVE_ERROR;
+ sendMessage(mResultPipeFds, message);
+ return;
+ }
+ mutex = IpcMutex::Import(mem);
+ pthread_mutex_lock(&(mutex->lock));
+ while (mutex->signalled != true) {
+ pthread_cond_wait(&(mutex->cond), &(mutex->lock));
+ }
+ val = mutex->counter;
+ pthread_mutex_unlock(&(mutex->lock));
+
+ (void)TestBufferPoolAllocator::UnmapMemoryForMutex(mem);
+ if (rhandle) {
+ native_handle_close(rhandle);
+ native_handle_delete(rhandle);
+ }
+ }
+ if (val == kSignalInt) {
+ message.data.command = PipeCommand::RECEIVE_OK;
+ } else {
+ message.data.command = PipeCommand::RECEIVE_ERROR;
+ }
+ sendMessage(mResultPipeFds, message);
+ }
+};
+
+// Buffer transfer test between processes.
+TEST_F(BufferpoolMultiTest, TransferBuffer) {
+ ResultStatus status;
+ PipeMessage message;
+
+ ASSERT_TRUE(receiveMessage(mResultPipeFds, &message));
+
+ android::sp<IClientManager> receiver = IClientManager::getService();
+ ConnectionId receiverId;
+ ASSERT_TRUE((bool)receiver);
+
+ status = mManager->registerSender(receiver, mConnectionId, &receiverId);
+ ASSERT_TRUE(status == ResultStatus::OK);
+ {
+ native_handle_t *shandle = nullptr;
+ std::shared_ptr<BufferPoolData> sbuffer;
+ TransactionId transactionId;
+ int64_t postUs;
+ std::vector<uint8_t> vecParams;
+ void *mem = nullptr;
+ IpcMutex *mutex = nullptr;
+
+ getIpcMutexParams(&vecParams);
+ status = mManager->allocate(mConnectionId, vecParams, &shandle, &sbuffer);
+ ASSERT_TRUE(status == ResultStatus::OK);
+
+ ASSERT_TRUE(TestBufferPoolAllocator::MapMemoryForMutex(shandle, &mem));
+
+ mutex = new(mem) IpcMutex();
+ mutex->init();
+
+ status = mManager->postSend(receiverId, sbuffer, &transactionId, &postUs);
+ ASSERT_TRUE(status == ResultStatus::OK);
+
+ message.data.command = PipeCommand::SEND;
+ message.data.bufferId = sbuffer->mId;
+ message.data.connectionId = receiverId;
+ message.data.transactionId = transactionId;
+ message.data.timestampUs = postUs;
+ sendMessage(mCommandPipeFds, message);
+ for (int i=0; i < 200000000; ++i) {
+ // no-op in order to ensure
+ // pthread_cond_wait is called before pthread_cond_signal
+ }
+ pthread_mutex_lock(&(mutex->lock));
+ mutex->counter = kSignalInt;
+ mutex->signalled = true;
+ pthread_cond_signal(&(mutex->cond));
+ pthread_mutex_unlock(&(mutex->lock));
+ (void)TestBufferPoolAllocator::UnmapMemoryForMutex(mem);
+ if (shandle) {
+ native_handle_close(shandle);
+ native_handle_delete(shandle);
+ }
+ }
+ EXPECT_TRUE(receiveMessage(mResultPipeFds, &message));
+ EXPECT_TRUE(message.data.command == PipeCommand::RECEIVE_OK);
+}
+
+} // anonymous namespace
+
+int main(int argc, char** argv) {
+ android::hardware::details::setTrebleTestingOverride(true);
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ LOG(INFO) << "Test result = " << status;
+ return status;
+}
diff --git a/media/bufferpool/2.0/tests/multi.cpp b/media/bufferpool/2.0/tests/multi.cpp
index b40838e..43b0a8c 100644
--- a/media/bufferpool/2.0/tests/multi.cpp
+++ b/media/bufferpool/2.0/tests/multi.cpp
@@ -161,11 +161,18 @@
message.data.bufferId, message.data.timestampUs, &rhandle, &rbuffer);
mManager->close(message.data.connectionId);
if (status != ResultStatus::OK) {
- if (!TestBufferPoolAllocator::Verify(rhandle, 0x77)) {
- message.data.command = PipeCommand::RECEIVE_ERROR;
- sendMessage(mResultPipeFds, message);
- return;
- }
+ message.data.command = PipeCommand::RECEIVE_ERROR;
+ sendMessage(mResultPipeFds, message);
+ return;
+ }
+ if (!TestBufferPoolAllocator::Verify(rhandle, 0x77)) {
+ message.data.command = PipeCommand::RECEIVE_ERROR;
+ sendMessage(mResultPipeFds, message);
+ return;
+ }
+ if (rhandle) {
+ native_handle_close(rhandle);
+ native_handle_delete(rhandle);
}
}
message.data.command = PipeCommand::RECEIVE_OK;
@@ -198,6 +205,10 @@
ASSERT_TRUE(status == ResultStatus::OK);
ASSERT_TRUE(TestBufferPoolAllocator::Fill(shandle, 0x77));
+ if (shandle) {
+ native_handle_close(shandle);
+ native_handle_delete(shandle);
+ }
status = mManager->postSend(receiverId, sbuffer, &transactionId, &postUs);
ASSERT_TRUE(status == ResultStatus::OK);
@@ -210,6 +221,7 @@
sendMessage(mCommandPipeFds, message);
}
EXPECT_TRUE(receiveMessage(mResultPipeFds, &message));
+ EXPECT_TRUE(message.data.command == PipeCommand::RECEIVE_OK);
}
} // anonymous namespace
diff --git a/media/bufferpool/2.0/tests/single.cpp b/media/bufferpool/2.0/tests/single.cpp
index 777edcf..1e9027b 100644
--- a/media/bufferpool/2.0/tests/single.cpp
+++ b/media/bufferpool/2.0/tests/single.cpp
@@ -102,6 +102,10 @@
for (int i = 0; i < kNumAllocationTest; ++i) {
status = mManager->allocate(mConnectionId, vecParams, &allocHandle, &buffer[i]);
ASSERT_TRUE(status == ResultStatus::OK);
+ if (allocHandle) {
+ native_handle_close(allocHandle);
+ native_handle_delete(allocHandle);
+ }
}
for (int i = 0; i < kNumAllocationTest; ++i) {
for (int j = i + 1; j < kNumAllocationTest; ++j) {
@@ -125,6 +129,10 @@
status = mManager->allocate(mConnectionId, vecParams, &allocHandle, &buffer);
ASSERT_TRUE(status == ResultStatus::OK);
bid[i] = buffer->mId;
+ if (allocHandle) {
+ native_handle_close(allocHandle);
+ native_handle_delete(allocHandle);
+ }
}
for (int i = 1; i < kNumRecycleTest; ++i) {
ASSERT_TRUE(bid[i - 1] == bid[i]);
@@ -154,6 +162,15 @@
&recvHandle, &rbuffer);
EXPECT_TRUE(status == ResultStatus::OK);
ASSERT_TRUE(TestBufferPoolAllocator::Verify(recvHandle, 0x77));
+
+ if (allocHandle) {
+ native_handle_close(allocHandle);
+ native_handle_delete(allocHandle);
+ }
+ if (recvHandle) {
+ native_handle_close(recvHandle);
+ native_handle_delete(recvHandle);
+ }
}
} // anonymous namespace
diff --git a/media/codec2/TEST_MAPPING b/media/codec2/TEST_MAPPING
index fca3477..6ac4210 100644
--- a/media/codec2/TEST_MAPPING
+++ b/media/codec2/TEST_MAPPING
@@ -4,7 +4,9 @@
// { "name": "codec2_core_param_test"},
// TODO(b/155516524)
// { "name": "codec2_vndk_interface_test"},
- { "name": "codec2_vndk_test"},
+ { "name": "codec2_vndk_test"}
+ ],
+ "presubmit-large": [
{
"name": "CtsMediaTestCases",
"options": [
diff --git a/media/codec2/components/aac/Android.bp b/media/codec2/components/aac/Android.bp
index 9eca585..50495a9 100644
--- a/media/codec2/components/aac/Android.bp
+++ b/media/codec2/components/aac/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_aacdec",
defaults: [
"libcodec2_soft-defaults",
@@ -15,7 +15,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_aacenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/aac/C2SoftAacDec.cpp b/media/codec2/components/aac/C2SoftAacDec.cpp
index 677f316..f3341ab 100644
--- a/media/codec2/components/aac/C2SoftAacDec.cpp
+++ b/media/codec2/components/aac/C2SoftAacDec.cpp
@@ -1061,11 +1061,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAacDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/aac/C2SoftAacEnc.cpp b/media/codec2/components/aac/C2SoftAacEnc.cpp
index 2e85915..ea76cbb 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.cpp
+++ b/media/codec2/components/aac/C2SoftAacEnc.cpp
@@ -692,11 +692,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAacEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/amr_nb_wb/Android.bp b/media/codec2/components/amr_nb_wb/Android.bp
index ce25bc9..b09a505 100644
--- a/media/codec2/components/amr_nb_wb/Android.bp
+++ b/media/codec2/components/amr_nb_wb/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_amrnbdec",
defaults: [
"libcodec2_soft-defaults",
@@ -21,7 +21,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_amrwbdec",
defaults: [
"libcodec2_soft-defaults",
@@ -40,7 +40,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_amrnbenc",
defaults: [
"libcodec2_soft-defaults",
@@ -58,7 +58,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_amrwbenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
index f7943be..c08e02b 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
@@ -420,11 +420,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAMRDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp
index e2d8cb6..bb63e1f 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp
@@ -337,11 +337,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAmrNbEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp
index 84ae4b7..84728ae 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp
@@ -411,11 +411,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAmrWbEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/aom/Android.bp b/media/codec2/components/aom/Android.bp
index 61dbd4c..fcc4552 100644
--- a/media/codec2/components/aom/Android.bp
+++ b/media/codec2/components/aom/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_av1dec_aom",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/aom/C2SoftAomDec.cpp b/media/codec2/components/aom/C2SoftAomDec.cpp
index 9ba3b697..c08cd59 100644
--- a/media/codec2/components/aom/C2SoftAomDec.cpp
+++ b/media/codec2/components/aom/C2SoftAomDec.cpp
@@ -800,11 +800,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAomFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/avc/Android.bp b/media/codec2/components/avc/Android.bp
index 4021444..9f8bc68 100644
--- a/media/codec2/components/avc/Android.bp
+++ b/media/codec2/components/avc/Android.bp
@@ -1,9 +1,10 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_avcdec",
defaults: [
"libcodec2_soft-defaults",
"libcodec2_soft_sanitize_signed-defaults",
- ],
+ "libcodec2_soft_sanitize_cfi-defaults",
+ ],
static_libs: ["libavcdec"],
@@ -15,12 +16,13 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_avcenc",
defaults: [
"libcodec2_soft-defaults",
"libcodec2_soft_sanitize_signed-defaults",
- ],
+ "libcodec2_soft_sanitize_cfi-defaults",
+ ],
static_libs: ["libavcenc"],
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index 3afd670..0207311 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -1049,11 +1049,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAvcDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index ab93ce3..cfaeb66 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -1756,11 +1756,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAvcEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/base/Android.bp b/media/codec2/components/base/Android.bp
index f10835f..0c8f4a4 100644
--- a/media/codec2/components/base/Android.bp
+++ b/media/codec2/components/base/Android.bp
@@ -1,6 +1,6 @@
// DO NOT DEPEND ON THIS DIRECTLY
// use libcodec2_soft-defaults instead
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_common",
defaults: ["libcodec2-impl-defaults"],
vendor_available: true,
@@ -20,7 +20,7 @@
shared_libs: [
"libcutils", // for properties
- "liblog", // for ALOG
+ "liblog", // for ALOG
"libsfplugin_ccodec_utils", // for ImageCopy
"libstagefright_foundation", // for Mutexed
],
@@ -38,7 +38,7 @@
filegroup {
name: "codec2_soft_exports",
- srcs: [ "exports.lds" ],
+ srcs: ["exports.lds"],
}
// public dependency for software codec implementation
@@ -91,12 +91,25 @@
misc_undefined: [
"signed-integer-overflow",
],
+ },
+}
+
+cc_defaults {
+ name: "libcodec2_soft_sanitize_cfi-defaults",
+
+ sanitize: {
cfi: true,
+ config: {
+ cfi_assembly_support: true,
+ },
+ diag: {
+ cfi: true,
+ },
},
}
// TEMP: used by cheets2 project - remove when no longer used
-cc_library_shared {
+cc_library {
name: "libcodec2_simple_component",
vendor_available: true,
@@ -131,4 +144,3 @@
ldflags: ["-Wl,-Bsymbolic"],
}
-
diff --git a/media/codec2/components/flac/Android.bp b/media/codec2/components/flac/Android.bp
index 48cc51b..603c412 100644
--- a/media/codec2/components/flac/Android.bp
+++ b/media/codec2/components/flac/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_flacdec",
defaults: [
"libcodec2_soft-defaults",
@@ -14,7 +14,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_flacenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/flac/C2SoftFlacDec.cpp b/media/codec2/components/flac/C2SoftFlacDec.cpp
index 4039b9b..e70c289 100644
--- a/media/codec2/components/flac/C2SoftFlacDec.cpp
+++ b/media/codec2/components/flac/C2SoftFlacDec.cpp
@@ -367,11 +367,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftFlacDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.cpp b/media/codec2/components/flac/C2SoftFlacEnc.cpp
index 72910c5..6fead3a 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.cpp
+++ b/media/codec2/components/flac/C2SoftFlacEnc.cpp
@@ -482,11 +482,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftFlacEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/g711/Android.bp b/media/codec2/components/g711/Android.bp
index 0101b1a..c39df7b 100644
--- a/media/codec2/components/g711/Android.bp
+++ b/media/codec2/components/g711/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_g711alawdec",
defaults: [
"libcodec2_soft-defaults",
@@ -14,7 +14,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_g711mlawdec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/g711/C2SoftG711Dec.cpp b/media/codec2/components/g711/C2SoftG711Dec.cpp
index 7f9c34e..f9299af 100644
--- a/media/codec2/components/g711/C2SoftG711Dec.cpp
+++ b/media/codec2/components/g711/C2SoftG711Dec.cpp
@@ -259,11 +259,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftG711DecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/gav1/Android.bp b/media/codec2/components/gav1/Android.bp
index f374089..32aa98d 100644
--- a/media/codec2/components/gav1/Android.bp
+++ b/media/codec2/components/gav1/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_av1dec_gav1",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index a1929e7..76345ae 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -770,11 +770,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory *CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftGav1Factory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory *factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/gsm/Android.bp b/media/codec2/components/gsm/Android.bp
index 9330c01..7f54af8 100644
--- a/media/codec2/components/gsm/Android.bp
+++ b/media/codec2/components/gsm/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_gsmdec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/gsm/C2SoftGsmDec.cpp b/media/codec2/components/gsm/C2SoftGsmDec.cpp
index 287cfc6..977677d 100644
--- a/media/codec2/components/gsm/C2SoftGsmDec.cpp
+++ b/media/codec2/components/gsm/C2SoftGsmDec.cpp
@@ -294,11 +294,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftGSMDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/hevc/Android.bp b/media/codec2/components/hevc/Android.bp
index 369bd78..2858212 100644
--- a/media/codec2/components/hevc/Android.bp
+++ b/media/codec2/components/hevc/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_hevcdec",
defaults: [
"libcodec2_soft-defaults",
@@ -11,7 +11,7 @@
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_hevcenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index 23104dc..56dd26b 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -1048,11 +1048,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftHevcDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index c2d2540..436a2c4 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -1078,11 +1078,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftHevcEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/mp3/Android.bp b/media/codec2/components/mp3/Android.bp
index 66665ed..b4fb1b0 100644
--- a/media/codec2/components/mp3/Android.bp
+++ b/media/codec2/components/mp3/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_mp3dec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/mp3/C2SoftMp3Dec.cpp b/media/codec2/components/mp3/C2SoftMp3Dec.cpp
index 5ba7e3d..7137767 100644
--- a/media/codec2/components/mp3/C2SoftMp3Dec.cpp
+++ b/media/codec2/components/mp3/C2SoftMp3Dec.cpp
@@ -539,11 +539,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftMp3DecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/mpeg2/Android.bp b/media/codec2/components/mpeg2/Android.bp
index 841f0a9..666e697 100644
--- a/media/codec2/components/mpeg2/Android.bp
+++ b/media/codec2/components/mpeg2/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_mpeg2dec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index 55dd475..82c061a 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -1113,11 +1113,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftMpeg2DecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/mpeg4_h263/Android.bp b/media/codec2/components/mpeg4_h263/Android.bp
index 41e4f44..0673709 100644
--- a/media/codec2/components/mpeg4_h263/Android.bp
+++ b/media/codec2/components/mpeg4_h263/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_mpeg4dec",
defaults: [
"libcodec2_soft-defaults",
@@ -15,7 +15,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_h263dec",
defaults: [
"libcodec2_soft-defaults",
@@ -31,7 +31,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_mpeg4enc",
defaults: [
"libcodec2_soft-defaults",
@@ -49,7 +49,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_h263enc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
index 13cc0ec..a7cc037 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
@@ -747,11 +747,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftMpeg4DecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
index 54c8c47..e1cc6b3 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
@@ -652,11 +652,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftMpeg4EncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/opus/Android.bp b/media/codec2/components/opus/Android.bp
index 0ed141b..32e2bf8 100644
--- a/media/codec2/components/opus/Android.bp
+++ b/media/codec2/components/opus/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_opusdec",
defaults: [
"libcodec2_soft-defaults",
@@ -9,7 +9,7 @@
shared_libs: ["libopus"],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_opusenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/opus/C2SoftOpusDec.cpp b/media/codec2/components/opus/C2SoftOpusDec.cpp
index b7c1556..d4987c0 100644
--- a/media/codec2/components/opus/C2SoftOpusDec.cpp
+++ b/media/codec2/components/opus/C2SoftOpusDec.cpp
@@ -473,11 +473,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftOpusDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/opus/C2SoftOpusEnc.cpp b/media/codec2/components/opus/C2SoftOpusEnc.cpp
index 70d1965..b47275f 100644
--- a/media/codec2/components/opus/C2SoftOpusEnc.cpp
+++ b/media/codec2/components/opus/C2SoftOpusEnc.cpp
@@ -626,11 +626,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftOpusEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/raw/Android.bp b/media/codec2/components/raw/Android.bp
index dc944da..d4fb8f8 100644
--- a/media/codec2/components/raw/Android.bp
+++ b/media/codec2/components/raw/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_rawdec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/raw/C2SoftRawDec.cpp b/media/codec2/components/raw/C2SoftRawDec.cpp
index 7b6f21a..31ca705 100644
--- a/media/codec2/components/raw/C2SoftRawDec.cpp
+++ b/media/codec2/components/raw/C2SoftRawDec.cpp
@@ -215,11 +215,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftRawDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/vorbis/Android.bp b/media/codec2/components/vorbis/Android.bp
index bc1c380..ff1183f 100644
--- a/media/codec2/components/vorbis/Android.bp
+++ b/media/codec2/components/vorbis/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_vorbisdec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/vorbis/C2SoftVorbisDec.cpp b/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
index d3b6e31..899fe9b 100644
--- a/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
+++ b/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
@@ -359,10 +359,6 @@
}
memcpy(&numPageFrames, data + inSize - sizeof(numPageFrames), sizeof(numPageFrames));
inSize -= sizeof(numPageFrames);
- if (inSize == 0) {
- // empty buffer, ignore
- return;
- }
if (numPageFrames >= 0) {
mNumFramesLeftOnPage = numPageFrames;
}
@@ -413,7 +409,7 @@
mState, reinterpret_cast<int16_t *> (wView.data()),
kMaxNumSamplesPerChannel);
if (numFrames < 0) {
- ALOGD("vorbis_dsp_pcmout returned %d frames", numFrames);
+ ALOGD("vorbis_dsp_pcmout returned %d", numFrames);
numFrames = 0;
}
}
@@ -481,11 +477,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftVorbisDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/vpx/Android.bp b/media/codec2/components/vpx/Android.bp
index 34f5753..72178aa 100644
--- a/media/codec2/components/vpx/Android.bp
+++ b/media/codec2/components/vpx/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_vp9dec",
defaults: [
"libcodec2_soft-defaults",
@@ -14,7 +14,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_vp8dec",
defaults: [
"libcodec2_soft-defaults",
@@ -26,7 +26,7 @@
shared_libs: ["libvpx"],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_vp9enc",
defaults: [
"libcodec2_soft-defaults",
@@ -43,7 +43,7 @@
cflags: ["-DVP9"],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_vp8enc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/vpx/C2SoftVp8Enc.cpp b/media/codec2/components/vpx/C2SoftVp8Enc.cpp
index f18f5d0..049ec38 100644
--- a/media/codec2/components/vpx/C2SoftVp8Enc.cpp
+++ b/media/codec2/components/vpx/C2SoftVp8Enc.cpp
@@ -101,11 +101,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftVp8EncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/vpx/C2SoftVp9Enc.cpp b/media/codec2/components/vpx/C2SoftVp9Enc.cpp
index 740dbda..6401521 100644
--- a/media/codec2/components/vpx/C2SoftVp9Enc.cpp
+++ b/media/codec2/components/vpx/C2SoftVp9Enc.cpp
@@ -131,11 +131,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftVp9EncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.cpp b/media/codec2/components/vpx/C2SoftVpxDec.cpp
index 91238e8..2953d90 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxDec.cpp
@@ -948,11 +948,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftVpxFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/xaac/Android.bp b/media/codec2/components/xaac/Android.bp
index 7795cc1..9b7e2de 100644
--- a/media/codec2/components/xaac/Android.bp
+++ b/media/codec2/components/xaac/Android.bp
@@ -1,8 +1,9 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_xaacdec",
defaults: [
"libcodec2_soft-defaults",
"libcodec2_soft_sanitize_all-defaults",
+ "libcodec2_soft_sanitize_cfi-defaults",
],
srcs: ["C2SoftXaacDec.cpp"],
diff --git a/media/codec2/components/xaac/C2SoftXaacDec.cpp b/media/codec2/components/xaac/C2SoftXaacDec.cpp
index 951d058..6deafda 100644
--- a/media/codec2/components/xaac/C2SoftXaacDec.cpp
+++ b/media/codec2/components/xaac/C2SoftXaacDec.cpp
@@ -1600,11 +1600,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftXaacDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/core/Android.bp b/media/codec2/core/Android.bp
index 33fafa7..beeadb8 100644
--- a/media/codec2/core/Android.bp
+++ b/media/codec2/core/Android.bp
@@ -5,7 +5,7 @@
export_include_dirs: ["include"],
}
-cc_library_shared {
+cc_library {
name: "libcodec2",
vendor_available: true,
min_sdk_version: "29",
diff --git a/media/codec2/fuzzer/Android.bp b/media/codec2/fuzzer/Android.bp
new file mode 100644
index 0000000..2de400d
--- /dev/null
+++ b/media/codec2/fuzzer/Android.bp
@@ -0,0 +1,333 @@
+/*
+ * 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.
+ *
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_defaults {
+ name: "C2Fuzzer-defaults",
+
+ srcs: [
+ "C2Fuzzer.cpp",
+ ],
+
+ static_libs: [
+ "liblog",
+ "libion",
+ "libfmq",
+ "libbase",
+ "libutils",
+ "libcutils",
+ "libcodec2",
+ "libhidlbase",
+ "libdmabufheap",
+ "libcodec2_vndk",
+ "libnativewindow",
+ "libcodec2_soft_common",
+ "libsfplugin_ccodec_utils",
+ "libstagefright_foundation",
+ "libstagefright_bufferpool@2.0.1",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ "android.hardware.media.bufferpool@2.0",
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ ],
+
+ shared_libs: [
+ "libui",
+ "libdl",
+ "libbinder",
+ "libhardware",
+ "libvndksupport",
+ "libprocessgroup",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerAvcDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.avc.decoder\"",
+ ],
+
+ static_libs: [
+ "libavcdec",
+ "libcodec2_soft_avcdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerHevcDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.hevc.decoder\"",
+ ],
+
+ static_libs: [
+ "libhevcdec",
+ "libcodec2_soft_hevcdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerMpeg2Dec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.mpeg2.decoder\"",
+ ],
+
+ static_libs: [
+ "libmpeg2dec",
+ "libcodec2_soft_mpeg2dec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerMpeg4Dec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.mpeg4.decoder\"",
+ ],
+
+ static_libs: [
+ "libstagefright_m4vh263dec",
+ "libcodec2_soft_mpeg4dec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerH263Dec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.h263.decoder\"",
+ ],
+
+ static_libs: [
+ "libstagefright_m4vh263dec",
+ "libcodec2_soft_h263dec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerVp8Dec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.vp8.decoder\"",
+ ],
+
+ static_libs: [
+ "libvpx",
+ "libcodec2_soft_vp8dec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerVp9Dec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.vp9.decoder\"",
+ ],
+
+ static_libs: [
+ "libvpx",
+ "libcodec2_soft_vp9dec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerAacDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.aac.decoder\"",
+ ],
+
+ static_libs: [
+ "libFraunhoferAAC",
+ "libcodec2_soft_aacdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerAmrnbDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.amrnb.decoder\"",
+ ],
+
+ static_libs: [
+ "libstagefright_amrnbdec",
+ "libstagefright_amrwbdec",
+ "libstagefright_amrnb_common",
+ "libcodec2_soft_amrnbdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerAmrwbDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.amrwb.decoder\"",
+ ],
+
+ static_libs: [
+ "libstagefright_amrnbdec",
+ "libstagefright_amrwbdec",
+ "libstagefright_amrnb_common",
+ "libcodec2_soft_amrwbdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerFlacDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.flac.decoder\"",
+ ],
+
+ static_libs: [
+ "libFLAC",
+ "libstagefright_flacdec",
+ "libcodec2_soft_flacdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerG711AlawDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.g711.alaw.decoder\"",
+ ],
+
+ static_libs: [
+ "codecs_g711dec",
+ "libcodec2_soft_g711alawdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerG711MlawDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.g711.mlaw.decoder\"",
+ ],
+
+ static_libs: [
+ "codecs_g711dec",
+ "libcodec2_soft_g711mlawdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerGsmDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.gsm.decoder\"",
+ ],
+
+ static_libs: [
+ "libgsm",
+ "libcodec2_soft_gsmdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerMp3Dec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.mp3.decoder\"",
+ ],
+
+ static_libs: [
+ "libstagefright_mp3dec",
+ "libcodec2_soft_mp3dec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerOpusDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.opus.decoder\"",
+ ],
+
+ static_libs: [
+ "libopus",
+ "libcodec2_soft_opusdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerRawDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.raw.decoder\"",
+ ],
+
+ static_libs: [
+ "libcodec2_soft_rawdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerVorbisDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.vorbis.decoder\"",
+ ],
+
+ static_libs: [
+ "libvorbisidec",
+ "libcodec2_soft_vorbisdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerXaacDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.xaac.decoder\"",
+ ],
+
+ static_libs: [
+ "libxaacdec",
+ "libcodec2_soft_xaacdec",
+ ],
+}
diff --git a/media/codec2/fuzzer/C2Fuzzer.cpp b/media/codec2/fuzzer/C2Fuzzer.cpp
new file mode 100644
index 0000000..71956a2
--- /dev/null
+++ b/media/codec2/fuzzer/C2Fuzzer.cpp
@@ -0,0 +1,318 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <stdio.h>
+
+#include <C2Fuzzer.h>
+
+using namespace android;
+
+class LinearBuffer : public C2Buffer {
+ public:
+ explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
+ : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
+
+ explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block, size_t size)
+ : C2Buffer({block->share(block->offset(), size, ::C2Fence())}) {}
+};
+
+/**
+ * Handle Callback functions onWorkDone_nb(), onTripped_nb(), onError_nb() for C2 Components
+ */
+struct CodecListener : public C2Component::Listener {
+ public:
+ CodecListener(const std::function<void(std::weak_ptr<C2Component> comp,
+ std::list<std::unique_ptr<C2Work>>& workItems)>
+ fn = nullptr)
+ : callBack(fn) {}
+ virtual void onWorkDone_nb(const std::weak_ptr<C2Component> comp,
+ std::list<std::unique_ptr<C2Work>> workItems) {
+ if (callBack) {
+ callBack(comp, workItems);
+ }
+ }
+
+ virtual void onTripped_nb(const std::weak_ptr<C2Component> comp,
+ const std::vector<std::shared_ptr<C2SettingResult>> settingResults) {
+ (void)comp;
+ (void)settingResults;
+ }
+
+ virtual void onError_nb(const std::weak_ptr<C2Component> comp, uint32_t errorCode) {
+ (void)comp;
+ (void)errorCode;
+ }
+
+ std::function<void(std::weak_ptr<C2Component> comp,
+ std::list<std::unique_ptr<C2Work>>& workItems)> callBack;
+};
+
+/**
+ * Buffer source implementations to identify a frame and its size
+ */
+bool Codec2Fuzzer::BufferSource::searchForMarker() {
+ while (true) {
+ if (isMarker()) {
+ return true;
+ }
+ --mReadIndex;
+ if (mReadIndex > mSize) {
+ break;
+ }
+ }
+ return false;
+}
+
+void Codec2Fuzzer::BufferSource::parse() {
+ bool isFrameAvailable = true;
+ size_t bytesRemaining = mSize;
+ while (isFrameAvailable) {
+ isFrameAvailable = searchForMarker();
+ if (isFrameAvailable) {
+ size_t location = mReadIndex + kMarkerSize;
+ bool isCSD = isCSDMarker(location);
+ location += kMarkerSuffixSize;
+ uint8_t* framePtr = const_cast<uint8_t*>(&mData[location]);
+ size_t frameSize = bytesRemaining - location;
+ uint32_t flags = 0;
+ if (mFrameList.empty()) {
+ flags |= C2FrameData::FLAG_END_OF_STREAM;
+ } else if (isCSD) {
+ flags |= C2FrameData::FLAG_CODEC_CONFIG;
+ }
+ mFrameList.emplace_back(std::make_tuple(framePtr, frameSize, flags));
+ bytesRemaining -= (frameSize + kMarkerSize + kMarkerSuffixSize);
+ --mReadIndex;
+ }
+ }
+ if (mFrameList.empty()) {
+ /**
+ * Scenario where input data does not contain the custom frame markers.
+ * Hence feed the entire data as single frame.
+ */
+ mFrameList.emplace_back(
+ std::make_tuple(const_cast<uint8_t*>(mData), 0, C2FrameData::FLAG_END_OF_STREAM));
+ mFrameList.emplace_back(
+ std::make_tuple(const_cast<uint8_t*>(mData), mSize, C2FrameData::FLAG_CODEC_CONFIG));
+ }
+}
+
+FrameData Codec2Fuzzer::BufferSource::getFrame() {
+ FrameData frame = mFrameList.back();
+ mFrameList.pop_back();
+ return frame;
+}
+
+void Codec2Fuzzer::handleWorkDone(std::weak_ptr<C2Component> comp,
+ std::list<std::unique_ptr<C2Work>>& workItems) {
+ (void)comp;
+ for (std::unique_ptr<C2Work>& work : workItems) {
+ if (!work->worklets.empty()) {
+ if (work->worklets.front()->output.flags != C2FrameData::FLAG_INCOMPLETE) {
+ mEos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
+ work->input.buffers.clear();
+ work->worklets.clear();
+ {
+ std::unique_lock<std::mutex> lock(mQueueLock);
+ mWorkQueue.push_back(std::move(work));
+ mQueueCondition.notify_all();
+ }
+ if (mEos) {
+ {
+ std::lock_guard<std::mutex> waitForDecodeComplete(mDecodeCompleteMutex);
+ }
+ mConditionalVariable.notify_one();
+ }
+ }
+ }
+ }
+}
+
+bool Codec2Fuzzer::initDecoder() {
+ std::vector<std::tuple<C2String, C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc>> codec2FactoryFunc;
+
+ codec2FactoryFunc.emplace_back(std::make_tuple(C2COMPONENTNAME,
+ &CreateCodec2Factory,
+ &DestroyCodec2Factory));
+
+ std::shared_ptr<C2ComponentStore> componentStore = GetTestComponentStore(codec2FactoryFunc);
+ if (!componentStore) {
+ return false;
+ }
+
+ std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
+ if (!allocatorStore) {
+ return false;
+ }
+
+ c2_status_t status =
+ allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator);
+ if (status != C2_OK) {
+ return false;
+ }
+
+ mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, ++mBlockPoolId);
+ if (!mLinearPool) {
+ return false;
+ }
+
+ for (int32_t i = 0; i < kNumberOfC2WorkItems; ++i) {
+ mWorkQueue.emplace_back(new C2Work);
+ }
+
+ status = componentStore->createComponent(C2COMPONENTNAME, &mComponent);
+ if (status != C2_OK) {
+ return false;
+ }
+
+ status = componentStore->createInterface(C2COMPONENTNAME, &mInterface);
+ if (status != C2_OK) {
+ return false;
+ }
+
+ C2ComponentKindSetting kind;
+ C2ComponentDomainSetting domain;
+ status = mInterface->query_vb({&kind, &domain}, {}, C2_MAY_BLOCK, nullptr);
+ if (status != C2_OK) {
+ return false;
+ }
+
+ std::vector<C2Param*> configParams;
+ if (domain.value == DOMAIN_VIDEO) {
+ C2StreamPictureSizeInfo::input inputSize(0u, kWidthOfVideo, kHeightOfVideo);
+ configParams.push_back(&inputSize);
+ } else if (domain.value == DOMAIN_AUDIO) {
+ C2StreamSampleRateInfo::output sampleRateInfo(0u, kSamplingRateOfAudio);
+ C2StreamChannelCountInfo::output channelCountInfo(0u, kChannelsOfAudio);
+ configParams.push_back(&sampleRateInfo);
+ configParams.push_back(&channelCountInfo);
+ }
+
+ mListener.reset(new CodecListener(
+ [this](std::weak_ptr<C2Component> comp, std::list<std::unique_ptr<C2Work>>& workItems) {
+ handleWorkDone(comp, workItems);
+ }));
+ if (!mListener) {
+ return false;
+ }
+
+ status = mComponent->setListener_vb(mListener, C2_DONT_BLOCK);
+ if (status != C2_OK) {
+ return false;
+ }
+
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ componentStore->config_sm(configParams, &failures);
+ if (failures.size() != 0) {
+ return false;
+ }
+
+ status = mComponent->start();
+ if (status != C2_OK) {
+ return false;
+ }
+
+ return true;
+}
+
+void Codec2Fuzzer::deInitDecoder() {
+ mComponent->stop();
+ mComponent->reset();
+ mComponent->release();
+ mComponent = nullptr;
+}
+
+void Codec2Fuzzer::decodeFrames(const uint8_t* data, size_t size) {
+ mBufferSource = new BufferSource(data, size);
+ if (!mBufferSource) {
+ return;
+ }
+ mBufferSource->parse();
+ c2_status_t status = C2_OK;
+ size_t numFrames = 0;
+ while (!mBufferSource->isEos()) {
+ uint8_t* frame = nullptr;
+ size_t frameSize = 0;
+ FrameData frameData = mBufferSource->getFrame();
+ frame = std::get<0>(frameData);
+ frameSize = std::get<1>(frameData);
+
+ std::unique_ptr<C2Work> work;
+ {
+ std::unique_lock<std::mutex> lock(mQueueLock);
+ if (mWorkQueue.empty()) mQueueCondition.wait_for(lock, kC2FuzzerTimeOut);
+ if (!mWorkQueue.empty()) {
+ work.swap(mWorkQueue.front());
+ mWorkQueue.pop_front();
+ } else {
+ return;
+ }
+ }
+
+ work->input.flags = (C2FrameData::flags_t)std::get<2>(frameData);
+ work->input.ordinal.timestamp = 0;
+ work->input.ordinal.frameIndex = ++numFrames;
+ work->input.buffers.clear();
+ int32_t alignedSize = C2FUZZER_ALIGN(frameSize, PAGE_SIZE);
+
+ std::shared_ptr<C2LinearBlock> block;
+ status = mLinearPool->fetchLinearBlock(
+ alignedSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+ if (status != C2_OK || block == nullptr) {
+ return;
+ }
+
+ C2WriteView view = block->map().get();
+ if (view.error() != C2_OK) {
+ return;
+ }
+ memcpy(view.base(), frame, frameSize);
+ work->input.buffers.emplace_back(new LinearBuffer(block, frameSize));
+ work->worklets.clear();
+ work->worklets.emplace_back(new C2Worklet);
+
+ std::list<std::unique_ptr<C2Work>> items;
+ items.push_back(std::move(work));
+ status = mComponent->queue_nb(&items);
+ if (status != C2_OK) {
+ return;
+ }
+ }
+ std::unique_lock<std::mutex> waitForDecodeComplete(mDecodeCompleteMutex);
+ mConditionalVariable.wait_for(waitForDecodeComplete, kC2FuzzerTimeOut, [this] { return mEos; });
+ std::list<std::unique_ptr<C2Work>> c2flushedWorks;
+ mComponent->flush_sm(C2Component::FLUSH_COMPONENT, &c2flushedWorks);
+ delete mBufferSource;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ if (size < 1) {
+ return 0;
+ }
+ Codec2Fuzzer* codec = new Codec2Fuzzer();
+ if (!codec) {
+ return 0;
+ }
+ if (codec->initDecoder()) {
+ codec->decodeFrames(data, size);
+ }
+ delete codec;
+ return 0;
+}
diff --git a/media/codec2/fuzzer/C2Fuzzer.h b/media/codec2/fuzzer/C2Fuzzer.h
new file mode 100644
index 0000000..2efad50
--- /dev/null
+++ b/media/codec2/fuzzer/C2Fuzzer.h
@@ -0,0 +1,114 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#ifndef __C2FUZZER_H__
+#define __C2FUZZER_H__
+
+#include <C2AllocatorIon.h>
+#include <C2Buffer.h>
+#include <C2BufferPriv.h>
+#include <C2Component.h>
+#include <C2Config.h>
+#include <C2PlatformSupport.h>
+
+using namespace std::chrono_literals;
+
+extern "C" ::C2ComponentFactory* CreateCodec2Factory();
+extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory);
+
+namespace android {
+
+#define C2FUZZER_ALIGN(_sz, _align) (((_sz) + ((_align)-1)) & ~((_align)-1))
+
+constexpr std::chrono::milliseconds kC2FuzzerTimeOut = 5000ms;
+constexpr int32_t kNumberOfC2WorkItems = 8;
+constexpr uint32_t kWidthOfVideo = 3840;
+constexpr uint32_t kHeightOfVideo = 2160;
+constexpr uint32_t kSamplingRateOfAudio = 48000;
+constexpr uint32_t kChannelsOfAudio = 8;
+
+typedef std::tuple<uint8_t*, size_t, uint32_t> FrameData;
+
+class Codec2Fuzzer {
+ public:
+ Codec2Fuzzer() = default;
+ ~Codec2Fuzzer() { deInitDecoder(); }
+ bool initDecoder();
+ void deInitDecoder();
+ void decodeFrames(const uint8_t* data, size_t size);
+
+ void handleWorkDone(std::weak_ptr<C2Component> comp,
+ std::list<std::unique_ptr<C2Work>>& workItems);
+
+ private:
+ class BufferSource {
+ public:
+ BufferSource(const uint8_t* data, size_t size)
+ : mData(data), mSize(size), mReadIndex(size - kMarkerSize) {}
+ ~BufferSource() {
+ mData = nullptr;
+ mSize = 0;
+ mReadIndex = 0;
+ mFrameList.clear();
+ }
+ bool isEos() { return mFrameList.empty(); }
+ void parse();
+ FrameData getFrame();
+
+ private:
+ bool isMarker() { return (memcmp(&mData[mReadIndex], kMarker, kMarkerSize) == 0); }
+
+ bool isCSDMarker(size_t position) {
+ return (memcmp(&mData[position], kCsdMarkerSuffix, kMarkerSuffixSize) == 0);
+ }
+
+ bool searchForMarker();
+
+ const uint8_t* mData = nullptr;
+ size_t mSize = 0;
+ size_t mReadIndex = 0;
+ std::vector<FrameData> mFrameList;
+ static constexpr uint8_t kMarker[] = "_MARK";
+ static constexpr uint8_t kCsdMarkerSuffix[] = "_H_";
+ static constexpr uint8_t kFrameMarkerSuffix[] = "_F_";
+ // All markers should be 5 bytes long ( sizeof '_MARK' which is 5)
+ static constexpr size_t kMarkerSize = (sizeof(kMarker) - 1);
+ // All marker types should be 3 bytes long ('_H_', '_F_')
+ static constexpr size_t kMarkerSuffixSize = 3;
+ };
+
+ BufferSource* mBufferSource;
+ bool mEos = false;
+ C2BlockPool::local_id_t mBlockPoolId;
+
+ std::shared_ptr<C2BlockPool> mLinearPool;
+ std::shared_ptr<C2Allocator> mLinearAllocator;
+ std::shared_ptr<C2Component::Listener> mListener;
+ std::shared_ptr<C2Component> mComponent;
+ std::shared_ptr<C2ComponentInterface> mInterface;
+ std::mutex mQueueLock;
+ std::condition_variable mQueueCondition;
+ std::list<std::unique_ptr<C2Work>> mWorkQueue;
+ std::mutex mDecodeCompleteMutex;
+ std::condition_variable mConditionalVariable;
+};
+
+} // namespace android
+
+#endif // __C2FUZZER_H__
diff --git a/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp b/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
index fb1c291..47ceed5 100644
--- a/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
@@ -73,9 +73,10 @@
ASSERT_NE(listener, nullptr);
// Create component from all known services
- component =
- mClient->CreateComponentByName(listTraits[i].name.c_str(), listener, &mClient);
- ASSERT_NE(component, nullptr)
+ const c2_status_t status =
+ android::Codec2Client::CreateComponentByName(
+ listTraits[i].name.c_str(), listener, &component, &mClient);
+ ASSERT_EQ(status, C2_OK)
<< "Create component failed for " << listTraits[i].name.c_str();
}
}
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 12ed725..b520c17 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
@@ -734,7 +734,7 @@
}
if (timestampMax < timestamp) timestampMax = timestamp;
}
- timestampOffset = timestampMax;
+ timestampOffset = timestampMax + 33333;
eleInfo.close();
// Reset Total frames before second decode loop
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 4650672..341a577 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -1008,6 +1008,8 @@
std::scoped_lock lock{key2IndexMutex};
key2Index[key] = index; // update last known client index
return C2_OK;
+ } else if (status == C2_NO_MEMORY) {
+ return C2_NO_MEMORY;
} else if (status == C2_TRANSACTION_FAILED) {
LOG(WARNING) << "\"" << key << "\" failed for service \""
<< client->getName()
@@ -1028,24 +1030,23 @@
return status; // return the last status from a valid client
}
-std::shared_ptr<Codec2Client::Component>
- Codec2Client::CreateComponentByName(
+c2_status_t Codec2Client::CreateComponentByName(
const char* componentName,
const std::shared_ptr<Listener>& listener,
+ std::shared_ptr<Component>* component,
std::shared_ptr<Codec2Client>* owner,
size_t numberOfAttempts) {
std::string key{"create:"};
key.append(componentName);
- std::shared_ptr<Component> component;
c2_status_t status = ForAllServices(
key,
numberOfAttempts,
- [owner, &component, componentName, &listener](
+ [owner, component, componentName, &listener](
const std::shared_ptr<Codec2Client> &client)
-> c2_status_t {
c2_status_t status = client->createComponent(componentName,
listener,
- &component);
+ component);
if (status == C2_OK) {
if (owner) {
*owner = client;
@@ -1064,7 +1065,7 @@
<< "\" from all known services. "
"Last returned status = " << status << ".";
}
- return component;
+ return status;
}
std::shared_ptr<Codec2Client::Interface>
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index ffd194a..bbb2b96 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -200,9 +200,10 @@
// Try to create a component with a given name from all known
// IComponentStore services. numberOfAttempts determines the number of times
// to retry the HIDL call if the transaction fails.
- static std::shared_ptr<Component> CreateComponentByName(
+ static c2_status_t CreateComponentByName(
char const* componentName,
std::shared_ptr<Listener> const& listener,
+ std::shared_ptr<Component>* component,
std::shared_ptr<Codec2Client>* owner = nullptr,
size_t numberOfAttempts = 10);
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 9c1df71..5de4d7f 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -247,15 +247,20 @@
return NO_INIT;
}
- size_t numSlots = 4;
- constexpr OMX_U32 kPortIndexInput = 0;
+ size_t numSlots = 16;
+ // WORKAROUND: having more slots improve performance while consuming
+ // more memory. This is a temporary workaround to reduce memory for
+ // larger-than-4K scenario.
+ if (mWidth * mHeight > 4096 * 2340) {
+ constexpr OMX_U32 kPortIndexInput = 0;
- OMX_PARAM_PORTDEFINITIONTYPE param;
- param.nPortIndex = kPortIndexInput;
- status_t err = mNode->getParameter(OMX_IndexParamPortDefinition,
- ¶m, sizeof(param));
- if (err == OK) {
- numSlots = param.nBufferCountActual;
+ OMX_PARAM_PORTDEFINITIONTYPE param;
+ param.nPortIndex = kPortIndexInput;
+ status_t err = mNode->getParameter(OMX_IndexParamPortDefinition,
+ ¶m, sizeof(param));
+ if (err == OK) {
+ numSlots = param.nBufferCountActual;
+ }
}
for (size_t i = 0; i < numSlots; ++i) {
@@ -645,17 +650,18 @@
std::make_shared<Codec2ClientInterfaceWrapper>(client));
}
- std::shared_ptr<Codec2Client::Component> comp =
- Codec2Client::CreateComponentByName(
+ std::shared_ptr<Codec2Client::Component> comp;
+ c2_status_t status = Codec2Client::CreateComponentByName(
componentName.c_str(),
mClientListener,
+ &comp,
&client);
- if (!comp) {
- ALOGE("Failed Create component: %s", componentName.c_str());
+ if (status != C2_OK) {
+ ALOGE("Failed Create component: %s, error=%d", componentName.c_str(), status);
Mutexed<State>::Locked state(mState);
state->set(RELEASED);
state.unlock();
- mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
+ mCallback->onError((status == C2_NO_MEMORY ? NO_MEMORY : UNKNOWN_ERROR), ACTION_CODE_FATAL);
state.lock();
return;
}
@@ -967,6 +973,7 @@
C2AndroidMemoryUsage androidUsage(C2MemoryUsage(usage.value));
config->mISConfig->mUsage = androidUsage.asGrallocUsage();
}
+ config->mInputFormat->setInt64("android._C2MemoryUsage", usage.value);
}
// NOTE: we don't blindly use client specified input size if specified as clients
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 3ef454b..8c1e712 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1300,54 +1300,30 @@
return a.capacity < b.capacity;
});
- {
- Mutexed<std::list<sp<ABuffer>>>::Locked configs(mFlushedConfigs);
- if (!configs->empty()) {
- while (!configs->empty()) {
- sp<ABuffer> config = configs->front();
- configs->pop_front();
- // Find the smallest input buffer that can fit the config.
- auto i = std::find_if(
- clientInputBuffers.begin(),
- clientInputBuffers.end(),
- [cfgSize = config->size()](const ClientInputBuffer& b) {
- return b.capacity >= cfgSize;
- });
- if (i == clientInputBuffers.end()) {
- ALOGW("[%s] no input buffer large enough for the config "
- "(%zu bytes)",
- mName, config->size());
- return NO_MEMORY;
- }
- sp<MediaCodecBuffer> buffer = i->buffer;
- memcpy(buffer->base(), config->data(), config->size());
- buffer->setRange(0, config->size());
- buffer->meta()->clear();
- buffer->meta()->setInt64("timeUs", 0);
- buffer->meta()->setInt32("csd", 1);
- if (queueInputBufferInternal(buffer) != OK) {
- ALOGW("[%s] Error while queueing a flushed config",
- mName);
- return UNKNOWN_ERROR;
- }
- clientInputBuffers.erase(i);
- }
- } else if (oStreamFormat.value == C2BufferData::LINEAR &&
- (!prepend || prepend.value == PREPEND_HEADER_TO_NONE)) {
- sp<MediaCodecBuffer> buffer = clientInputBuffers.front().buffer;
- // WORKAROUND: Some apps expect CSD available without queueing
- // any input. Queue an empty buffer to get the CSD.
- buffer->setRange(0, 0);
- buffer->meta()->clear();
- buffer->meta()->setInt64("timeUs", 0);
- if (queueInputBufferInternal(buffer) != OK) {
- ALOGW("[%s] Error while queueing an empty buffer to get CSD",
- mName);
- return UNKNOWN_ERROR;
- }
- clientInputBuffers.pop_front();
+ std::list<std::unique_ptr<C2Work>> flushedConfigs;
+ mFlushedConfigs.lock()->swap(flushedConfigs);
+ if (!flushedConfigs.empty()) {
+ err = mComponent->queue(&flushedConfigs);
+ if (err != C2_OK) {
+ ALOGW("[%s] Error while queueing a flushed config", mName);
+ return UNKNOWN_ERROR;
}
}
+ if (oStreamFormat.value == C2BufferData::LINEAR &&
+ (!prepend || prepend.value == PREPEND_HEADER_TO_NONE)) {
+ sp<MediaCodecBuffer> buffer = clientInputBuffers.front().buffer;
+ // WORKAROUND: Some apps expect CSD available without queueing
+ // any input. Queue an empty buffer to get the CSD.
+ buffer->setRange(0, 0);
+ buffer->meta()->clear();
+ buffer->meta()->setInt64("timeUs", 0);
+ if (queueInputBufferInternal(buffer) != OK) {
+ ALOGW("[%s] Error while queueing an empty buffer to get CSD",
+ mName);
+ return UNKNOWN_ERROR;
+ }
+ clientInputBuffers.pop_front();
+ }
for (const ClientInputBuffer& clientInputBuffer: clientInputBuffers) {
mCallback->onInputBufferAvailable(
@@ -1396,27 +1372,36 @@
void CCodecBufferChannel::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
ALOGV("[%s] flush", mName);
- {
- Mutexed<std::list<sp<ABuffer>>>::Locked configs(mFlushedConfigs);
- for (const std::unique_ptr<C2Work> &work : flushedWork) {
- if (!(work->input.flags & C2FrameData::FLAG_CODEC_CONFIG)) {
- continue;
- }
- if (work->input.buffers.empty()
- || work->input.buffers.front()->data().linearBlocks().empty()) {
- ALOGD("[%s] no linear codec config data found", mName);
- continue;
- }
- C2ReadView view =
- work->input.buffers.front()->data().linearBlocks().front().map().get();
- if (view.error() != C2_OK) {
- ALOGD("[%s] failed to map flushed codec config data: %d", mName, view.error());
- continue;
- }
- configs->push_back(ABuffer::CreateAsCopy(view.data(), view.capacity()));
- ALOGV("[%s] stashed flushed codec config data (size=%u)", mName, view.capacity());
+ std::list<std::unique_ptr<C2Work>> configs;
+ for (const std::unique_ptr<C2Work> &work : flushedWork) {
+ if (!(work->input.flags & C2FrameData::FLAG_CODEC_CONFIG)) {
+ continue;
}
+ if (work->input.buffers.empty()
+ || work->input.buffers.front() == nullptr
+ || work->input.buffers.front()->data().linearBlocks().empty()) {
+ ALOGD("[%s] no linear codec config data found", mName);
+ continue;
+ }
+ std::unique_ptr<C2Work> copy(new C2Work);
+ copy->input.flags = C2FrameData::flags_t(work->input.flags | C2FrameData::FLAG_DROP_FRAME);
+ copy->input.ordinal = work->input.ordinal;
+ copy->input.buffers.insert(
+ copy->input.buffers.begin(),
+ work->input.buffers.begin(),
+ work->input.buffers.end());
+ for (const std::unique_ptr<C2Param> ¶m : work->input.configUpdate) {
+ copy->input.configUpdate.push_back(C2Param::Copy(*param));
+ }
+ copy->input.infoBuffers.insert(
+ copy->input.infoBuffers.begin(),
+ work->input.infoBuffers.begin(),
+ work->input.infoBuffers.end());
+ copy->worklets.emplace_back(new C2Worklet);
+ configs.push_back(std::move(copy));
+ ALOGV("[%s] stashed flushed codec config data", mName);
}
+ mFlushedConfigs.lock()->swap(configs);
{
Mutexed<Input>::Locked input(mInput);
input->buffers->flush();
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index 046c5c3..e2c9aaa 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -277,7 +277,7 @@
uint32_t outputDelay;
};
Mutexed<Output> mOutput;
- Mutexed<std::list<sp<ABuffer>>> mFlushedConfigs;
+ Mutexed<std::list<std::unique_ptr<C2Work>>> mFlushedConfigs;
std::atomic_uint64_t mFrameIndex;
std::atomic_uint64_t mFirstValidFrameIndex;
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index 692da58..dd28b6a 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -96,6 +96,9 @@
int32_t vstride = int32_t(offsetDelta / stride);
newFormat->setInt32(KEY_SLICE_HEIGHT, vstride);
ALOGD("[%s] updating vstride = %d", mName, vstride);
+ buffer->setRange(
+ img->mPlane[0].mOffset,
+ buffer->size() - img->mPlane[0].mOffset);
}
}
setFormat(newFormat);
@@ -804,8 +807,9 @@
capacity = kMaxLinearBufferSize;
}
- // TODO: read usage from intf
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
+ int64_t usageValue = 0;
+ (void)format->findInt64("android._C2MemoryUsage", &usageValue);
+ C2MemoryUsage usage{usageValue | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE};
std::shared_ptr<C2LinearBlock> block;
c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
@@ -1037,8 +1041,9 @@
}
sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
- // TODO: read usage from intf
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
+ int64_t usageValue = 0;
+ (void)mFormat->findInt64("android._C2MemoryUsage", &usageValue);
+ C2MemoryUsage usage{usageValue | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE};
return AllocateGraphicBuffer(
mPool, mFormat, HAL_PIXEL_FORMAT_YV12, usage, mLocalBufferPool);
}
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 25e7da9..5072323 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "Codec2Buffer"
#include <utils/Log.h>
+#include <android-base/properties.h>
#include <android/hardware/cas/native/1.0/types.h>
#include <android/hardware/drm/1.0/types.h>
#include <hidlmemory/FrameworkUtils.h>
@@ -276,20 +277,22 @@
int32_t planeSize = 0;
for (uint32_t i = 0; i < layout.numPlanes; ++i) {
const C2PlaneInfo &plane = layout.planes[i];
- ssize_t minOffset = plane.minOffset(mWidth, mHeight);
- ssize_t maxOffset = plane.maxOffset(mWidth, mHeight);
+ int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
+ ssize_t minOffset = plane.minOffset(
+ mWidth / plane.colSampling, mHeight / plane.rowSampling);
+ ssize_t maxOffset = plane.maxOffset(
+ mWidth / plane.colSampling, mHeight / plane.rowSampling);
if (minPtr > mView.data()[i] + minOffset) {
minPtr = mView.data()[i] + minOffset;
}
if (maxPtr < mView.data()[i] + maxOffset) {
maxPtr = mView.data()[i] + maxOffset;
}
- planeSize += std::abs(plane.rowInc) * align(mHeight, 64)
- / plane.rowSampling / plane.colSampling
- * divUp(mAllocatedDepth, 8u);
+ planeSize += planeStride * divUp(mAllocatedDepth, 8u)
+ * align(mHeight, 64) / plane.rowSampling;
}
- if ((maxPtr - minPtr + 1) <= planeSize) {
+ if (minPtr == mView.data()[0] && (maxPtr - minPtr + 1) <= planeSize) {
// FIXME: this is risky as reading/writing data out of bound results
// in an undefined behavior, but gralloc does assume a
// contiguous mapping
@@ -578,7 +581,23 @@
}
std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
-#ifndef __LP64__
+#ifdef __LP64__
+ static std::once_flag s_checkOnce;
+ static bool s_64bitonly {false};
+ std::call_once(s_checkOnce, [&](){
+ const std::string abi32list =
+ ::android::base::GetProperty("ro.product.cpu.abilist32", "");
+ if (abi32list.empty()) {
+ s_64bitonly = true;
+ }
+ });
+
+ if (!s_64bitonly) {
+ ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object");
+ return nullptr;
+ }
+#endif
+
VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
if (buffer == nullptr) {
@@ -611,10 +630,6 @@
}
return C2Buffer::CreateGraphicBuffer(
block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
-#else
- ALOGE("GraphicMetadataBuffer does not work on 64-bit arch");
- return nullptr;
-#endif
}
// ConstGraphicBlockBuffer
diff --git a/media/codec2/sfplugin/InputSurfaceWrapper.h b/media/codec2/sfplugin/InputSurfaceWrapper.h
index bb35763..479acb1 100644
--- a/media/codec2/sfplugin/InputSurfaceWrapper.h
+++ b/media/codec2/sfplugin/InputSurfaceWrapper.h
@@ -61,24 +61,24 @@
/// Input Surface configuration
struct Config {
// IN PARAMS (GBS)
- float mMinFps; // minimum fps (repeat frame to achieve this)
- float mMaxFps; // max fps (via frame drop)
- float mCaptureFps; // capture fps
- float mCodedFps; // coded fps
- bool mSuspended; // suspended
- int64_t mTimeOffsetUs; // time offset (input => codec)
- int64_t mSuspendAtUs; // suspend/resume time
- int64_t mStartAtUs; // start time
- bool mStopped; // stopped
- int64_t mStopAtUs; // stop time
+ float mMinFps = 0.0; // minimum fps (repeat frame to achieve this)
+ float mMaxFps = 0.0; // max fps (via frame drop)
+ float mCaptureFps = 0.0; // capture fps
+ float mCodedFps = 0.0; // coded fps
+ bool mSuspended = false; // suspended
+ int64_t mTimeOffsetUs = 0; // time offset (input => codec)
+ int64_t mSuspendAtUs = 0; // suspend/resume time
+ int64_t mStartAtUs = 0; // start time
+ bool mStopped = false; // stopped
+ int64_t mStopAtUs = 0; // stop time
// OUT PARAMS (GBS)
- int64_t mInputDelayUs; // delay between encoder input and surface input
+ int64_t mInputDelayUs = 0; // delay between encoder input and surface input
// IN PARAMS (CODEC WRAPPER)
- float mFixedAdjustedFps; // fixed fps via PTS manipulation
- float mMinAdjustedFps; // minimum fps via PTS manipulation
- uint64_t mUsage; // consumer usage
+ float mFixedAdjustedFps = 0.0; // fixed fps via PTS manipulation
+ float mMinAdjustedFps = 0.0; // minimum fps via PTS manipulation
+ uint64_t mUsage = 0; // consumer usage
};
/**
diff --git a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
index 5bee605..ad8f6e5 100644
--- a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
+++ b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
@@ -18,22 +18,31 @@
#include <gtest/gtest.h>
+#include <media/stagefright/foundation/AString.h>
#include <media/stagefright/MediaCodecConstants.h>
+#include <C2BlockInternal.h>
#include <C2PlatformSupport.h>
namespace android {
+static std::shared_ptr<RawGraphicOutputBuffers> GetRawGraphicOutputBuffers(
+ int32_t width, int32_t height) {
+ std::shared_ptr<RawGraphicOutputBuffers> buffers =
+ std::make_shared<RawGraphicOutputBuffers>("test");
+ sp<AMessage> format{new AMessage};
+ format->setInt32(KEY_WIDTH, width);
+ format->setInt32(KEY_HEIGHT, height);
+ buffers->setFormat(format);
+ return buffers;
+}
+
TEST(RawGraphicOutputBuffersTest, ChangeNumSlots) {
constexpr int32_t kWidth = 3840;
constexpr int32_t kHeight = 2160;
std::shared_ptr<RawGraphicOutputBuffers> buffers =
- std::make_shared<RawGraphicOutputBuffers>("test");
- sp<AMessage> format{new AMessage};
- format->setInt32("width", kWidth);
- format->setInt32("height", kHeight);
- buffers->setFormat(format);
+ GetRawGraphicOutputBuffers(kWidth, kHeight);
std::shared_ptr<C2BlockPool> pool;
ASSERT_EQ(OK, GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, nullptr, &pool));
@@ -96,4 +105,435 @@
}
}
+class TestGraphicAllocation : public C2GraphicAllocation {
+public:
+ TestGraphicAllocation(
+ uint32_t width,
+ uint32_t height,
+ const C2PlanarLayout &layout,
+ size_t capacity,
+ std::vector<size_t> offsets)
+ : C2GraphicAllocation(width, height),
+ mLayout(layout),
+ mMemory(capacity, 0xAA),
+ mOffsets(offsets) {
+ }
+
+ c2_status_t map(
+ C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
+ C2PlanarLayout *layout, uint8_t **addr) override {
+ (void)rect;
+ (void)usage;
+ (void)fence;
+ *layout = mLayout;
+ for (size_t i = 0; i < mLayout.numPlanes; ++i) {
+ addr[i] = mMemory.data() + mOffsets[i];
+ }
+ return C2_OK;
+ }
+
+ c2_status_t unmap(uint8_t **, C2Rect, C2Fence *) override { return C2_OK; }
+
+ C2Allocator::id_t getAllocatorId() const override { return -1; }
+
+ const C2Handle *handle() const override { return nullptr; }
+
+ bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override {
+ return other.get() == this;
+ }
+
+private:
+ C2PlanarLayout mLayout;
+ std::vector<uint8_t> mMemory;
+ std::vector<uint8_t *> mAddr;
+ std::vector<size_t> mOffsets;
+};
+
+class LayoutTest : public ::testing::TestWithParam<std::tuple<bool, std::string, bool, int32_t>> {
+private:
+ static C2PlanarLayout YUVPlanarLayout(int32_t stride) {
+ C2PlanarLayout layout = {
+ C2PlanarLayout::TYPE_YUV,
+ 3, /* numPlanes */
+ 3, /* rootPlanes */
+ {}, /* planes --- to be filled below */
+ };
+ layout.planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y,
+ 1, /* colInc */
+ stride, /* rowInc */
+ 1, /* colSampling */
+ 1, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_Y, /* rootIx */
+ 0, /* offset */
+ };
+ layout.planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB,
+ 1, /* colInc */
+ stride / 2, /* rowInc */
+ 2, /* colSampling */
+ 2, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_U, /* rootIx */
+ 0, /* offset */
+ };
+ layout.planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR,
+ 1, /* colInc */
+ stride / 2, /* rowInc */
+ 2, /* colSampling */
+ 2, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_V, /* rootIx */
+ 0, /* offset */
+ };
+ return layout;
+ }
+
+ static C2PlanarLayout YUVSemiPlanarLayout(int32_t stride) {
+ C2PlanarLayout layout = {
+ C2PlanarLayout::TYPE_YUV,
+ 3, /* numPlanes */
+ 2, /* rootPlanes */
+ {}, /* planes --- to be filled below */
+ };
+ layout.planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y,
+ 1, /* colInc */
+ stride, /* rowInc */
+ 1, /* colSampling */
+ 1, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_Y, /* rootIx */
+ 0, /* offset */
+ };
+ layout.planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB,
+ 2, /* colInc */
+ stride, /* rowInc */
+ 2, /* colSampling */
+ 2, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_U, /* rootIx */
+ 0, /* offset */
+ };
+ layout.planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR,
+ 2, /* colInc */
+ stride, /* rowInc */
+ 2, /* colSampling */
+ 2, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_U, /* rootIx */
+ 1, /* offset */
+ };
+ return layout;
+ }
+
+ static C2PlanarLayout YVUSemiPlanarLayout(int32_t stride) {
+ C2PlanarLayout layout = {
+ C2PlanarLayout::TYPE_YUV,
+ 3, /* numPlanes */
+ 2, /* rootPlanes */
+ {}, /* planes --- to be filled below */
+ };
+ layout.planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y,
+ 1, /* colInc */
+ stride, /* rowInc */
+ 1, /* colSampling */
+ 1, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_Y, /* rootIx */
+ 0, /* offset */
+ };
+ layout.planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB,
+ 2, /* colInc */
+ stride, /* rowInc */
+ 2, /* colSampling */
+ 2, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_V, /* rootIx */
+ 1, /* offset */
+ };
+ layout.planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR,
+ 2, /* colInc */
+ stride, /* rowInc */
+ 2, /* colSampling */
+ 2, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_V, /* rootIx */
+ 0, /* offset */
+ };
+ return layout;
+ }
+
+ static std::shared_ptr<C2GraphicBlock> CreateGraphicBlock(
+ uint32_t width,
+ uint32_t height,
+ const C2PlanarLayout &layout,
+ size_t capacity,
+ std::vector<size_t> offsets) {
+ std::shared_ptr<C2GraphicAllocation> alloc = std::make_shared<TestGraphicAllocation>(
+ width,
+ height,
+ layout,
+ capacity,
+ offsets);
+
+ return _C2BlockFactory::CreateGraphicBlock(alloc);
+ }
+
+ static constexpr uint8_t GetPixelValue(uint8_t value, uint32_t row, uint32_t col) {
+ return (uint32_t(value) * row + col) & 0xFF;
+ }
+
+ static void FillPlane(C2GraphicView &view, size_t index, uint8_t value) {
+ C2PlanarLayout layout = view.layout();
+
+ uint8_t *rowPtr = view.data()[index];
+ C2PlaneInfo plane = layout.planes[index];
+ for (uint32_t row = 0; row < view.height() / plane.rowSampling; ++row) {
+ uint8_t *colPtr = rowPtr;
+ for (uint32_t col = 0; col < view.width() / plane.colSampling; ++col) {
+ *colPtr = GetPixelValue(value, row, col);
+ colPtr += plane.colInc;
+ }
+ rowPtr += plane.rowInc;
+ }
+ }
+
+ static void FillBlock(const std::shared_ptr<C2GraphicBlock> &block) {
+ C2GraphicView view = block->map().get();
+
+ FillPlane(view, C2PlanarLayout::PLANE_Y, 'Y');
+ FillPlane(view, C2PlanarLayout::PLANE_U, 'U');
+ FillPlane(view, C2PlanarLayout::PLANE_V, 'V');
+ }
+
+ static bool VerifyPlane(
+ const MediaImage2 *mediaImage,
+ const uint8_t *base,
+ uint32_t index,
+ uint8_t value,
+ std::string *errorMsg) {
+ *errorMsg = "";
+ MediaImage2::PlaneInfo plane = mediaImage->mPlane[index];
+ const uint8_t *rowPtr = base + plane.mOffset;
+ for (uint32_t row = 0; row < mediaImage->mHeight / plane.mVertSubsampling; ++row) {
+ const uint8_t *colPtr = rowPtr;
+ for (uint32_t col = 0; col < mediaImage->mWidth / plane.mHorizSubsampling; ++col) {
+ if (GetPixelValue(value, row, col) != *colPtr) {
+ *errorMsg = AStringPrintf("row=%u col=%u expected=%02x actual=%02x",
+ row, col, GetPixelValue(value, row, col), *colPtr).c_str();
+ return false;
+ }
+ colPtr += plane.mColInc;
+ }
+ rowPtr += plane.mRowInc;
+ }
+ return true;
+ }
+
+public:
+ static constexpr int32_t kWidth = 320;
+ static constexpr int32_t kHeight = 240;
+ static constexpr int32_t kGapLength = kWidth * kHeight * 10;
+
+ static std::shared_ptr<C2Buffer> CreateAndFillBufferFromParam(const ParamType ¶m) {
+ bool contiguous = std::get<0>(param);
+ std::string planeOrderStr = std::get<1>(param);
+ bool planar = std::get<2>(param);
+ int32_t stride = std::get<3>(param);
+
+ C2PlanarLayout::plane_index_t planeOrder[3];
+ C2PlanarLayout layout;
+
+ if (planeOrderStr.size() != 3) {
+ return nullptr;
+ }
+ for (size_t i = 0; i < 3; ++i) {
+ C2PlanarLayout::plane_index_t planeIndex;
+ switch (planeOrderStr[i]) {
+ case 'Y': planeIndex = C2PlanarLayout::PLANE_Y; break;
+ case 'U': planeIndex = C2PlanarLayout::PLANE_U; break;
+ case 'V': planeIndex = C2PlanarLayout::PLANE_V; break;
+ default: return nullptr;
+ }
+ planeOrder[i] = planeIndex;
+ }
+
+ if (planar) {
+ layout = YUVPlanarLayout(stride);
+ } else { // semi-planar
+ for (size_t i = 0; i < 3; ++i) {
+ if (planeOrder[i] == C2PlanarLayout::PLANE_U) {
+ layout = YUVSemiPlanarLayout(stride);
+ break;
+ }
+ if (planeOrder[i] == C2PlanarLayout::PLANE_V) {
+ layout = YVUSemiPlanarLayout(stride);
+ break;
+ }
+ }
+ }
+
+ size_t yPlaneSize = stride * kHeight;
+ size_t uvPlaneSize = stride * kHeight / 4;
+ size_t capacity = yPlaneSize + uvPlaneSize * 2;
+ std::vector<size_t> offsets(3);
+
+ if (!contiguous) {
+ if (planar) {
+ capacity += kGapLength * 2;
+ } else { // semi-planar
+ capacity += kGapLength;
+ }
+ }
+
+ offsets[planeOrder[0]] = 0;
+ size_t planeSize = (planeOrder[0] == C2PlanarLayout::PLANE_Y) ? yPlaneSize : uvPlaneSize;
+ for (size_t i = 1; i < 3; ++i) {
+ offsets[planeOrder[i]] = offsets[planeOrder[i - 1]] + planeSize;
+ if (!contiguous) {
+ offsets[planeOrder[i]] += kGapLength;
+ }
+ planeSize = (planeOrder[i] == C2PlanarLayout::PLANE_Y) ? yPlaneSize : uvPlaneSize;
+ if (!planar // semi-planar
+ && planeOrder[i - 1] != C2PlanarLayout::PLANE_Y
+ && planeOrder[i] != C2PlanarLayout::PLANE_Y) {
+ offsets[planeOrder[i]] = offsets[planeOrder[i - 1]] + 1;
+ planeSize = uvPlaneSize * 2 - 1;
+ }
+ }
+
+ std::shared_ptr<C2GraphicBlock> block = CreateGraphicBlock(
+ kWidth,
+ kHeight,
+ layout,
+ capacity,
+ offsets);
+ FillBlock(block);
+ return C2Buffer::CreateGraphicBuffer(
+ block->share(block->crop(), C2Fence()));
+ }
+
+ static bool VerifyClientBuffer(
+ const sp<MediaCodecBuffer> &buffer, std::string *errorMsg) {
+ *errorMsg = "";
+ sp<ABuffer> imageData;
+ if (!buffer->format()->findBuffer("image-data", &imageData)) {
+ *errorMsg = "Missing image data";
+ return false;
+ }
+ MediaImage2 *mediaImage = (MediaImage2 *)imageData->data();
+ if (mediaImage->mType != MediaImage2::MEDIA_IMAGE_TYPE_YUV) {
+ *errorMsg = AStringPrintf("Unexpected type: %d", mediaImage->mType).c_str();
+ return false;
+ }
+ std::string planeErrorMsg;
+ if (!VerifyPlane(mediaImage, buffer->base(), MediaImage2::Y, 'Y', &planeErrorMsg)) {
+ *errorMsg = "Y plane does not match: " + planeErrorMsg;
+ return false;
+ }
+ if (!VerifyPlane(mediaImage, buffer->base(), MediaImage2::U, 'U', &planeErrorMsg)) {
+ *errorMsg = "U plane does not match: " + planeErrorMsg;
+ return false;
+ }
+ if (!VerifyPlane(mediaImage, buffer->base(), MediaImage2::V, 'V', &planeErrorMsg)) {
+ *errorMsg = "V plane does not match: " + planeErrorMsg;
+ return false;
+ }
+
+ int32_t width, height, stride;
+ buffer->format()->findInt32(KEY_WIDTH, &width);
+ buffer->format()->findInt32(KEY_HEIGHT, &height);
+ buffer->format()->findInt32(KEY_STRIDE, &stride);
+
+ MediaImage2 legacyYLayout = {
+ MediaImage2::MEDIA_IMAGE_TYPE_Y,
+ 1, // mNumPlanes
+ uint32_t(width),
+ uint32_t(height),
+ 8,
+ 8,
+ {}, // mPlane
+ };
+ legacyYLayout.mPlane[MediaImage2::Y] = {
+ 0, // mOffset
+ 1, // mColInc
+ stride, // mRowInc
+ 1, // mHorizSubsampling
+ 1, // mVertSubsampling
+ };
+ if (!VerifyPlane(&legacyYLayout, buffer->data(), MediaImage2::Y, 'Y', &planeErrorMsg)) {
+ *errorMsg = "Y plane by legacy layout does not match: " + planeErrorMsg;
+ return false;
+ }
+ return true;
+ }
+
+};
+
+TEST_P(LayoutTest, VerifyLayout) {
+ std::shared_ptr<RawGraphicOutputBuffers> buffers =
+ GetRawGraphicOutputBuffers(kWidth, kHeight);
+
+ std::shared_ptr<C2Buffer> c2Buffer = CreateAndFillBufferFromParam(GetParam());
+ ASSERT_NE(nullptr, c2Buffer);
+ sp<MediaCodecBuffer> clientBuffer;
+ size_t index;
+ ASSERT_EQ(OK, buffers->registerBuffer(c2Buffer, &index, &clientBuffer));
+ ASSERT_NE(nullptr, clientBuffer);
+ std::string errorMsg;
+ ASSERT_TRUE(VerifyClientBuffer(clientBuffer, &errorMsg)) << errorMsg;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ RawGraphicOutputBuffersTest,
+ LayoutTest,
+ ::testing::Combine(
+ ::testing::Bool(), /* contiguous */
+ ::testing::Values("YUV", "YVU", "UVY", "VUY"),
+ ::testing::Bool(), /* planar */
+ ::testing::Values(320, 512)),
+ [](const ::testing::TestParamInfo<LayoutTest::ParamType> &info) {
+ std::string contiguous = std::get<0>(info.param) ? "Contiguous" : "Noncontiguous";
+ std::string planar = std::get<2>(info.param) ? "Planar" : "SemiPlanar";
+ return contiguous
+ + std::get<1>(info.param)
+ + planar
+ + std::to_string(std::get<3>(info.param));
+ });
+
} // namespace android
diff --git a/media/codec2/sfplugin/utils/Android.bp b/media/codec2/sfplugin/utils/Android.bp
index 6287221..e7dc92a 100644
--- a/media/codec2/sfplugin/utils/Android.bp
+++ b/media/codec2/sfplugin/utils/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libsfplugin_ccodec_utils",
vendor_available: true,
min_sdk_version: "29",
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index 60f4736..19afccf 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -13,7 +13,7 @@
// !!!DO NOT DEPEND ON THIS SHARED LIBRARY DIRECTLY!!!
// use libcodec2-impl-defaults instead
-cc_library_shared {
+cc_library {
name: "libcodec2_vndk",
vendor_available: true,
min_sdk_version: "29",
diff --git a/media/codec2/vndk/C2DmaBufAllocator.cpp b/media/codec2/vndk/C2DmaBufAllocator.cpp
index 59e82e2..750aa31 100644
--- a/media/codec2/vndk/C2DmaBufAllocator.cpp
+++ b/media/codec2/vndk/C2DmaBufAllocator.cpp
@@ -315,8 +315,8 @@
if (mUsageMapper) {
res = mUsageMapper(usage, capacity, heap_name, flags);
} else {
- // No system-uncached yet, so disabled for now
- if (0 && !(usage.expected & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE)))
+ if (C2DmaBufAllocator::system_uncached_supported() &&
+ !(usage.expected & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE)))
*heap_name = "system-uncached";
else
*heap_name = "system";
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 1e907c1..dee3bf6 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -622,6 +622,12 @@
std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
C2PlatformComponentStore();
+ // For testing only
+ C2PlatformComponentStore(
+ std::vector<std::tuple<C2String,
+ C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc>>);
+
virtual ~C2PlatformComponentStore() override = default;
private:
@@ -662,6 +668,24 @@
}
/**
+ * Creates an uninitialized component module.
+ * NOTE: For testing only
+ *
+ * \param name[in] component name.
+ *
+ * \note Only used by ComponentLoader.
+ */
+ ComponentModule(
+ C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
+ C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
+ : mInit(C2_NO_INIT),
+ mLibHandle(nullptr),
+ createFactory(createFactory),
+ destroyFactory(destroyFactory),
+ mComponentFactory(nullptr) {
+ }
+
+ /**
* Initializes a component module with a given library path. Must be called exactly once.
*
* \note Only used by ComponentLoader.
@@ -717,7 +741,13 @@
std::lock_guard<std::mutex> lock(mMutex);
std::shared_ptr<ComponentModule> localModule = mModule.lock();
if (localModule == nullptr) {
- localModule = std::make_shared<ComponentModule>();
+ if(mCreateFactory) {
+ // For testing only
+ localModule = std::make_shared<ComponentModule>(mCreateFactory,
+ mDestroyFactory);
+ } else {
+ localModule = std::make_shared<ComponentModule>();
+ }
res = localModule->init(mLibPath);
if (res == C2_OK) {
mModule = localModule;
@@ -733,10 +763,22 @@
ComponentLoader(std::string libPath)
: mLibPath(libPath) {}
+ // For testing only
+ ComponentLoader(std::tuple<C2String,
+ C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc> func)
+ : mLibPath(std::get<0>(func)),
+ mCreateFactory(std::get<1>(func)),
+ mDestroyFactory(std::get<2>(func)) {}
+
private:
std::mutex mMutex; ///< mutex guarding the module
std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
std::string mLibPath; ///< library path
+
+ // For testing only
+ C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
+ C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
};
struct Interface : public C2InterfaceHelper {
@@ -780,7 +822,13 @@
};
static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
- strncpy(me.set().m.heapName, "system", me.v.flexCount());
+ long long usage = (long long)me.get().m.usage;
+ if (C2DmaBufAllocator::system_uncached_supported() &&
+ !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
+ strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
+ } else {
+ strncpy(me.set().m.heapName, "system", me.v.flexCount());
+ }
me.set().m.allocFlags = 0;
return C2R::Ok();
};
@@ -846,25 +894,33 @@
std::shared_ptr<C2ReflectorHelper> mReflector;
Interface mInterface;
+
+ // For testing only
+ std::vector<std::tuple<C2String,
+ C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
};
c2_status_t C2PlatformComponentStore::ComponentModule::init(
std::string libPath) {
ALOGV("in %s", __func__);
ALOGV("loading dll");
- mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
- LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
- "could not dlopen %s: %s", libPath.c_str(), dlerror());
- createFactory =
- (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
- LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
- "createFactory is null in %s", libPath.c_str());
+ if(!createFactory) {
+ mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
+ LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
+ "could not dlopen %s: %s", libPath.c_str(), dlerror());
- destroyFactory =
- (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
- LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
- "destroyFactory is null in %s", libPath.c_str());
+ createFactory =
+ (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
+ LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
+ "createFactory is null in %s", libPath.c_str());
+
+ destroyFactory =
+ (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
+ LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
+ "destroyFactory is null in %s", libPath.c_str());
+ }
mComponentFactory = createFactory();
if (mComponentFactory == nullptr) {
@@ -1065,6 +1121,22 @@
emplace("libcodec2_soft_vp8enc.so");
emplace("libcodec2_soft_vp9dec.so");
emplace("libcodec2_soft_vp9enc.so");
+
+}
+
+// For testing only
+C2PlatformComponentStore::C2PlatformComponentStore(
+ std::vector<std::tuple<C2String,
+ C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
+ : mVisited(false),
+ mReflector(std::make_shared<C2ReflectorHelper>()),
+ mInterface(mReflector),
+ mCodec2FactoryFuncs(funcs) {
+
+ for(auto const& func: mCodec2FactoryFuncs) {
+ mComponents.emplace(std::get<0>(func), func);
+ }
}
c2_status_t C2PlatformComponentStore::copyBuffer(
@@ -1184,4 +1256,11 @@
return store;
}
+// For testing only
+std::shared_ptr<C2ComponentStore> GetTestComponentStore(
+ std::vector<std::tuple<C2String,
+ C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
+ return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
+}
} // namespace android
diff --git a/media/codec2/vndk/include/C2DmaBufAllocator.h b/media/codec2/vndk/include/C2DmaBufAllocator.h
index abb8307..d84c8c6 100644
--- a/media/codec2/vndk/include/C2DmaBufAllocator.h
+++ b/media/codec2/vndk/include/C2DmaBufAllocator.h
@@ -84,6 +84,16 @@
void setUsageMapper(const UsageMapperFn& mapper, uint64_t minUsage, uint64_t maxUsage,
uint64_t blockSize);
+ static bool system_uncached_supported(void) {
+ static int cached_result = -1;
+
+ if (cached_result == -1) {
+ struct stat buffer;
+ cached_result = (stat("/dev/dma_heap/system-uncached", &buffer) == 0);
+ }
+ return (cached_result == 1);
+ };
+
private:
c2_status_t mInit;
BufferAllocator mBufferAllocator;
diff --git a/media/codec2/vndk/include/C2PlatformSupport.h b/media/codec2/vndk/include/C2PlatformSupport.h
index 4814494..6d351c2 100644
--- a/media/codec2/vndk/include/C2PlatformSupport.h
+++ b/media/codec2/vndk/include/C2PlatformSupport.h
@@ -144,6 +144,15 @@
std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore();
/**
+ * Returns the platform component store.
+ * NOTE: For testing only
+ * \retval nullptr if the platform component store could not be obtained
+ */
+std::shared_ptr<C2ComponentStore> GetTestComponentStore(
+ std::vector<std::tuple<C2String, C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc>>);
+
+/**
* Sets the preferred component store in this process for the sole purpose of accessing its
* interface. If this is not called, the default IComponentStore HAL (if exists) is the preferred
* store for this purpose. If the default IComponentStore HAL is not present, the platform
diff --git a/media/codecs/amrwb/dec/src/wb_syn_filt.cpp b/media/codecs/amrwb/dec/src/wb_syn_filt.cpp
index d960322..f12828d 100644
--- a/media/codecs/amrwb/dec/src/wb_syn_filt.cpp
+++ b/media/codecs/amrwb/dec/src/wb_syn_filt.cpp
@@ -181,12 +181,14 @@
L_tmp4 = fxp_mac_16by16(yy[(i<<2)+3 - j], a[j], L_tmp4);
L_tmp1 = shl_int32(L_tmp1, 4);
+ L_tmp1 = L_tmp1 == INT32_MIN ? INT32_MIN + 1 : L_tmp1;
y[(i<<2)] = yy[(i<<2)] = amr_wb_round(-L_tmp1);
L_tmp2 = fxp_mac_16by16(yy[(i<<2)], a[1], L_tmp2);
L_tmp2 = shl_int32(L_tmp2, 4);
+ L_tmp2 = L_tmp2 == INT32_MIN ? INT32_MIN + 1 : L_tmp2;
y[(i<<2)+1] = yy[(i<<2)+1] = amr_wb_round(-L_tmp2);
@@ -197,12 +199,14 @@
L_tmp3 = fxp_mac_16by16(yy[(i<<2) + 1], a[1], L_tmp3);
L_tmp3 = shl_int32(L_tmp3, 4);
+ L_tmp3 = L_tmp3 == INT32_MIN ? INT32_MIN + 1 : L_tmp3;
y[(i<<2)+2] = yy[(i<<2)+2] = amr_wb_round(-L_tmp3);
L_tmp4 = fxp_mac_16by16(yy[(i<<2)+2], a[1], L_tmp4);
L_tmp4 = shl_int32(L_tmp4, 4);
+ L_tmp4 = L_tmp4 == INT32_MIN ? INT32_MIN + 1 : L_tmp4;
y[(i<<2)+3] = yy[(i<<2)+3] = amr_wb_round(-L_tmp4);
}
diff --git a/media/codecs/g711/decoder/Android.bp b/media/codecs/g711/decoder/Android.bp
index efff60b..51f4c38 100644
--- a/media/codecs/g711/decoder/Android.bp
+++ b/media/codecs/g711/decoder/Android.bp
@@ -35,7 +35,13 @@
],
cfi: true,
},
- apex_available: ["com.android.media.swcodec"],
+
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ "test_com.android.media.swcodec",
+ ],
+
min_sdk_version: "29",
target: {
diff --git a/media/codecs/m4v_h263/dec/src/vop.cpp b/media/codecs/m4v_h263/dec/src/vop.cpp
index 335846c..7b32498 100644
--- a/media/codecs/m4v_h263/dec/src/vop.cpp
+++ b/media/codecs/m4v_h263/dec/src/vop.cpp
@@ -497,6 +497,13 @@
}
while ((qmat[*(zigzag_inv+i)] != 0) && (++i < 64));
+ /* qmatrix must have at least one non-zero value, which means
+ i would be non-zero in valid cases */
+ if (i == 0)
+ {
+ return PV_FAIL;
+ }
+
for (j = i; j < 64; j++)
qmat[*(zigzag_inv+j)] = qmat[*(zigzag_inv+i-1)];
}
@@ -520,6 +527,13 @@
}
while ((qmat[*(zigzag_inv+i)] != 0) && (++i < 64));
+ /* qmatrix must have at least one non-zero value, which means
+ i would be non-zero in valid cases */
+ if (i == 0)
+ {
+ return PV_FAIL;
+ }
+
for (j = i; j < 64; j++)
qmat[*(zigzag_inv+j)] = qmat[*(zigzag_inv+i-1)];
}
diff --git a/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
index 7ab8f45..30e4fda 100644
--- a/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
+++ b/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
@@ -491,6 +491,9 @@
}
for (i = 0; i < encParams->nLayers; i++)
{
+ if (encOption->encHeight[i] == 0 || encOption->encWidth[i] == 0 ||
+ encOption->encHeight[i] % 16 != 0 || encOption->encWidth[i] % 16 != 0)
+ goto CLEAN_UP;
encParams->LayerHeight[i] = encOption->encHeight[i];
encParams->LayerWidth[i] = encOption->encWidth[i];
}
diff --git a/media/codecs/mp3dec/Android.bp b/media/codecs/mp3dec/Android.bp
index 1acf0a6..f84da21 100644
--- a/media/codecs/mp3dec/Android.bp
+++ b/media/codecs/mp3dec/Android.bp
@@ -1,3 +1,18 @@
+cc_library_headers {
+ name: "libstagefright_mp3dec_headers",
+ vendor_available: true,
+ min_sdk_version: "29",
+ host_supported:true,
+ export_include_dirs: [
+ "include",
+ "src",
+ ],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ ],
+}
+
cc_library_static {
name: "libstagefright_mp3dec",
vendor_available: true,
@@ -65,10 +80,8 @@
include_dirs: ["frameworks/av/media/libstagefright/include"],
- export_include_dirs: [
- "include",
- "src",
- ],
+ header_libs: ["libstagefright_mp3dec_headers"],
+ export_header_lib_headers: ["libstagefright_mp3dec_headers"],
cflags: [
"-DOSCL_UNUSED_ARG(x)=(void)(x)",
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index 0617e88..ec7cb24 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -561,6 +561,8 @@
AMediaFormat_setString(mFileMetadata,
AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC);
}
+ mMaxBufferSize = getMaxBlockSize() * getChannels() * getOutputSampleSize();
+ AMediaFormat_setInt32(mTrackMetadata, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, mMaxBufferSize);
return OK;
}
@@ -568,8 +570,6 @@
{
CHECK(mGroup == NULL);
mGroup = group;
- mMaxBufferSize = getMaxBlockSize() * getChannels() * getOutputSampleSize();
- AMediaFormat_setInt32(mTrackMetadata, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, mMaxBufferSize);
mGroup->add_buffer(mMaxBufferSize);
}
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index ded3d1a..444664c 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -80,13 +80,15 @@
Vector<uint32_t> thumbnails;
Vector<uint32_t> dimgRefs;
- Vector<uint32_t> cdscRefs;
+ Vector<uint32_t> exifRefs;
+ Vector<uint32_t> xmpRefs;
size_t nextTileIndex;
};
-struct ExifItem {
+struct ExternalMetaItem {
off64_t offset;
size_t size;
+ bool isExif;
};
/////////////////////////////////////////////////////////////////////
@@ -482,7 +484,7 @@
void apply(
KeyedVector<uint32_t, ImageItem> &itemIdToItemMap,
- KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const;
+ KeyedVector<uint32_t, ExternalMetaItem> &itemIdToMetaMap) const;
private:
uint32_t mItemId;
@@ -494,7 +496,7 @@
void ItemReference::apply(
KeyedVector<uint32_t, ImageItem> &itemIdToItemMap,
- KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const {
+ KeyedVector<uint32_t, ExternalMetaItem> &itemIdToMetaMap) const {
ALOGV("attach reference type 0x%x to item id %d)", type(), mItemId);
switch(type()) {
@@ -556,15 +558,15 @@
break;
}
case FOURCC("cdsc"): {
- ssize_t itemIndex = itemIdToExifMap.indexOfKey(mItemId);
+ ssize_t metaIndex = itemIdToMetaMap.indexOfKey(mItemId);
- // ignore non-exif block items
- if (itemIndex < 0) {
+ // ignore non-meta items
+ if (metaIndex < 0) {
return;
}
for (size_t i = 0; i < mRefs.size(); i++) {
- itemIndex = itemIdToItemMap.indexOfKey(mRefs[i]);
+ ssize_t itemIndex = itemIdToItemMap.indexOfKey(mRefs[i]);
// ignore non-image items
if (itemIndex < 0) {
@@ -572,7 +574,11 @@
}
ALOGV("Image item id %d uses metadata item id %d", mRefs[i], mItemId);
ImageItem &image = itemIdToItemMap.editValueAt(itemIndex);
- image.cdscRefs.push_back(mItemId);
+ if (itemIdToMetaMap[metaIndex].isExif) {
+ image.exifRefs.push_back(mItemId);
+ } else {
+ image.xmpRefs.push_back(mItemId);
+ }
}
break;
}
@@ -1065,7 +1071,21 @@
struct ItemInfo {
uint32_t itemId;
uint32_t itemType;
+ String8 contentType;
bool hidden;
+
+ bool isXmp() const {
+ return itemType == FOURCC("mime") && contentType == String8("application/rdf+xml");
+ }
+ bool isExif() const {
+ return itemType == FOURCC("Exif");
+ }
+ bool isGrid() const {
+ return itemType == FOURCC("grid");
+ }
+ bool isSample() const {
+ return itemType == FOURCC("av01") || itemType == FOURCC("hvc1");
+ }
};
struct InfeBox : public FullBox {
@@ -1155,6 +1175,7 @@
if (!parseNullTerminatedString(&offset, &size, &content_type)) {
return ERROR_MALFORMED;
}
+ itemInfo->contentType = content_type;
// content_encoding is optional; can be omitted if would be empty
if (size > 0) {
@@ -1175,18 +1196,18 @@
struct IinfBox : public FullBox {
IinfBox(DataSourceHelper *source, Vector<ItemInfo> *itemInfos) :
- FullBox(source, FOURCC("iinf")), mItemInfos(itemInfos) {}
+ FullBox(source, FOURCC("iinf")), mItemInfos(itemInfos), mNeedIref(false) {}
status_t parse(off64_t offset, size_t size);
- bool hasFourCC(uint32_t type) { return mFourCCSeen.count(type) > 0; }
+ bool needIrefBox() { return mNeedIref; }
protected:
status_t onChunkData(uint32_t type, off64_t offset, size_t size) override;
private:
Vector<ItemInfo> *mItemInfos;
- std::unordered_set<uint32_t> mFourCCSeen;
+ bool mNeedIref;
};
status_t IinfBox::parse(off64_t offset, size_t size) {
@@ -1233,7 +1254,7 @@
status_t err = infeBox.parse(offset, size, &itemInfo);
if (err == OK) {
mItemInfos->push_back(itemInfo);
- mFourCCSeen.insert(itemInfo.itemType);
+ mNeedIref |= (itemInfo.isExif() || itemInfo.isXmp() || itemInfo.isGrid());
}
// InfeBox parse returns ERROR_UNSUPPORTED if the box if an unsupported
// version. Ignore this error as it's not fatal.
@@ -1323,7 +1344,7 @@
return err;
}
- if (iinfBox.hasFourCC(FOURCC("grid")) || iinfBox.hasFourCC(FOURCC("Exif"))) {
+ if (iinfBox.needIrefBox()) {
mRequiredBoxes.insert('iref');
}
@@ -1399,12 +1420,9 @@
// Only handle 3 types of items, all others are ignored:
// 'grid': derived image from tiles
- // 'hvc1': coded image (or tile)
- // 'Exif': EXIF metadata
- if (info.itemType != FOURCC("grid") &&
- info.itemType != FOURCC("hvc1") &&
- info.itemType != FOURCC("Exif") &&
- info.itemType != FOURCC("av01")) {
+ // 'hvc1' or 'av01': coded image (or tile)
+ // 'Exif' or XMP: metadata
+ if (!info.isGrid() && !info.isSample() && !info.isExif() && !info.isXmp()) {
continue;
}
@@ -1427,15 +1445,18 @@
return ERROR_MALFORMED;
}
- if (info.itemType == FOURCC("Exif")) {
- // Only add if the Exif data is non-empty. The first 4 bytes contain
+ if (info.isExif() || info.isXmp()) {
+ // Only add if the meta is non-empty. For Exif, the first 4 bytes contain
// the offset to TIFF header, which the Exif parser doesn't use.
- if (size > 4) {
- ExifItem exifItem = {
+ ALOGV("adding meta to mItemIdToMetaMap: isExif %d, offset %lld, size %lld",
+ info.isExif(), (long long)offset, (long long)size);
+ if ((info.isExif() && size > 4) || (info.isXmp() && size > 0)) {
+ ExternalMetaItem metaItem = {
+ .isExif = info.isExif(),
.offset = offset,
.size = size,
};
- mItemIdToExifMap.add(info.itemId, exifItem);
+ mItemIdToMetaMap.add(info.itemId, metaItem);
}
continue;
}
@@ -1470,7 +1491,7 @@
}
for (size_t i = 0; i < mItemReferences.size(); i++) {
- mItemReferences[i]->apply(mItemIdToItemMap, mItemIdToExifMap);
+ mItemReferences[i]->apply(mItemIdToItemMap, mItemIdToMetaMap);
}
bool foundPrimary = false;
@@ -1747,11 +1768,11 @@
}
const ImageItem &image = mItemIdToItemMap[itemIndex];
- if (image.cdscRefs.size() == 0) {
+ if (image.exifRefs.size() == 0) {
return NAME_NOT_FOUND;
}
- ssize_t exifIndex = mItemIdToExifMap.indexOfKey(image.cdscRefs[0]);
+ ssize_t exifIndex = mItemIdToMetaMap.indexOfKey(image.exifRefs[0]);
if (exifIndex < 0) {
return NAME_NOT_FOUND;
}
@@ -1759,7 +1780,7 @@
// skip the first 4-byte of the offset to TIFF header
uint32_t tiffOffset;
if (!mDataSource->readAt(
- mItemIdToExifMap[exifIndex].offset, &tiffOffset, 4)) {
+ mItemIdToMetaMap[exifIndex].offset, &tiffOffset, 4)) {
return ERROR_IO;
}
@@ -1772,16 +1793,43 @@
// exif data. The size of the item should be > 4 for a non-empty exif (this
// was already checked when the item was added). Also check that the tiff
// header offset is valid.
- if (mItemIdToExifMap[exifIndex].size <= 4 ||
- tiffOffset > mItemIdToExifMap[exifIndex].size - 4) {
+ if (mItemIdToMetaMap[exifIndex].size <= 4 ||
+ tiffOffset > mItemIdToMetaMap[exifIndex].size - 4) {
return ERROR_MALFORMED;
}
// Offset of 'Exif\0\0' relative to the beginning of 'Exif' item
// (first 4-byte is the tiff header offset)
uint32_t exifOffset = 4 + tiffOffset - 6;
- *offset = mItemIdToExifMap[exifIndex].offset + exifOffset;
- *size = mItemIdToExifMap[exifIndex].size - exifOffset;
+ *offset = mItemIdToMetaMap[exifIndex].offset + exifOffset;
+ *size = mItemIdToMetaMap[exifIndex].size - exifOffset;
+ return OK;
+}
+
+status_t ItemTable::getXmpOffsetAndSize(off64_t *offset, size_t *size) {
+ if (!mImageItemsValid) {
+ return INVALID_OPERATION;
+ }
+
+ ssize_t itemIndex = mItemIdToItemMap.indexOfKey(mPrimaryItemId);
+
+ // this should not happen, something's seriously wrong.
+ if (itemIndex < 0) {
+ return INVALID_OPERATION;
+ }
+
+ const ImageItem &image = mItemIdToItemMap[itemIndex];
+ if (image.xmpRefs.size() == 0) {
+ return NAME_NOT_FOUND;
+ }
+
+ ssize_t xmpIndex = mItemIdToMetaMap.indexOfKey(image.xmpRefs[0]);
+ if (xmpIndex < 0) {
+ return NAME_NOT_FOUND;
+ }
+
+ *offset = mItemIdToMetaMap[xmpIndex].offset;
+ *size = mItemIdToMetaMap[xmpIndex].size;
return OK;
}
diff --git a/media/extractors/mp4/ItemTable.h b/media/extractors/mp4/ItemTable.h
index b19dc18..62826b6 100644
--- a/media/extractors/mp4/ItemTable.h
+++ b/media/extractors/mp4/ItemTable.h
@@ -34,7 +34,7 @@
struct AssociationEntry;
struct ImageItem;
-struct ExifItem;
+struct ExternalMetaItem;
struct ItemLoc;
struct ItemInfo;
struct ItemProperty;
@@ -59,6 +59,7 @@
status_t getImageOffsetAndSize(
uint32_t *itemIndex, off64_t *offset, size_t *size);
status_t getExifOffsetAndSize(off64_t *offset, size_t *size);
+ status_t getXmpOffsetAndSize(off64_t *offset, size_t *size);
protected:
~ItemTable();
@@ -84,7 +85,7 @@
bool mImageItemsValid;
uint32_t mCurrentItemIndex;
KeyedVector<uint32_t, ImageItem> mItemIdToItemMap;
- KeyedVector<uint32_t, ExifItem> mItemIdToExifMap;
+ KeyedVector<uint32_t, ExternalMetaItem> mItemIdToMetaMap;
Vector<uint32_t> mDisplayables;
status_t parseIlocBox(off64_t offset, size_t size);
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 7989d4b..221bf4f 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -681,6 +681,19 @@
AMediaFormat_setInt64(mFileMetaData,
AMEDIAFORMAT_KEY_EXIF_SIZE, (int64_t)exifSize);
}
+ off64_t xmpOffset;
+ size_t xmpSize;
+ if (mItemTable->getXmpOffsetAndSize(&xmpOffset, &xmpSize) == OK) {
+ // TODO(chz): b/175717339
+ // Use a hard-coded string here instead of named keys. The keys are available
+ // only on API 31+. The mp4 extractor is part of mainline and has min_sdk_version
+ // of 29. This hard-coded string can be replaced with the named constant once
+ // the mp4 extractor is built against API 31+.
+ AMediaFormat_setInt64(mFileMetaData,
+ "xmp-offset" /*AMEDIAFORMAT_KEY_XMP_OFFSET*/, (int64_t)xmpOffset);
+ AMediaFormat_setInt64(mFileMetaData,
+ "xmp-size" /*AMEDIAFORMAT_KEY_XMP_SIZE*/, (int64_t)xmpSize);
+ }
for (uint32_t imageIndex = 0;
imageIndex < mItemTable->countImages(); imageIndex++) {
AMediaFormat *meta = mItemTable->getImageMeta(imageIndex);
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index 62f0808..eb2246d 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -43,9 +43,6 @@
long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
}
-static constexpr int OGG_PAGE_FLAG_CONTINUED_PACKET = 1;
-static constexpr int OGG_PAGE_FLAG_END_OF_STREAM = 4;
-
namespace android {
struct OggSource : public MediaTrackHelper {
@@ -300,8 +297,7 @@
AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
*out = packet;
- ALOGV("returning buffer %p, size %zu, length %zu",
- packet, packet->size(), packet->range_length());
+ ALOGV("returning buffer %p", packet);
return AMEDIA_OK;
}
@@ -362,10 +358,10 @@
if (!memcmp(signature, "OggS", 4)) {
if (*pageOffset > startOffset) {
- ALOGV("skipped %lld bytes of junk at %lld to reach next frame",
- (long long)(*pageOffset - startOffset), (long long)(startOffset));
+ ALOGV("skipped %lld bytes of junk to reach next frame",
+ (long long)(*pageOffset - startOffset));
}
- ALOGV("found frame at %lld", (long long)(*pageOffset));
+
return OK;
}
@@ -633,8 +629,7 @@
// Calculate timestamps by accumulating durations starting from the first sample of a page;
// We assume that we only seek to page boundaries.
AMediaFormat *meta = (*out)->meta_data();
- if (AMediaFormat_getInt32(meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, ¤tPageSamples) &&
- (mCurrentPage.mFlags & OGG_PAGE_FLAG_END_OF_STREAM)) {
+ if (AMediaFormat_getInt32(meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, ¤tPageSamples)) {
// first packet in page
if (mOffset == mFirstDataOffset) {
currentPageSamples -= mStartGranulePosition;
@@ -817,7 +812,6 @@
}
buffer = tmp;
- ALOGV("reading %zu bytes @ %zu", packetSize, size_t(dataOffset));
ssize_t n = mSource->readAt(
dataOffset,
(uint8_t *)buffer->data() + buffer->range_length(),
@@ -836,9 +830,8 @@
if (gotFullPacket) {
// We've just read the entire packet.
- ALOGV("got full packet, size %zu", fullSize);
- if (mFirstPacketInPage && (mCurrentPage.mFlags & OGG_PAGE_FLAG_END_OF_STREAM)) {
+ if (mFirstPacketInPage) {
AMediaFormat *meta = buffer->meta_data();
AMediaFormat_setInt32(
meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, mCurrentPageSamples);
@@ -871,9 +864,6 @@
}
// fall through, the buffer now contains the start of the packet.
- ALOGV("have start of packet, getting rest");
- } else {
- ALOGV("moving to next page");
}
CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments);
@@ -909,10 +899,9 @@
mNextLaceIndex = 0;
if (buffer != NULL) {
- if ((mCurrentPage.mFlags & OGG_PAGE_FLAG_CONTINUED_PACKET) == 0) {
+ if ((mCurrentPage.mFlags & 1) == 0) {
// This page does not continue the packet, i.e. the packet
// is already complete.
- ALOGV("packet was already complete?!");
if (timeUs >= 0) {
AMediaFormat *meta = buffer->meta_data();
@@ -920,10 +909,8 @@
}
AMediaFormat *meta = buffer->meta_data();
- if (mCurrentPage.mFlags & OGG_PAGE_FLAG_END_OF_STREAM) {
- AMediaFormat_setInt32(
- meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, mCurrentPageSamples);
- }
+ AMediaFormat_setInt32(
+ meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, mCurrentPageSamples);
mFirstPacketInPage = false;
*out = buffer;
@@ -942,7 +929,6 @@
for (size_t i = 0; i < mNumHeaders; ++i) {
// ignore timestamp for configuration packets
if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != AMEDIA_OK) {
- ALOGV("readNextPacket failed");
return err;
}
ALOGV("read packet of size %zu\n", packet->range_length());
@@ -1022,10 +1008,6 @@
size_t size = buffer->range_length();
- if (size == 0) {
- return 0;
- }
-
ogg_buffer buf;
buf.data = (uint8_t *)data;
buf.size = size;
diff --git a/media/libaaudio/Android.bp b/media/libaaudio/Android.bp
index e81ab06..7796ed5 100644
--- a/media/libaaudio/Android.bp
+++ b/media/libaaudio/Android.bp
@@ -32,6 +32,6 @@
cc_library_headers {
name: "libaaudio_headers",
export_include_dirs: ["include"],
- export_header_lib_headers: ["aaudio-aidl-cpp"],
- header_libs: ["aaudio-aidl-cpp"],
+ export_shared_lib_headers: ["aaudio-aidl-cpp"],
+ shared_libs: ["aaudio-aidl-cpp"],
}
diff --git a/media/libaaudio/src/binding/AAudioBinderAdapter.cpp b/media/libaaudio/src/binding/AAudioBinderAdapter.cpp
index 2b2fe6d..6e3a1c8 100644
--- a/media/libaaudio/src/binding/AAudioBinderAdapter.cpp
+++ b/media/libaaudio/src/binding/AAudioBinderAdapter.cpp
@@ -15,10 +15,12 @@
*/
#include <binding/AAudioBinderAdapter.h>
+#include <media/AidlConversionUtil.h>
#include <utility/AAudioUtilities.h>
namespace aaudio {
+using android::aidl_utils::statusTFromBinderStatus;
using android::binder::Status;
AAudioBinderAdapter::AAudioBinderAdapter(IAAudioService* delegate)
@@ -36,7 +38,7 @@
¶ms,
&result);
if (!status.isOk()) {
- result = AAudioConvert_androidToAAudioResult(status.transactionError());
+ result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
}
config = params;
return result;
@@ -46,7 +48,7 @@
aaudio_result_t result;
Status status = mDelegate->closeStream(streamHandle, &result);
if (!status.isOk()) {
- result = AAudioConvert_androidToAAudioResult(status.transactionError());
+ result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
}
return result;
}
@@ -59,7 +61,7 @@
&endpoint,
&result);
if (!status.isOk()) {
- result = AAudioConvert_androidToAAudioResult(status.transactionError());
+ result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
}
endpointOut = std::move(endpoint);
return result;
@@ -69,7 +71,7 @@
aaudio_result_t result;
Status status = mDelegate->startStream(streamHandle, &result);
if (!status.isOk()) {
- result = AAudioConvert_androidToAAudioResult(status.transactionError());
+ result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
}
return result;
}
@@ -78,7 +80,7 @@
aaudio_result_t result;
Status status = mDelegate->pauseStream(streamHandle, &result);
if (!status.isOk()) {
- result = AAudioConvert_androidToAAudioResult(status.transactionError());
+ result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
}
return result;
}
@@ -87,7 +89,7 @@
aaudio_result_t result;
Status status = mDelegate->stopStream(streamHandle, &result);
if (!status.isOk()) {
- result = AAudioConvert_androidToAAudioResult(status.transactionError());
+ result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
}
return result;
}
@@ -96,7 +98,7 @@
aaudio_result_t result;
Status status = mDelegate->flushStream(streamHandle, &result);
if (!status.isOk()) {
- result = AAudioConvert_androidToAAudioResult(status.transactionError());
+ result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
}
return result;
}
@@ -107,7 +109,7 @@
aaudio_result_t result;
Status status = mDelegate->registerAudioThread(streamHandle, clientThreadId, periodNanoseconds, &result);
if (!status.isOk()) {
- result = AAudioConvert_androidToAAudioResult(status.transactionError());
+ result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
}
return result;
}
@@ -117,7 +119,7 @@
aaudio_result_t result;
Status status = mDelegate->unregisterAudioThread(streamHandle, clientThreadId, &result);
if (!status.isOk()) {
- result = AAudioConvert_androidToAAudioResult(status.transactionError());
+ result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
}
return result;
}
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 57c4c16..431f0fa 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -171,7 +171,7 @@
aaudio_result_t result = requestStart_l();
if (result == AAUDIO_OK) {
// We only call this for logging in "dumpsys audio". So ignore return code.
- (void) mPlayerBase->start();
+ (void) mPlayerBase->startWithStatus(getDeviceId());
}
return result;
}
@@ -221,7 +221,7 @@
aaudio_result_t result = requestPause_l();
if (result == AAUDIO_OK) {
// We only call this for logging in "dumpsys audio". So ignore return code.
- (void) mPlayerBase->pause();
+ (void) mPlayerBase->pauseWithStatus();
}
return result;
}
@@ -251,7 +251,7 @@
aaudio_result_t result = safeStop_l();
if (result == AAUDIO_OK) {
// We only call this for logging in "dumpsys audio". So ignore return code.
- (void) mPlayerBase->stop();
+ (void) mPlayerBase->stopWithStatus();
}
return result;
}
@@ -265,7 +265,7 @@
aaudio_result_t result = safeStop_l();
if (result == AAUDIO_OK) {
// We only call this for logging in "dumpsys audio". So ignore return code.
- (void) mPlayerBase->stop();
+ (void) mPlayerBase->stopWithStatus();
}
return result;
}
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 1d036d0..af8ff19 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -558,7 +558,7 @@
if (status < 0) { // a non-negative value is the volume shaper id.
ALOGE("applyVolumeShaper() failed with status %d", status);
}
- return binder::Status::fromStatusT(status);
+ return aidl_utils::binderStatusFromStatusT(status);
} else {
ALOGD("applyVolumeShaper()"
" no AudioTrack for volume control from IPlayer");
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index f11f184..31c071e 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -117,56 +117,58 @@
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;
- default:
- break;
}
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;
- default:
- break;
}
break;
- default:
- 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;
- default:
- break;
}
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;
- default:
- break;
}
break;
- default:
- break;
}
return unexpected(BAD_VALUE);
}
@@ -236,6 +238,14 @@
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);
}
@@ -268,8 +278,9 @@
return std::string(legacy.c_str());
}
-// The legacy enum is unnamed. Thus, we use int.
-ConversionResult<int> aidl2legacy_AudioPortConfigType(media::AudioPortConfigType aidl) {
+// The legacy enum is unnamed. Thus, we use int32_t.
+ConversionResult<int32_t> aidl2legacy_AudioPortConfigType_int32_t(
+ media::AudioPortConfigType aidl) {
switch (aidl) {
case media::AudioPortConfigType::SAMPLE_RATE:
return AUDIO_PORT_CONFIG_SAMPLE_RATE;
@@ -285,8 +296,9 @@
return unexpected(BAD_VALUE);
}
-// The legacy enum is unnamed. Thus, we use int.
-ConversionResult<media::AudioPortConfigType> legacy2aidl_AudioPortConfigType(int legacy) {
+// The legacy enum is unnamed. Thus, we use int32_t.
+ConversionResult<media::AudioPortConfigType> legacy2aidl_int32_t_AudioPortConfigType(
+ int32_t legacy) {
switch (legacy) {
case AUDIO_PORT_CONFIG_SAMPLE_RATE:
return media::AudioPortConfigType::SAMPLE_RATE;
@@ -304,7 +316,7 @@
ConversionResult<unsigned int> aidl2legacy_int32_t_config_mask(int32_t aidl) {
return convertBitmask<unsigned int, int32_t, int, media::AudioPortConfigType>(
- aidl, aidl2legacy_AudioPortConfigType,
+ aidl, aidl2legacy_AudioPortConfigType_int32_t,
// AudioPortConfigType enum is index-based.
index2enum_index<media::AudioPortConfigType>,
// AUDIO_PORT_CONFIG_* flags are mask-based.
@@ -313,7 +325,7 @@
ConversionResult<int32_t> legacy2aidl_config_mask_int32_t(unsigned int legacy) {
return convertBitmask<int32_t, unsigned int, media::AudioPortConfigType, int>(
- legacy, legacy2aidl_AudioPortConfigType,
+ legacy, legacy2aidl_int32_t_AudioPortConfigType,
// AUDIO_PORT_CONFIG_* flags are mask-based.
index2enum_bitmask<unsigned>,
// AudioPortConfigType enum is index-based.
@@ -355,9 +367,8 @@
return AUDIO_INPUT_CONFIG_CHANGED;
case media::AudioIoConfigEvent::CLIENT_STARTED:
return AUDIO_CLIENT_STARTED;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<media::AudioIoConfigEvent> legacy2aidl_audio_io_config_event_AudioIoConfigEvent(
@@ -381,9 +392,8 @@
return media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED;
case AUDIO_CLIENT_STARTED:
return media::AudioIoConfigEvent::CLIENT_STARTED;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<audio_port_role_t> aidl2legacy_AudioPortRole_audio_port_role_t(
@@ -395,9 +405,8 @@
return AUDIO_PORT_ROLE_SOURCE;
case media::AudioPortRole::SINK:
return AUDIO_PORT_ROLE_SINK;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<media::AudioPortRole> legacy2aidl_audio_port_role_t_AudioPortRole(
@@ -409,9 +418,8 @@
return media::AudioPortRole::SOURCE;
case AUDIO_PORT_ROLE_SINK:
return media::AudioPortRole::SINK;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<audio_port_type_t> aidl2legacy_AudioPortType_audio_port_type_t(
@@ -425,9 +433,8 @@
return AUDIO_PORT_TYPE_MIX;
case media::AudioPortType::SESSION:
return AUDIO_PORT_TYPE_SESSION;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<media::AudioPortType> legacy2aidl_audio_port_type_t_AudioPortType(
@@ -441,9 +448,8 @@
return media::AudioPortType::MIX;
case AUDIO_PORT_TYPE_SESSION:
return media::AudioPortType::SESSION;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<audio_format_t> aidl2legacy_AudioFormat_audio_format_t(
@@ -468,9 +474,8 @@
return AUDIO_GAIN_MODE_CHANNELS;
case media::AudioGainMode::RAMP:
return AUDIO_GAIN_MODE_RAMP;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<media::AudioGainMode> legacy2aidl_audio_gain_mode_t_AudioGainMode(audio_gain_mode_t legacy) {
@@ -481,9 +486,8 @@
return media::AudioGainMode::CHANNELS;
case AUDIO_GAIN_MODE_RAMP:
return media::AudioGainMode::RAMP;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl) {
@@ -495,7 +499,7 @@
enumToMask_bitmask<audio_gain_mode_t, audio_gain_mode_t>);
}
-ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_mask_int32_t(audio_gain_mode_t legacy) {
+ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy) {
return convertBitmask<int32_t, audio_gain_mode_t, media::AudioGainMode, audio_gain_mode_t>(
legacy, legacy2aidl_audio_gain_mode_t_AudioGainMode,
// AUDIO_GAIN_MODE_* constants are mask-based.
@@ -540,7 +544,7 @@
const audio_gain_config& legacy, audio_port_role_t role, audio_port_type_t type) {
media::AudioGainConfig aidl;
aidl.index = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.index));
- aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_mask_int32_t(legacy.mode));
+ 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_int32_t(legacy.channel_mask));
const bool isInput = VALUE_OR_RETURN(direction(role, type)) == Direction::INPUT;
@@ -575,14 +579,15 @@
return AUDIO_INPUT_FLAG_HW_AV_SYNC;
case media::AudioInputFlags::DIRECT:
return AUDIO_INPUT_FLAG_DIRECT;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<media::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 media::AudioInputFlags::FAST;
case AUDIO_INPUT_FLAG_HW_HOTWORD:
@@ -599,9 +604,8 @@
return media::AudioInputFlags::HW_AV_SYNC;
case AUDIO_INPUT_FLAG_DIRECT:
return media::AudioInputFlags::DIRECT;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
@@ -637,14 +641,17 @@
return AUDIO_OUTPUT_FLAG_VOIP_RX;
case media::AudioOutputFlags::INCALL_MUSIC:
return AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
- default:
- return unexpected(BAD_VALUE);
+ case media::AudioOutputFlags::GAPLESS_OFFLOAD:
+ return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<media::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 media::AudioOutputFlags::DIRECT;
case AUDIO_OUTPUT_FLAG_PRIMARY:
@@ -675,12 +682,14 @@
return media::AudioOutputFlags::VOIP_RX;
case AUDIO_OUTPUT_FLAG_INCALL_MUSIC:
return media::AudioOutputFlags::INCALL_MUSIC;
- default:
- return unexpected(BAD_VALUE);
+ case AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD:
+ return media::AudioOutputFlags::GAPLESS_OFFLOAD;
}
+ return unexpected(BAD_VALUE);
}
-ConversionResult<audio_input_flags_t> aidl2legacy_audio_input_flags_mask(int32_t aidl) {
+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(
@@ -691,7 +700,8 @@
return static_cast<audio_input_flags_t>(converted);
}
-ConversionResult<int32_t> legacy2aidl_audio_input_flags_mask(audio_input_flags_t legacy) {
+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);
@@ -701,7 +711,8 @@
enumToMask_index<int32_t, media::AudioInputFlags>);
}
-ConversionResult<audio_output_flags_t> aidl2legacy_audio_output_flags_mask(int32_t aidl) {
+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,
@@ -711,7 +722,8 @@
enumToMask_bitmask<audio_output_flags_t, audio_output_flags_t>);
}
-ConversionResult<int32_t> legacy2aidl_audio_output_flags_mask(audio_output_flags_t legacy) {
+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);
@@ -728,13 +740,15 @@
switch (dir) {
case Direction::INPUT: {
legacy.input = VALUE_OR_RETURN(
- aidl2legacy_audio_input_flags_mask(VALUE_OR_RETURN(UNION_GET(aidl, input))));
+ aidl2legacy_int32_t_audio_input_flags_t_mask(
+ VALUE_OR_RETURN(UNION_GET(aidl, input))));
}
break;
case Direction::OUTPUT: {
legacy.output = VALUE_OR_RETURN(
- aidl2legacy_audio_output_flags_mask(VALUE_OR_RETURN(UNION_GET(aidl, output))));
+ aidl2legacy_int32_t_audio_output_flags_t_mask(
+ VALUE_OR_RETURN(UNION_GET(aidl, output))));
}
break;
}
@@ -750,17 +764,20 @@
switch (dir) {
case Direction::INPUT:
UNION_SET(aidl, input,
- VALUE_OR_RETURN(legacy2aidl_audio_input_flags_mask(legacy.input)));
+ VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(
+ legacy.input)));
break;
case Direction::OUTPUT:
UNION_SET(aidl, output,
- VALUE_OR_RETURN(legacy2aidl_audio_output_flags_mask(legacy.output)));
+ VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(
+ legacy.output)));
break;
}
return aidl;
}
-ConversionResult<audio_port_config_device_ext> aidl2legacy_AudioPortConfigDeviceExt(
+ConversionResult<audio_port_config_device_ext>
+aidl2legacy_AudioPortConfigDeviceExt_audio_port_config_device_ext(
const media::AudioPortConfigDeviceExt& aidl) {
audio_port_config_device_ext legacy;
legacy.hw_module = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_module_handle_t(aidl.hwModule));
@@ -769,7 +786,8 @@
return legacy;
}
-ConversionResult<media::AudioPortConfigDeviceExt> legacy2aidl_AudioPortConfigDeviceExt(
+ConversionResult<media::AudioPortConfigDeviceExt>
+legacy2aidl_audio_port_config_device_ext_AudioPortConfigDeviceExt(
const audio_port_config_device_ext& legacy) {
media::AudioPortConfigDeviceExt aidl;
aidl.hwModule = VALUE_OR_RETURN(legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
@@ -814,9 +832,8 @@
return AUDIO_STREAM_PATCH;
case media::AudioStreamType::CALL_ASSISTANT:
return AUDIO_STREAM_CALL_ASSISTANT;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<media::AudioStreamType> legacy2aidl_audio_stream_type_t_AudioStreamType(
@@ -854,9 +871,8 @@
return media::AudioStreamType::PATCH;
case AUDIO_STREAM_CALL_ASSISTANT:
return media::AudioStreamType::CALL_ASSISTANT;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<audio_source_t> aidl2legacy_AudioSourceType_audio_source_t(
@@ -893,9 +909,8 @@
return AUDIO_SOURCE_FM_TUNER;
case media::AudioSourceType::HOTWORD:
return AUDIO_SOURCE_HOTWORD;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<media::AudioSourceType> legacy2aidl_audio_source_t_AudioSourceType(
@@ -931,9 +946,8 @@
return media::AudioSourceType::FM_TUNER;
case AUDIO_SOURCE_HOTWORD:
return media::AudioSourceType::HOTWORD;
- default:
- return unexpected(BAD_VALUE);
}
+ return unexpected(BAD_VALUE);
}
ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl) {
@@ -955,24 +969,21 @@
case media::AudioPortRole::NONE:
// Just verify that the union is empty.
VALUE_OR_RETURN(UNION_GET(aidl, unspecified));
- break;
+ 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))));
- break;
+ return legacy;
case media::AudioPortRole::SINK:
// This is not a bug. A SINK role corresponds to the source field.
legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSourceType_audio_source_t(
VALUE_OR_RETURN(UNION_GET(aidl, source))));
- break;
-
- default:
- LOG_ALWAYS_FATAL("Shouldn't get here");
+ return legacy;
}
- return legacy;
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
}
ConversionResult<media::AudioPortConfigMixExtUseCase> legacy2aidl_AudioPortConfigMixExtUseCase(
@@ -982,21 +993,19 @@
switch (role) {
case AUDIO_PORT_ROLE_NONE:
UNION_SET(aidl, unspecified, false);
- break;
+ 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)));
- break;
+ return aidl;
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_AudioSourceType(legacy.source)));
- break;
- default:
- LOG_ALWAYS_FATAL("Shouldn't get here");
+ return aidl;
}
- return aidl;
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
}
ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortConfigMixExt(
@@ -1017,14 +1026,16 @@
return aidl;
}
-ConversionResult<audio_port_config_session_ext> aidl2legacy_AudioPortConfigSessionExt(
+ConversionResult<audio_port_config_session_ext>
+aidl2legacy_AudioPortConfigSessionExt_audio_port_config_session_ext(
const media::AudioPortConfigSessionExt& aidl) {
audio_port_config_session_ext legacy;
legacy.session = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl.session));
return legacy;
}
-ConversionResult<media::AudioPortConfigSessionExt> legacy2aidl_AudioPortConfigSessionExt(
+ConversionResult<media::AudioPortConfigSessionExt>
+legacy2aidl_audio_port_config_session_ext_AudioPortConfigSessionExt(
const audio_port_config_session_ext& legacy) {
media::AudioPortConfigSessionExt aidl;
aidl.session = VALUE_OR_RETURN(legacy2aidl_audio_session_t_int32_t(legacy.session));
@@ -1042,23 +1053,24 @@
case media::AudioPortType::NONE:
// Just verify that the union is empty.
VALUE_OR_RETURN(UNION_GET(aidl, unspecified));
- break;
+ return legacy;
case media::AudioPortType::DEVICE:
legacy.device = VALUE_OR_RETURN(
- aidl2legacy_AudioPortConfigDeviceExt(VALUE_OR_RETURN(UNION_GET(aidl, device))));
- break;
+ aidl2legacy_AudioPortConfigDeviceExt_audio_port_config_device_ext(
+ VALUE_OR_RETURN(UNION_GET(aidl, device))));
+ return legacy;
case media::AudioPortType::MIX:
legacy.mix = VALUE_OR_RETURN(
aidl2legacy_AudioPortConfigMixExt(VALUE_OR_RETURN(UNION_GET(aidl, mix)), role));
- break;
+ return legacy;
case media::AudioPortType::SESSION:
- legacy.session = VALUE_OR_RETURN(aidl2legacy_AudioPortConfigSessionExt(
- VALUE_OR_RETURN(UNION_GET(aidl, session))));
- break;
- default:
- LOG_ALWAYS_FATAL("Shouldn't get here");
+ legacy.session = VALUE_OR_RETURN(
+ aidl2legacy_AudioPortConfigSessionExt_audio_port_config_session_ext(
+ VALUE_OR_RETURN(UNION_GET(aidl, session))));
+ return legacy;
+
}
- return legacy;
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
}
ConversionResult<media::AudioPortConfigExt> legacy2aidl_AudioPortConfigExt(
@@ -1068,23 +1080,25 @@
switch (type) {
case AUDIO_PORT_TYPE_NONE:
UNION_SET(aidl, unspecified, false);
- break;
+ return aidl;
case AUDIO_PORT_TYPE_DEVICE:
UNION_SET(aidl, device,
- VALUE_OR_RETURN(legacy2aidl_AudioPortConfigDeviceExt(legacy.device)));
- break;
+ VALUE_OR_RETURN(
+ legacy2aidl_audio_port_config_device_ext_AudioPortConfigDeviceExt(
+ legacy.device)));
+ return aidl;
case AUDIO_PORT_TYPE_MIX:
UNION_SET(aidl, mix,
VALUE_OR_RETURN(legacy2aidl_AudioPortConfigMixExt(legacy.mix, role)));
- break;
+ return aidl;
case AUDIO_PORT_TYPE_SESSION:
UNION_SET(aidl, session,
- VALUE_OR_RETURN(legacy2aidl_AudioPortConfigSessionExt(legacy.session)));
- break;
- default:
- LOG_ALWAYS_FATAL("Shouldn't get here");
+ VALUE_OR_RETURN(
+ legacy2aidl_audio_port_config_session_ext_AudioPortConfigSessionExt(
+ legacy.session)));
+ return aidl;
}
- return aidl;
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
}
ConversionResult<audio_port_config> aidl2legacy_AudioPortConfig_audio_port_config(
@@ -1223,7 +1237,8 @@
return aidl;
}
-ConversionResult<AudioClient> aidl2legacy_AudioClient(const media::AudioClient& aidl) {
+ConversionResult<AudioClient> aidl2legacy_AudioClient_AudioClient(
+ const media::AudioClient& aidl) {
AudioClient legacy;
legacy.clientUid = VALUE_OR_RETURN(aidl2legacy_int32_t_uid_t(aidl.clientUid));
legacy.clientPid = VALUE_OR_RETURN(aidl2legacy_int32_t_pid_t(aidl.clientPid));
@@ -1232,7 +1247,8 @@
return legacy;
}
-ConversionResult<media::AudioClient> legacy2aidl_AudioClient(const AudioClient& legacy) {
+ConversionResult<media::AudioClient> legacy2aidl_AudioClient_AudioClient(
+ const AudioClient& legacy) {
media::AudioClient aidl;
aidl.clientUid = VALUE_OR_RETURN(legacy2aidl_uid_t_int32_t(legacy.clientUid));
aidl.clientPid = VALUE_OR_RETURN(legacy2aidl_pid_t_int32_t(legacy.clientPid));
@@ -1660,7 +1676,7 @@
}
ConversionResult<AudioTimestamp>
-aidl2legacy_AudioTimestamp(const media::AudioTimestampInternal& aidl) {
+aidl2legacy_AudioTimestampInternal_AudioTimestamp(const media::AudioTimestampInternal& aidl) {
AudioTimestamp legacy;
legacy.mPosition = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.position));
legacy.mTime.tv_sec = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sec));
@@ -1669,7 +1685,7 @@
}
ConversionResult<media::AudioTimestampInternal>
-legacy2aidl_AudioTimestamp(const AudioTimestamp& legacy) {
+legacy2aidl_AudioTimestamp_AudioTimestampInternal(const AudioTimestamp& legacy) {
media::AudioTimestampInternal aidl;
aidl.position = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.mPosition));
aidl.sec = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.mTime.tv_sec));
@@ -1900,25 +1916,24 @@
case media::AudioPortType::NONE:
// Just verify that the union is empty.
VALUE_OR_RETURN(UNION_GET(aidl, unspecified));
- break;
+ return legacy;
case media::AudioPortType::DEVICE:
legacy.device = VALUE_OR_RETURN(
aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
VALUE_OR_RETURN(UNION_GET(aidl, device))));
- break;
+ return legacy;
case media::AudioPortType::MIX:
legacy.mix = VALUE_OR_RETURN(
aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
VALUE_OR_RETURN(UNION_GET(aidl, mix))));
- break;
+ return legacy;
case media::AudioPortType::SESSION:
legacy.session = VALUE_OR_RETURN(aidl2legacy_AudioPortSessionExt_audio_port_session_ext(
VALUE_OR_RETURN(UNION_GET(aidl, session))));
- break;
- default:
- LOG_ALWAYS_FATAL("Shouldn't get here");
+ return legacy;
+
}
- return legacy;
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
}
ConversionResult<media::AudioPortExt> legacy2aidl_AudioPortExt(
@@ -1927,25 +1942,23 @@
switch (type) {
case AUDIO_PORT_TYPE_NONE:
UNION_SET(aidl, unspecified, false);
- break;
+ return aidl;
case AUDIO_PORT_TYPE_DEVICE:
UNION_SET(aidl, device,
VALUE_OR_RETURN(
legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(legacy.device)));
- break;
+ return aidl;
case AUDIO_PORT_TYPE_MIX:
UNION_SET(aidl, mix,
VALUE_OR_RETURN(legacy2aidl_audio_port_mix_ext_AudioPortMixExt(legacy.mix)));
- break;
+ return aidl;
case AUDIO_PORT_TYPE_SESSION:
UNION_SET(aidl, session,
VALUE_OR_RETURN(legacy2aidl_audio_port_session_ext_AudioPortSessionExt(
legacy.session)));
- break;
- default:
- LOG_ALWAYS_FATAL("Shouldn't get here");
+ return aidl;
}
- return aidl;
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
}
ConversionResult<audio_profile>
@@ -2012,7 +2025,7 @@
ConversionResult<media::AudioGain>
legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy) {
media::AudioGain aidl;
- aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_mask_int32_t(legacy.mode));
+ 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_int32_t(legacy.channel_mask));
aidl.minValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_value));
@@ -2082,4 +2095,106 @@
return aidl;
}
+ConversionResult<audio_mode_t>
+aidl2legacy_AudioMode_audio_mode_t(media::AudioMode aidl) {
+ switch (aidl) {
+ case media::AudioMode::INVALID:
+ return AUDIO_MODE_INVALID;
+ case media::AudioMode::CURRENT:
+ return AUDIO_MODE_CURRENT;
+ case media::AudioMode::NORMAL:
+ return AUDIO_MODE_NORMAL;
+ case media::AudioMode::RINGTONE:
+ return AUDIO_MODE_RINGTONE;
+ case media::AudioMode::IN_CALL:
+ return AUDIO_MODE_IN_CALL;
+ case media::AudioMode::IN_COMMUNICATION:
+ return AUDIO_MODE_IN_COMMUNICATION;
+ case media::AudioMode::CALL_SCREEN:
+ return AUDIO_MODE_CALL_SCREEN;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<media::AudioMode>
+legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_MODE_INVALID:
+ return media::AudioMode::INVALID;
+ case AUDIO_MODE_CURRENT:
+ return media::AudioMode::CURRENT;
+ case AUDIO_MODE_NORMAL:
+ return media::AudioMode::NORMAL;
+ case AUDIO_MODE_RINGTONE:
+ return media::AudioMode::RINGTONE;
+ case AUDIO_MODE_IN_CALL:
+ return media::AudioMode::IN_CALL;
+ case AUDIO_MODE_IN_COMMUNICATION:
+ return media::AudioMode::IN_COMMUNICATION;
+ case AUDIO_MODE_CALL_SCREEN:
+ return media::AudioMode::CALL_SCREEN;
+ 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) {
+ case media::AudioUniqueIdUse::UNSPECIFIED:
+ return AUDIO_UNIQUE_ID_USE_UNSPECIFIED;
+ case media::AudioUniqueIdUse::SESSION:
+ return AUDIO_UNIQUE_ID_USE_SESSION;
+ case media::AudioUniqueIdUse::MODULE:
+ return AUDIO_UNIQUE_ID_USE_MODULE;
+ case media::AudioUniqueIdUse::EFFECT:
+ return AUDIO_UNIQUE_ID_USE_EFFECT;
+ case media::AudioUniqueIdUse::PATCH:
+ return AUDIO_UNIQUE_ID_USE_PATCH;
+ case media::AudioUniqueIdUse::OUTPUT:
+ return AUDIO_UNIQUE_ID_USE_OUTPUT;
+ case media::AudioUniqueIdUse::INPUT:
+ return AUDIO_UNIQUE_ID_USE_INPUT;
+ case media::AudioUniqueIdUse::CLIENT:
+ return AUDIO_UNIQUE_ID_USE_CLIENT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<media::AudioUniqueIdUse>
+legacy2aidl_audio_unique_id_use_t_AudioUniqueIdUse(audio_unique_id_use_t legacy) {
+ switch (legacy) {
+ case AUDIO_UNIQUE_ID_USE_UNSPECIFIED:
+ return media::AudioUniqueIdUse::UNSPECIFIED;
+ case AUDIO_UNIQUE_ID_USE_SESSION:
+ return media::AudioUniqueIdUse::SESSION;
+ case AUDIO_UNIQUE_ID_USE_MODULE:
+ return media::AudioUniqueIdUse::MODULE;
+ case AUDIO_UNIQUE_ID_USE_EFFECT:
+ return media::AudioUniqueIdUse::EFFECT;
+ case AUDIO_UNIQUE_ID_USE_PATCH:
+ return media::AudioUniqueIdUse::PATCH;
+ case AUDIO_UNIQUE_ID_USE_OUTPUT:
+ return media::AudioUniqueIdUse::OUTPUT;
+ case AUDIO_UNIQUE_ID_USE_INPUT:
+ return media::AudioUniqueIdUse::INPUT;
+ case AUDIO_UNIQUE_ID_USE_CLIENT:
+ return media::AudioUniqueIdUse::CLIENT;
+ case AUDIO_UNIQUE_ID_USE_MAX:
+ break;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<volume_group_t>
+aidl2legacy_int32_t_volume_group_t(int32_t aidl) {
+ return convertReinterpret<volume_group_t>(aidl);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_volume_group_t_int32_t(volume_group_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
} // namespace android
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index fa67898..aa740a7 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -15,10 +15,12 @@
],
static_libs: [
"audioflinger-aidl-unstable-cpp",
+ "audiopolicy-aidl-unstable-cpp",
"av-types-aidl-unstable-cpp",
],
export_static_lib_headers: [
"audioflinger-aidl-unstable-cpp",
+ "audiopolicy-aidl-unstable-cpp",
"av-types-aidl-unstable-cpp",
],
target: {
@@ -56,9 +58,10 @@
"audioflinger-aidl-unstable-cpp",
"capture_state_listener-aidl-cpp",
],
+ header_libs: ["libaudioclient_headers"],
}
-cc_library_shared {
+cc_library {
name: "libaudioclient",
aidl: {
@@ -82,7 +85,6 @@
"AudioTrackShared.cpp",
"IAudioFlinger.cpp",
"IAudioPolicyService.cpp",
- "IAudioPolicyServiceClient.cpp",
"ToneGenerator.cpp",
"PlayerBase.cpp",
"RecordingActivityTracker.cpp",
@@ -91,6 +93,7 @@
shared_libs: [
"audioclient-types-aidl-unstable-cpp",
"audioflinger-aidl-unstable-cpp",
+ "audiopolicy-aidl-unstable-cpp",
"av-types-aidl-unstable-cpp",
"capture_state_listener-aidl-cpp",
"libaudioclient_aidl_conversion",
@@ -113,6 +116,7 @@
],
export_shared_lib_headers: [
"audioflinger-aidl-unstable-cpp",
+ "audiopolicy-aidl-unstable-cpp",
"libbinder",
],
@@ -347,7 +351,9 @@
"aidl/android/media/OpenInputResponse.aidl",
"aidl/android/media/OpenOutputRequest.aidl",
"aidl/android/media/OpenOutputResponse.aidl",
+ "aidl/android/media/RenderPosition.aidl",
+ "aidl/android/media/IAudioFlingerService.aidl",
"aidl/android/media/IAudioFlingerClient.aidl",
"aidl/android/media/IAudioRecord.aidl",
"aidl/android/media/IAudioTrack.aidl",
@@ -371,3 +377,29 @@
},
},
}
+
+aidl_interface {
+ name: "audiopolicy-aidl",
+ unstable: true,
+ local_include_dir: "aidl",
+ host_supported: true,
+ vendor_available: true,
+ srcs: [
+ "aidl/android/media/RecordClientInfo.aidl",
+
+ "aidl/android/media/IAudioPolicyServiceClient.aidl",
+ ],
+ imports: [
+ "audioclient-types-aidl",
+ ],
+ double_loadable: true,
+ backend: {
+ cpp: {
+ min_sdk_version: "29",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media",
+ ],
+ },
+ },
+}
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index ae899c0..79ea1bb 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -30,7 +30,7 @@
#include <utils/Log.h>
namespace android {
-
+using aidl_utils::statusTFromBinderStatus;
using binder::Status;
namespace {
@@ -262,7 +262,7 @@
bs = mIEffect->disable(&status);
}
if (!bs.isOk()) {
- status = bs.transactionError();
+ status = statusTFromBinderStatus(bs);
}
if (status == NO_ERROR) {
mEnabled = enabled;
@@ -303,7 +303,7 @@
Status bs = mIEffect->command(cmdCode, data, *replySize, &response, &status);
if (!bs.isOk()) {
- status = bs.transactionError();
+ status = statusTFromBinderStatus(bs);
}
if (status == NO_ERROR) {
memcpy(replyData, response.data(), response.size());
@@ -351,7 +351,7 @@
&response,
&status);
if (!bs.isOk()) {
- status = bs.transactionError();
+ status = statusTFromBinderStatus(bs);
return status;
}
assert(response.size() == sizeof(int));
@@ -410,7 +410,7 @@
&response,
&status);
if (!bs.isOk()) {
- status = bs.transactionError();
+ status = statusTFromBinderStatus(bs);
}
return status;
}
@@ -441,7 +441,7 @@
Status bs = mIEffect->command(EFFECT_CMD_GET_PARAM, cmd, psize, &response, &status);
if (!bs.isOk()) {
- status = bs.transactionError();
+ status = statusTFromBinderStatus(bs);
return status;
}
memcpy(param, response.data(), response.size());
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index f01b1d0..112cb67 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -47,6 +47,8 @@
#define WAIT_PERIOD_MS 10
namespace android {
+using aidl_utils::statusTFromBinderStatus;
+
// ---------------------------------------------------------------------------
// static
@@ -450,7 +452,7 @@
mActive = true;
if (!(flags & CBLK_INVALID)) {
- status = mAudioRecord->start(event, triggerSession).transactionError();
+ status = statusTFromBinderStatus(mAudioRecord->start(event, triggerSession));
if (status == DEAD_OBJECT) {
flags |= CBLK_INVALID;
}
@@ -1439,8 +1441,8 @@
if (mActive) {
// callback thread or sync event hasn't changed
// FIXME this fails if we have a new AudioFlinger instance
- result = mAudioRecord->start(
- AudioSystem::SYNC_EVENT_SAME, AUDIO_SESSION_NONE).transactionError();
+ result = statusTFromBinderStatus(mAudioRecord->start(
+ AudioSystem::SYNC_EVENT_SAME, AUDIO_SESSION_NONE));
}
mFramesReadServerOffset = mFramesRead; // server resets to zero so we need an offset.
}
@@ -1531,7 +1533,7 @@
{
AutoMutex lock(mLock);
std::vector<media::MicrophoneInfoData> mics;
- status_t status = mAudioRecord->getActiveMicrophones(&mics).transactionError();
+ 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]);
@@ -1552,7 +1554,7 @@
// the internal AudioRecord hasn't be created yet, so just stash the attribute.
return OK;
} else {
- return mAudioRecord->setPreferredMicrophoneDirection(direction).transactionError();
+ return statusTFromBinderStatus(mAudioRecord->setPreferredMicrophoneDirection(direction));
}
}
@@ -1568,7 +1570,7 @@
// the internal AudioRecord hasn't be created yet, so just stash the attribute.
return OK;
} else {
- return mAudioRecord->setPreferredMicrophoneFieldDimension(zoom).transactionError();
+ return statusTFromBinderStatus(mAudioRecord->setPreferredMicrophoneFieldDimension(zoom));
}
}
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index d163feb..2187635 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -35,7 +35,7 @@
#define VALUE_OR_RETURN_BINDER_STATUS(x) \
({ auto _tmp = (x); \
- if (!_tmp.ok()) return Status::fromStatusT(_tmp.error()); \
+ if (!_tmp.ok()) return aidl_utils::binderStatusFromStatusT(_tmp.error()); \
std::move(_tmp.value()); })
// ----------------------------------------------------------------------------
@@ -53,6 +53,7 @@
std::set<audio_error_callback> AudioSystem::gAudioErrorCallbacks;
dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL;
record_config_callback AudioSystem::gRecordConfigCallback = NULL;
+routing_callback AudioSystem::gRoutingCallback = NULL;
// Required to be held while calling into gSoundTriggerCaptureStateListener.
class CaptureStateListenerImpl;
@@ -71,7 +72,7 @@
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
- binder = sm->getService(String16("media.audio_flinger"));
+ binder = sm->getService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME));
if (binder != 0)
break;
ALOGW("AudioFlinger not published, waiting...");
@@ -83,7 +84,8 @@
reportNoError = true;
}
binder->linkToDeath(gAudioFlingerClient);
- gAudioFlinger = interface_cast<IAudioFlinger>(binder);
+ gAudioFlinger = new AudioFlingerClientAdapter(
+ interface_cast<media::IAudioFlingerService>(binder));
LOG_ALWAYS_FATAL_IF(gAudioFlinger == 0);
afc = gAudioFlingerClient;
// Make sure callbacks can be received by gAudioFlingerClient
@@ -770,6 +772,12 @@
gRecordConfigCallback = cb;
}
+/*static*/ void AudioSystem::setRoutingCallback(routing_callback cb)
+{
+ Mutex::Autolock _l(gLock);
+ gRoutingCallback = cb;
+}
+
// client singleton for AudioPolicyService binder interface
// protected by gLockAPS
sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
@@ -1187,18 +1195,18 @@
return aps->setAllowedCapturePolicy(uid, flags);
}
-bool AudioSystem::isOffloadSupported(const audio_offload_info_t& info)
+audio_offload_mode_t AudioSystem::getOffloadSupport(const audio_offload_info_t& info)
{
- ALOGV("isOffloadSupported()");
+ ALOGV("%s", __func__);
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
- if (aps == 0) return false;
- return aps->isOffloadSupported(info);
+ if (aps == 0) return AUDIO_OFFLOAD_NOT_SUPPORTED;
+ return aps->getOffloadSupport(info);
}
status_t AudioSystem::listAudioPorts(audio_port_role_t role,
audio_port_type_t type,
unsigned int *num_ports,
- struct audio_port *ports,
+ struct audio_port_v7 *ports,
unsigned int *generation)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
@@ -1206,7 +1214,7 @@
return aps->listAudioPorts(role, type, num_ports, ports, generation);
}
-status_t AudioSystem::getAudioPort(struct audio_port *port)
+status_t AudioSystem::getAudioPort(struct audio_port_v7 *port)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
@@ -1791,20 +1799,22 @@
}
-void AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate()
+Status AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate()
{
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) {
mAudioPortCallbacks[i]->onAudioPortListUpdate();
}
+ return Status::ok();
}
-void AudioSystem::AudioPolicyServiceClient::onAudioPatchListUpdate()
+Status AudioSystem::AudioPolicyServiceClient::onAudioPatchListUpdate()
{
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) {
mAudioPortCallbacks[i]->onAudioPatchListUpdate();
}
+ return Status::ok();
}
// ----------------------------------------------------------------------------
@@ -1838,20 +1848,26 @@
return mAudioVolumeGroupCallback.size();
}
-void AudioSystem::AudioPolicyServiceClient::onAudioVolumeGroupChanged(volume_group_t group,
- int flags)
-{
+Status AudioSystem::AudioPolicyServiceClient::onAudioVolumeGroupChanged(int32_t group,
+ int32_t flags) {
+ volume_group_t groupLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_int32_t_volume_group_t(group));
+ int flagsLegacy = VALUE_OR_RETURN_BINDER_STATUS(convertReinterpret<int>(flags));
+
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mAudioVolumeGroupCallback.size(); i++) {
- mAudioVolumeGroupCallback[i]->onAudioVolumeGroupChanged(group, flags);
+ mAudioVolumeGroupCallback[i]->onAudioVolumeGroupChanged(groupLegacy, flagsLegacy);
}
+ return Status::ok();
}
// ----------------------------------------------------------------------------
-void AudioSystem::AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate(
- String8 regId, int32_t state)
-{
- ALOGV("AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate(%s, %d)", regId.string(), state);
+Status AudioSystem::AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate(
+ const ::std::string& regId, int32_t state) {
+ ALOGV("AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate(%s, %d)", regId.c_str(), state);
+
+ String8 regIdLegacy = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_string_view_String8(regId));
+ int stateLegacy = VALUE_OR_RETURN_BINDER_STATUS(convertReinterpret<int>(state));
dynamic_policy_callback cb = NULL;
{
Mutex::Autolock _l(AudioSystem::gLock);
@@ -1859,19 +1875,20 @@
}
if (cb != NULL) {
- cb(DYNAMIC_POLICY_EVENT_MIX_STATE_UPDATE, regId, state);
+ cb(DYNAMIC_POLICY_EVENT_MIX_STATE_UPDATE, regIdLegacy, stateLegacy);
}
+ return Status::ok();
}
-void AudioSystem::AudioPolicyServiceClient::onRecordingConfigurationUpdate(
- int event,
- const record_client_info_t *clientInfo,
- const audio_config_base_t *clientConfig,
- std::vector<effect_descriptor_t> clientEffects,
- const audio_config_base_t *deviceConfig,
- std::vector<effect_descriptor_t> effects,
- audio_patch_handle_t patchHandle,
- audio_source_t source) {
+Status AudioSystem::AudioPolicyServiceClient::onRecordingConfigurationUpdate(
+ int32_t event,
+ const media::RecordClientInfo& clientInfo,
+ const media::AudioConfigBase& clientConfig,
+ const std::vector<media::EffectDescriptor>& clientEffects,
+ const media::AudioConfigBase& deviceConfig,
+ const std::vector<media::EffectDescriptor>& effects,
+ int32_t patchHandle,
+ media::AudioSourceType source) {
record_config_callback cb = NULL;
{
Mutex::Autolock _l(AudioSystem::gLock);
@@ -1879,9 +1896,42 @@
}
if (cb != NULL) {
- cb(event, clientInfo, clientConfig, clientEffects,
- deviceConfig, effects, patchHandle, source);
+ int eventLegacy = VALUE_OR_RETURN_BINDER_STATUS(convertReinterpret<int>(event));
+ record_client_info_t clientInfoLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_RecordClientInfo_record_client_info_t(clientInfo));
+ audio_config_base_t clientConfigLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_AudioConfigBase_audio_config_base_t(clientConfig));
+ std::vector<effect_descriptor_t> clientEffectsLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+ convertContainer<std::vector<effect_descriptor_t>>(
+ clientEffects,
+ aidl2legacy_EffectDescriptor_effect_descriptor_t));
+ audio_config_base_t deviceConfigLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_AudioConfigBase_audio_config_base_t(deviceConfig));
+ std::vector<effect_descriptor_t> effectsLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+ convertContainer<std::vector<effect_descriptor_t>>(
+ effects,
+ aidl2legacy_EffectDescriptor_effect_descriptor_t));
+ audio_patch_handle_t patchHandleLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_int32_t_audio_patch_handle_t(patchHandle));
+ audio_source_t sourceLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_AudioSourceType_audio_source_t(source));
+ cb(eventLegacy, &clientInfoLegacy, &clientConfigLegacy, clientEffectsLegacy,
+ &deviceConfigLegacy, effectsLegacy, patchHandleLegacy, sourceLegacy);
}
+ return Status::ok();
+}
+
+Status AudioSystem::AudioPolicyServiceClient::onRoutingUpdated() {
+ routing_callback cb = NULL;
+ {
+ Mutex::Autolock _l(AudioSystem::gLock);
+ cb = gRoutingCallback;
+ }
+
+ if (cb != NULL) {
+ cb();
+ }
+ return Status::ok();
}
void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused)
@@ -1903,4 +1953,28 @@
ALOGW("AudioPolicyService server died!");
}
+ConversionResult<record_client_info_t>
+aidl2legacy_RecordClientInfo_record_client_info_t(const media::RecordClientInfo& aidl) {
+ record_client_info_t legacy;
+ legacy.riid = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_unique_id_t(aidl.riid));
+ legacy.uid = VALUE_OR_RETURN(aidl2legacy_int32_t_uid_t(aidl.uid));
+ legacy.session = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl.session));
+ legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSourceType_audio_source_t(aidl.source));
+ legacy.port_id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.portId));
+ legacy.silenced = aidl.silenced;
+ return legacy;
+}
+
+ConversionResult<media::RecordClientInfo>
+legacy2aidl_record_client_info_t_RecordClientInfo(const record_client_info_t& legacy) {
+ media::RecordClientInfo aidl;
+ aidl.riid = VALUE_OR_RETURN(legacy2aidl_audio_unique_id_t_int32_t(legacy.riid));
+ aidl.uid = VALUE_OR_RETURN(legacy2aidl_uid_t_int32_t(legacy.uid));
+ aidl.session = VALUE_OR_RETURN(legacy2aidl_audio_session_t_int32_t(legacy.session));
+ aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSourceType(legacy.source));
+ aidl.portId = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.port_id));
+ aidl.silenced = legacy.silenced;
+ return aidl;
+}
+
} // namespace android
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 8c53c5b..d4cbbc3 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1609,9 +1609,11 @@
media::CreateTrackResponse response;
status = audioFlinger->createTrack(VALUE_OR_FATAL(input.toAidl()), response);
- IAudioFlinger::CreateTrackOutput output = VALUE_OR_FATAL(
- IAudioFlinger::CreateTrackOutput::fromAidl(
- response));
+
+ IAudioFlinger::CreateTrackOutput output{};
+ if (status == NO_ERROR) {
+ output = VALUE_OR_FATAL(IAudioFlinger::CreateTrackOutput::fromAidl(response));
+ }
if (status != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
ALOGE("%s(%d): AudioFlinger could not create track, status: %d output %d",
@@ -2819,7 +2821,7 @@
media::AudioTimestampInternal ts;
mAudioTrack->getTimestamp(&ts, &status);
if (status == OK) {
- timestamp = VALUE_OR_FATAL(aidl2legacy_AudioTimestamp(ts));
+ timestamp = VALUE_OR_FATAL(aidl2legacy_AudioTimestampInternal_AudioTimestamp(ts));
}
} else {
// read timestamp from shared memory
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 786af53..20124df 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -28,19 +28,41 @@
namespace android {
+using aidl_utils::statusTFromBinderStatus;
+using binder::Status;
+
#define MAX_ITEMS_PER_LIST 1024
+#define VALUE_OR_RETURN_BINDER(x) \
+ ({ \
+ auto _tmp = (x); \
+ if (!_tmp.ok()) return Status::fromStatusT(_tmp.error()); \
+ std::move(_tmp.value()); \
+ })
+
+#define RETURN_STATUS_IF_ERROR(x) \
+ { \
+ auto _tmp = (x); \
+ if (_tmp != OK) return _tmp; \
+ }
+
+#define RETURN_BINDER_IF_ERROR(x) \
+ { \
+ auto _tmp = (x); \
+ if (_tmp != OK) return Status::fromStatusT(_tmp); \
+ }
+
ConversionResult<media::CreateTrackRequest> IAudioFlinger::CreateTrackInput::toAidl() const {
media::CreateTrackRequest aidl;
aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
aidl.config = VALUE_OR_RETURN(legacy2aidl_audio_config_t_AudioConfig(config));
- aidl.clientInfo = VALUE_OR_RETURN(legacy2aidl_AudioClient(clientInfo));
+ aidl.clientInfo = VALUE_OR_RETURN(legacy2aidl_AudioClient_AudioClient(clientInfo));
aidl.sharedBuffer = VALUE_OR_RETURN(legacy2aidl_NullableIMemory_SharedFileRegion(sharedBuffer));
aidl.notificationsPerBuffer = VALUE_OR_RETURN(convertIntegral<int32_t>(notificationsPerBuffer));
aidl.speed = speed;
aidl.audioTrackCallback = audioTrackCallback;
aidl.opPackageName = opPackageName;
- aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_output_flags_mask(flags));
+ aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(frameCount));
aidl.notificationFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(notificationFrameCount));
aidl.selectedDeviceId = VALUE_OR_RETURN(
@@ -54,14 +76,14 @@
IAudioFlinger::CreateTrackInput legacy;
legacy.attr = VALUE_OR_RETURN(aidl2legacy_AudioAttributesInternal_audio_attributes_t(aidl.attr));
legacy.config = VALUE_OR_RETURN(aidl2legacy_AudioConfig_audio_config_t(aidl.config));
- legacy.clientInfo = VALUE_OR_RETURN(aidl2legacy_AudioClient(aidl.clientInfo));
+ legacy.clientInfo = VALUE_OR_RETURN(aidl2legacy_AudioClient_AudioClient(aidl.clientInfo));
legacy.sharedBuffer = VALUE_OR_RETURN(aidl2legacy_NullableSharedFileRegion_IMemory(aidl.sharedBuffer));
legacy.notificationsPerBuffer = VALUE_OR_RETURN(
convertIntegral<uint32_t>(aidl.notificationsPerBuffer));
legacy.speed = aidl.speed;
legacy.audioTrackCallback = aidl.audioTrackCallback;
legacy.opPackageName = aidl.opPackageName;
- legacy.flags = VALUE_OR_RETURN(aidl2legacy_audio_output_flags_mask(aidl.flags));
+ legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_output_flags_t_mask(aidl.flags));
legacy.frameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCount));
legacy.notificationFrameCount = VALUE_OR_RETURN(
convertIntegral<size_t>(aidl.notificationFrameCount));
@@ -74,7 +96,7 @@
ConversionResult<media::CreateTrackResponse>
IAudioFlinger::CreateTrackOutput::toAidl() const {
media::CreateTrackResponse aidl;
- aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_output_flags_mask(flags));
+ aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(frameCount));
aidl.notificationFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(notificationFrameCount));
aidl.selectedDeviceId = VALUE_OR_RETURN(
@@ -94,7 +116,7 @@
IAudioFlinger::CreateTrackOutput::fromAidl(
const media::CreateTrackResponse& aidl) {
IAudioFlinger::CreateTrackOutput legacy;
- legacy.flags = VALUE_OR_RETURN(aidl2legacy_audio_output_flags_mask(aidl.flags));
+ legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_output_flags_t_mask(aidl.flags));
legacy.frameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCount));
legacy.notificationFrameCount = VALUE_OR_RETURN(
convertIntegral<size_t>(aidl.notificationFrameCount));
@@ -116,10 +138,10 @@
media::CreateRecordRequest aidl;
aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
aidl.config = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(config));
- aidl.clientInfo = VALUE_OR_RETURN(legacy2aidl_AudioClient(clientInfo));
+ aidl.clientInfo = VALUE_OR_RETURN(legacy2aidl_AudioClient_AudioClient(clientInfo));
aidl.opPackageName = VALUE_OR_RETURN(legacy2aidl_String16_string(opPackageName));
aidl.riid = VALUE_OR_RETURN(legacy2aidl_audio_unique_id_t_int32_t(riid));
- aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_input_flags_mask(flags));
+ aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(frameCount));
aidl.notificationFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(notificationFrameCount));
aidl.selectedDeviceId = VALUE_OR_RETURN(
@@ -134,10 +156,10 @@
IAudioFlinger::CreateRecordInput legacy;
legacy.attr = VALUE_OR_RETURN(aidl2legacy_AudioAttributesInternal_audio_attributes_t(aidl.attr));
legacy.config = VALUE_OR_RETURN(aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.config));
- legacy.clientInfo = VALUE_OR_RETURN(aidl2legacy_AudioClient(aidl.clientInfo));
+ legacy.clientInfo = VALUE_OR_RETURN(aidl2legacy_AudioClient_AudioClient(aidl.clientInfo));
legacy.opPackageName = VALUE_OR_RETURN(aidl2legacy_string_view_String16(aidl.opPackageName));
legacy.riid = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_unique_id_t(aidl.riid));
- legacy.flags = VALUE_OR_RETURN(aidl2legacy_audio_input_flags_mask(aidl.flags));
+ legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_input_flags_t_mask(aidl.flags));
legacy.frameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCount));
legacy.notificationFrameCount = VALUE_OR_RETURN(
convertIntegral<size_t>(aidl.notificationFrameCount));
@@ -150,7 +172,7 @@
ConversionResult<media::CreateRecordResponse>
IAudioFlinger::CreateRecordOutput::toAidl() const {
media::CreateRecordResponse aidl;
- aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_input_flags_mask(flags));
+ aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(frameCount));
aidl.notificationFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(notificationFrameCount));
aidl.selectedDeviceId = VALUE_OR_RETURN(
@@ -169,7 +191,7 @@
IAudioFlinger::CreateRecordOutput::fromAidl(
const media::CreateRecordResponse& aidl) {
IAudioFlinger::CreateRecordOutput legacy;
- legacy.flags = VALUE_OR_RETURN(aidl2legacy_audio_input_flags_mask(aidl.flags));
+ legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_input_flags_t_mask(aidl.flags));
legacy.frameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCount));
legacy.notificationFrameCount = VALUE_OR_RETURN(
convertIntegral<size_t>(aidl.notificationFrameCount));
@@ -185,1275 +207,975 @@
return legacy;
}
-class BpAudioFlinger : public BpInterface<IAudioFlinger>
-{
-public:
- explicit BpAudioFlinger(const sp<IBinder>& impl)
- : BpInterface<IAudioFlinger>(impl)
- {
- }
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// AudioFlingerClientAdapter
- virtual status_t createTrack(const media::CreateTrackRequest& input,
- media::CreateTrackResponse& output)
- {
- Parcel data, reply;
- status_t status;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeParcelable(input);
+AudioFlingerClientAdapter::AudioFlingerClientAdapter(
+ const sp<media::IAudioFlingerService> delegate) : mDelegate(delegate) {}
- status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
- if (lStatus != NO_ERROR) {
- ALOGE("createTrack transaction error %d", lStatus);
- return DEAD_OBJECT;
- }
- status = reply.readInt32();
- if (status != NO_ERROR) {
- ALOGE("createTrack returned error %d", status);
- return status;
- }
- output.readFromParcel(&reply);
- if (output.audioTrack == 0) {
- ALOGE("createTrack returned an NULL IAudioTrack with status OK");
- return DEAD_OBJECT;
- }
- return OK;
- }
-
- virtual status_t createRecord(const media::CreateRecordRequest& input,
- media::CreateRecordResponse& output)
- {
- Parcel data, reply;
- status_t status;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-
- data.writeParcelable(input);
-
- status_t lStatus = remote()->transact(CREATE_RECORD, data, &reply);
- if (lStatus != NO_ERROR) {
- ALOGE("createRecord transaction error %d", lStatus);
- return DEAD_OBJECT;
- }
- status = reply.readInt32();
- if (status != NO_ERROR) {
- ALOGE("createRecord returned error %d", status);
- return status;
- }
-
- output.readFromParcel(&reply);
- if (output.audioRecord == 0) {
- ALOGE("createRecord returned a NULL IAudioRecord with status OK");
- return DEAD_OBJECT;
- }
- return OK;
- }
-
- virtual uint32_t sampleRate(audio_io_handle_t ioHandle) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) ioHandle);
- remote()->transact(SAMPLE_RATE, data, &reply);
- return reply.readInt32();
- }
-
- // RESERVED for channelCount()
-
- virtual audio_format_t format(audio_io_handle_t output) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) output);
- remote()->transact(FORMAT, data, &reply);
- return (audio_format_t) reply.readInt32();
- }
-
- virtual size_t frameCount(audio_io_handle_t ioHandle) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) ioHandle);
- remote()->transact(FRAME_COUNT, data, &reply);
- return reply.readInt64();
- }
-
- virtual uint32_t latency(audio_io_handle_t output) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) output);
- remote()->transact(LATENCY, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t setMasterVolume(float value)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeFloat(value);
- remote()->transact(SET_MASTER_VOLUME, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t setMasterMute(bool muted)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(muted);
- remote()->transact(SET_MASTER_MUTE, data, &reply);
- return reply.readInt32();
- }
-
- virtual float masterVolume() const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- remote()->transact(MASTER_VOLUME, data, &reply);
- return reply.readFloat();
- }
-
- virtual bool masterMute() const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- remote()->transact(MASTER_MUTE, data, &reply);
- return reply.readInt32();
- }
-
- status_t setMasterBalance(float balance) override
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeFloat(balance);
- status_t status = remote()->transact(SET_MASTER_BALANCE, data, &reply);
- if (status != NO_ERROR) {
- return status;
- }
- return reply.readInt32();
- }
-
- status_t getMasterBalance(float *balance) const override
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- status_t status = remote()->transact(GET_MASTER_BALANCE, data, &reply);
- if (status != NO_ERROR) {
- return status;
- }
- status = (status_t)reply.readInt32();
- if (status != NO_ERROR) {
- return status;
- }
- *balance = reply.readFloat();
- return NO_ERROR;
- }
-
- virtual status_t setStreamVolume(audio_stream_type_t stream, float value,
- audio_io_handle_t output)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) stream);
- data.writeFloat(value);
- data.writeInt32((int32_t) output);
- remote()->transact(SET_STREAM_VOLUME, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t setStreamMute(audio_stream_type_t stream, bool muted)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) stream);
- data.writeInt32(muted);
- remote()->transact(SET_STREAM_MUTE, data, &reply);
- return reply.readInt32();
- }
-
- virtual float streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) stream);
- data.writeInt32((int32_t) output);
- remote()->transact(STREAM_VOLUME, data, &reply);
- return reply.readFloat();
- }
-
- virtual bool streamMute(audio_stream_type_t stream) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) stream);
- remote()->transact(STREAM_MUTE, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t setMode(audio_mode_t mode)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(mode);
- remote()->transact(SET_MODE, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t setMicMute(bool state)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(state);
- remote()->transact(SET_MIC_MUTE, data, &reply);
- return reply.readInt32();
- }
-
- virtual bool getMicMute() const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- remote()->transact(GET_MIC_MUTE, data, &reply);
- return reply.readInt32();
- }
-
- virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(portId);
- data.writeInt32(silenced ? 1 : 0);
- remote()->transact(SET_RECORD_SILENCED, data, &reply);
- }
-
- virtual status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) ioHandle);
- data.writeString8(keyValuePairs);
- remote()->transact(SET_PARAMETERS, data, &reply);
- return reply.readInt32();
- }
-
- virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) ioHandle);
- data.writeString8(keys);
- remote()->transact(GET_PARAMETERS, data, &reply);
- return reply.readString8();
- }
-
- virtual void registerClient(const sp<media::IAudioFlingerClient>& client)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(client));
- remote()->transact(REGISTER_CLIENT, data, &reply);
- }
-
- virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
- audio_channel_mask_t channelMask) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(sampleRate);
- data.writeInt32(format);
- data.writeInt32(channelMask);
- remote()->transact(GET_INPUTBUFFERSIZE, data, &reply);
- return reply.readInt64();
- }
-
- virtual status_t openOutput(const media::OpenOutputRequest& request,
- media::OpenOutputResponse* response)
- {
- status_t status;
- Parcel data, reply;
- return data.writeParcelable(request)
- ?: remote()->transact(OPEN_OUTPUT, data, &reply)
- ?: data.readInt32(&status)
- ?: status
- ?: data.readParcelable(response);
- }
-
- virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
- audio_io_handle_t output2)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) output1);
- data.writeInt32((int32_t) output2);
- remote()->transact(OPEN_DUPLICATE_OUTPUT, data, &reply);
- return (audio_io_handle_t) reply.readInt32();
- }
-
- virtual status_t closeOutput(audio_io_handle_t output)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) output);
- remote()->transact(CLOSE_OUTPUT, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t suspendOutput(audio_io_handle_t output)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) output);
- remote()->transact(SUSPEND_OUTPUT, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t restoreOutput(audio_io_handle_t output)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) output);
- remote()->transact(RESTORE_OUTPUT, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t openInput(const media::OpenInputRequest& request,
- media::OpenInputResponse* response)
- {
- Parcel data, reply;
- status_t status;
- return data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor())
- ?: data.writeParcelable(request)
- ?: remote()->transact(OPEN_INPUT, data, &reply)
- ?: reply.readInt32(&status)
- ?: status
- ?: reply.readParcelable(response);
- }
-
- virtual status_t closeInput(int input)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(input);
- remote()->transact(CLOSE_INPUT, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t invalidateStream(audio_stream_type_t stream)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) stream);
- remote()->transact(INVALIDATE_STREAM, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t setVoiceVolume(float volume)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeFloat(volume);
- remote()->transact(SET_VOICE_VOLUME, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
- audio_io_handle_t output) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) output);
- remote()->transact(GET_RENDER_POSITION, data, &reply);
- status_t status = reply.readInt32();
- if (status == NO_ERROR) {
- uint32_t tmp = reply.readInt32();
- if (halFrames != NULL) {
- *halFrames = tmp;
- }
- tmp = reply.readInt32();
- if (dspFrames != NULL) {
- *dspFrames = tmp;
- }
- }
- return status;
- }
-
- virtual uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) ioHandle);
- status_t status = remote()->transact(GET_INPUT_FRAMES_LOST, data, &reply);
- if (status != NO_ERROR) {
- return 0;
- }
- return (uint32_t) reply.readInt32();
- }
-
- virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) use);
- status_t status = remote()->transact(NEW_AUDIO_UNIQUE_ID, data, &reply);
- audio_unique_id_t id = AUDIO_UNIQUE_ID_ALLOCATE;
- if (status == NO_ERROR) {
- id = reply.readInt32();
- }
- return id;
- }
-
- void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid) override
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(audioSession);
- data.writeInt32((int32_t)pid);
- data.writeInt32((int32_t)uid);
- remote()->transact(ACQUIRE_AUDIO_SESSION_ID, data, &reply);
- }
-
- virtual void releaseAudioSessionId(audio_session_t audioSession, int pid)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(audioSession);
- data.writeInt32(pid);
- remote()->transact(RELEASE_AUDIO_SESSION_ID, data, &reply);
- }
-
- virtual status_t queryNumberEffects(uint32_t *numEffects) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- status_t status = remote()->transact(QUERY_NUM_EFFECTS, data, &reply);
- if (status != NO_ERROR) {
- return status;
- }
- status = reply.readInt32();
- if (status != NO_ERROR) {
- return status;
- }
- if (numEffects != NULL) {
- *numEffects = (uint32_t)reply.readInt32();
- }
- return NO_ERROR;
- }
-
- virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor) const
- {
- if (pDescriptor == NULL) {
- return BAD_VALUE;
- }
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(index);
- status_t status = remote()->transact(QUERY_EFFECT, data, &reply);
- if (status != NO_ERROR) {
- return status;
- }
- status = reply.readInt32();
- if (status != NO_ERROR) {
- return status;
- }
- reply.read(pDescriptor, sizeof(effect_descriptor_t));
- return NO_ERROR;
- }
-
- virtual status_t getEffectDescriptor(const effect_uuid_t *pUuid,
- const effect_uuid_t *pType,
- uint32_t preferredTypeFlag,
- effect_descriptor_t *pDescriptor) const
- {
- if (pUuid == NULL || pType == NULL || pDescriptor == NULL) {
- return BAD_VALUE;
- }
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.write(pUuid, sizeof(effect_uuid_t));
- data.write(pType, sizeof(effect_uuid_t));
- data.writeUint32(preferredTypeFlag);
- status_t status = remote()->transact(GET_EFFECT_DESCRIPTOR, data, &reply);
- if (status != NO_ERROR) {
- return status;
- }
- status = reply.readInt32();
- if (status != NO_ERROR) {
- return status;
- }
- reply.read(pDescriptor, sizeof(effect_descriptor_t));
- return NO_ERROR;
- }
-
- virtual status_t createEffect(const media::CreateEffectRequest& request,
- media::CreateEffectResponse* response)
- {
- Parcel data, reply;
- sp<media::IEffect> effect;
- if (response == nullptr) {
- return BAD_VALUE;
- }
- status_t status;
- status_t lStatus = data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor())
- ?: data.writeParcelable(request)
- ?: remote()->transact(CREATE_EFFECT, data, &reply)
- ?: reply.readInt32(&status)
- ?: reply.readParcelable(response)
- ?: status;
- if (lStatus != NO_ERROR) {
- ALOGE("createEffect error: %s", strerror(-lStatus));
- }
- return lStatus;
- }
-
- virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
- audio_io_handle_t dstOutput)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(session);
- data.writeInt32((int32_t) srcOutput);
- data.writeInt32((int32_t) dstOutput);
- remote()->transact(MOVE_EFFECTS, data, &reply);
- return reply.readInt32();
- }
-
- virtual void setEffectSuspended(int effectId,
- audio_session_t sessionId,
- bool suspended)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(effectId);
- data.writeInt32(sessionId);
- data.writeInt32(suspended ? 1 : 0);
- remote()->transact(SET_EFFECT_SUSPENDED, data, &reply);
- }
-
- virtual audio_module_handle_t loadHwModule(const char *name)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeCString(name);
- remote()->transact(LOAD_HW_MODULE, data, &reply);
- return (audio_module_handle_t) reply.readInt32();
- }
-
- virtual uint32_t getPrimaryOutputSamplingRate()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- remote()->transact(GET_PRIMARY_OUTPUT_SAMPLING_RATE, data, &reply);
- return reply.readInt32();
- }
-
- virtual size_t getPrimaryOutputFrameCount()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- remote()->transact(GET_PRIMARY_OUTPUT_FRAME_COUNT, data, &reply);
- return reply.readInt64();
- }
-
- virtual status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) override
- {
- Parcel data, reply;
-
- static_assert(NO_ERROR == 0, "NO_ERROR must be 0");
- return data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor())
- ?: data.writeInt32((int) isLowRamDevice)
- ?: data.writeInt64(totalMemory)
- ?: remote()->transact(SET_LOW_RAM_DEVICE, data, &reply)
- ?: reply.readInt32();
- }
-
- virtual status_t listAudioPorts(unsigned int *num_ports,
- struct audio_port *ports)
- {
- if (num_ports == NULL || *num_ports == 0 || ports == NULL) {
- return BAD_VALUE;
- }
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(*num_ports);
- status_t status = remote()->transact(LIST_AUDIO_PORTS, data, &reply);
- if (status != NO_ERROR ||
- (status = (status_t)reply.readInt32()) != NO_ERROR) {
- return status;
- }
- *num_ports = (unsigned int)reply.readInt32();
- reply.read(ports, *num_ports * sizeof(struct audio_port));
- return status;
- }
- virtual status_t getAudioPort(struct audio_port_v7 *port)
- {
- if (port == nullptr) {
- return BAD_VALUE;
- }
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.write(port, sizeof(struct audio_port_v7));
- status_t status = remote()->transact(GET_AUDIO_PORT, data, &reply);
- if (status != NO_ERROR ||
- (status = (status_t)reply.readInt32()) != NO_ERROR) {
- return status;
- }
- reply.read(port, sizeof(struct audio_port));
- return status;
- }
- virtual status_t createAudioPatch(const struct audio_patch *patch,
- audio_patch_handle_t *handle)
- {
- if (patch == NULL || handle == NULL) {
- return BAD_VALUE;
- }
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.write(patch, sizeof(struct audio_patch));
- data.write(handle, sizeof(audio_patch_handle_t));
- status_t status = remote()->transact(CREATE_AUDIO_PATCH, data, &reply);
- if (status != NO_ERROR ||
- (status = (status_t)reply.readInt32()) != NO_ERROR) {
- return status;
- }
- reply.read(handle, sizeof(audio_patch_handle_t));
- return status;
- }
- virtual status_t releaseAudioPatch(audio_patch_handle_t handle)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.write(&handle, sizeof(audio_patch_handle_t));
- status_t status = remote()->transact(RELEASE_AUDIO_PATCH, data, &reply);
- if (status != NO_ERROR) {
- status = (status_t)reply.readInt32();
- }
- return status;
- }
- virtual status_t listAudioPatches(unsigned int *num_patches,
- struct audio_patch *patches)
- {
- if (num_patches == NULL || *num_patches == 0 || patches == NULL) {
- return BAD_VALUE;
- }
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(*num_patches);
- status_t status = remote()->transact(LIST_AUDIO_PATCHES, data, &reply);
- if (status != NO_ERROR ||
- (status = (status_t)reply.readInt32()) != NO_ERROR) {
- return status;
- }
- *num_patches = (unsigned int)reply.readInt32();
- reply.read(patches, *num_patches * sizeof(struct audio_patch));
- return status;
- }
- virtual status_t setAudioPortConfig(const struct audio_port_config *config)
- {
- if (config == NULL) {
- return BAD_VALUE;
- }
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.write(config, sizeof(struct audio_port_config));
- status_t status = remote()->transact(SET_AUDIO_PORT_CONFIG, data, &reply);
- if (status != NO_ERROR) {
- status = (status_t)reply.readInt32();
- }
- return status;
- }
- virtual audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(sessionId);
- status_t status = remote()->transact(GET_AUDIO_HW_SYNC_FOR_SESSION, data, &reply);
- if (status != NO_ERROR) {
- return AUDIO_HW_SYNC_INVALID;
- }
- return (audio_hw_sync_t)reply.readInt32();
- }
- virtual status_t systemReady()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- return remote()->transact(SYSTEM_READY, data, &reply, IBinder::FLAG_ONEWAY);
- }
- virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) ioHandle);
- status_t status = remote()->transact(FRAME_COUNT_HAL, data, &reply);
- if (status != NO_ERROR) {
- return 0;
- }
- return reply.readInt64();
- }
- virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- status_t status = remote()->transact(GET_MICROPHONES, data, &reply);
- if (status != NO_ERROR ||
- (status = (status_t)reply.readInt32()) != NO_ERROR) {
- return status;
- }
- status = reply.readParcelableVector(microphones);
- return status;
- }
- virtual status_t setAudioHalPids(const std::vector<pid_t>& pids)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(pids.size());
- for (auto pid : pids) {
- data.writeInt32(pid);
- }
- status_t status = remote()->transact(SET_AUDIO_HAL_PIDS, data, &reply);
- if (status != NO_ERROR) {
- return status;
- }
- return static_cast <status_t> (reply.readInt32());
- }
-};
-
-IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
-
-// ----------------------------------------------------------------------
-
-status_t BnAudioFlinger::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch (code) {
- case CREATE_TRACK: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
-
- media::CreateTrackRequest input;
- if (data.readParcelable(&input) != NO_ERROR) {
- reply->writeInt32(DEAD_OBJECT);
- return NO_ERROR;
- }
-
- status_t status;
- media::CreateTrackResponse output;
-
- status = createTrack(input, output);
-
- LOG_ALWAYS_FATAL_IF((output.audioTrack != 0) != (status == NO_ERROR));
- reply->writeInt32(status);
- if (status != NO_ERROR) {
- return NO_ERROR;
- }
- output.writeToParcel(reply);
- return NO_ERROR;
- } break;
- case CREATE_RECORD: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
-
- media::CreateRecordRequest input;
- if (data.readParcelable(&input) != NO_ERROR) {
- reply->writeInt32(DEAD_OBJECT);
- return NO_ERROR;
- }
-
- status_t status;
- media::CreateRecordResponse output;
-
- status = createRecord(input, output);
-
- LOG_ALWAYS_FATAL_IF((output.audioRecord != 0) != (status == NO_ERROR));
- reply->writeInt32(status);
- if (status != NO_ERROR) {
- return NO_ERROR;
- }
- output.writeToParcel(reply);
- return NO_ERROR;
- } break;
- case SAMPLE_RATE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32( sampleRate((audio_io_handle_t) data.readInt32()) );
- return NO_ERROR;
- } break;
-
- // RESERVED for channelCount()
-
- case FORMAT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32( format((audio_io_handle_t) data.readInt32()) );
- return NO_ERROR;
- } break;
- case FRAME_COUNT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt64( frameCount((audio_io_handle_t) data.readInt32()) );
- return NO_ERROR;
- } break;
- case LATENCY: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32( latency((audio_io_handle_t) data.readInt32()) );
- return NO_ERROR;
- } break;
- case SET_MASTER_VOLUME: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32( setMasterVolume(data.readFloat()) );
- return NO_ERROR;
- } break;
- case SET_MASTER_MUTE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32( setMasterMute(data.readInt32()) );
- return NO_ERROR;
- } break;
- case MASTER_VOLUME: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeFloat( masterVolume() );
- return NO_ERROR;
- } break;
- case MASTER_MUTE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32( masterMute() );
- return NO_ERROR;
- } break;
- case SET_MASTER_BALANCE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32( setMasterBalance(data.readFloat()) );
- return NO_ERROR;
- } break;
- case GET_MASTER_BALANCE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- float f;
- const status_t status = getMasterBalance(&f);
- reply->writeInt32((int32_t)status);
- if (status == NO_ERROR) {
- (void)reply->writeFloat(f);
- }
- return NO_ERROR;
- } break;
- case SET_STREAM_VOLUME: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- int stream = data.readInt32();
- float volume = data.readFloat();
- audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
- reply->writeInt32( setStreamVolume((audio_stream_type_t) stream, volume, output) );
- return NO_ERROR;
- } break;
- case SET_STREAM_MUTE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- int stream = data.readInt32();
- reply->writeInt32( setStreamMute((audio_stream_type_t) stream, data.readInt32()) );
- return NO_ERROR;
- } break;
- case STREAM_VOLUME: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- int stream = data.readInt32();
- int output = data.readInt32();
- reply->writeFloat( streamVolume((audio_stream_type_t) stream, output) );
- return NO_ERROR;
- } break;
- case STREAM_MUTE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- int stream = data.readInt32();
- reply->writeInt32( streamMute((audio_stream_type_t) stream) );
- return NO_ERROR;
- } break;
- case SET_MODE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- audio_mode_t mode = (audio_mode_t) data.readInt32();
- reply->writeInt32( setMode(mode) );
- return NO_ERROR;
- } break;
- case SET_MIC_MUTE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- int state = data.readInt32();
- reply->writeInt32( setMicMute(state) );
- return NO_ERROR;
- } break;
- case GET_MIC_MUTE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32( getMicMute() );
- return NO_ERROR;
- } break;
- case SET_RECORD_SILENCED: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- audio_port_handle_t portId = data.readInt32();
- bool silenced = data.readInt32() == 1;
- setRecordSilenced(portId, silenced);
- return NO_ERROR;
- } break;
- case SET_PARAMETERS: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- audio_io_handle_t ioHandle = (audio_io_handle_t) data.readInt32();
- String8 keyValuePairs(data.readString8());
- reply->writeInt32(setParameters(ioHandle, keyValuePairs));
- return NO_ERROR;
- } break;
- case GET_PARAMETERS: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- audio_io_handle_t ioHandle = (audio_io_handle_t) data.readInt32();
- String8 keys(data.readString8());
- reply->writeString8(getParameters(ioHandle, keys));
- return NO_ERROR;
- } break;
-
- case REGISTER_CLIENT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- sp<media::IAudioFlingerClient> client = interface_cast<media::IAudioFlingerClient>(
- data.readStrongBinder());
- registerClient(client);
- return NO_ERROR;
- } break;
- case GET_INPUTBUFFERSIZE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- uint32_t sampleRate = data.readInt32();
- audio_format_t format = (audio_format_t) data.readInt32();
- audio_channel_mask_t channelMask = (audio_channel_mask_t) data.readInt32();
- reply->writeInt64( getInputBufferSize(sampleRate, format, channelMask) );
- return NO_ERROR;
- } break;
- case OPEN_OUTPUT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- status_t status;
- media::OpenOutputRequest request;
- media::OpenOutputResponse response;
- return data.readParcelable(&request)
- ?: (status = openOutput(request, &response), OK)
- ?: reply->writeInt32(status)
- ?: reply->writeParcelable(response);
- } break;
- case OPEN_DUPLICATE_OUTPUT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- audio_io_handle_t output1 = (audio_io_handle_t) data.readInt32();
- audio_io_handle_t output2 = (audio_io_handle_t) data.readInt32();
- reply->writeInt32((int32_t) openDuplicateOutput(output1, output2));
- return NO_ERROR;
- } break;
- case CLOSE_OUTPUT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32(closeOutput((audio_io_handle_t) data.readInt32()));
- return NO_ERROR;
- } break;
- case SUSPEND_OUTPUT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32(suspendOutput((audio_io_handle_t) data.readInt32()));
- return NO_ERROR;
- } break;
- case RESTORE_OUTPUT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32(restoreOutput((audio_io_handle_t) data.readInt32()));
- return NO_ERROR;
- } break;
- case OPEN_INPUT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- media::OpenInputRequest request;
- media::OpenInputResponse response;
- status_t status;
- return data.readParcelable(&request)
- ?: (status = openInput(request, &response), OK)
- ?: reply->writeInt32(status)
- ?: reply->writeParcelable(response);
- } break;
- case CLOSE_INPUT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32(closeInput((audio_io_handle_t) data.readInt32()));
- return NO_ERROR;
- } break;
- case INVALIDATE_STREAM: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- audio_stream_type_t stream = (audio_stream_type_t) data.readInt32();
- reply->writeInt32(invalidateStream(stream));
- return NO_ERROR;
- } break;
- case SET_VOICE_VOLUME: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- float volume = data.readFloat();
- reply->writeInt32( setVoiceVolume(volume) );
- return NO_ERROR;
- } break;
- case GET_RENDER_POSITION: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
- uint32_t halFrames = 0;
- uint32_t dspFrames = 0;
- status_t status = getRenderPosition(&halFrames, &dspFrames, output);
- reply->writeInt32(status);
- if (status == NO_ERROR) {
- reply->writeInt32(halFrames);
- reply->writeInt32(dspFrames);
- }
- return NO_ERROR;
- }
- case GET_INPUT_FRAMES_LOST: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- audio_io_handle_t ioHandle = (audio_io_handle_t) data.readInt32();
- reply->writeInt32((int32_t) getInputFramesLost(ioHandle));
- return NO_ERROR;
- } break;
- case NEW_AUDIO_UNIQUE_ID: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32(newAudioUniqueId((audio_unique_id_use_t) data.readInt32()));
- return NO_ERROR;
- } break;
- case ACQUIRE_AUDIO_SESSION_ID: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- audio_session_t audioSession = (audio_session_t) data.readInt32();
- const pid_t pid = (pid_t)data.readInt32();
- const uid_t uid = (uid_t)data.readInt32();
- acquireAudioSessionId(audioSession, pid, uid);
- return NO_ERROR;
- } break;
- case RELEASE_AUDIO_SESSION_ID: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- audio_session_t audioSession = (audio_session_t) data.readInt32();
- int pid = data.readInt32();
- releaseAudioSessionId(audioSession, pid);
- return NO_ERROR;
- } break;
- case QUERY_NUM_EFFECTS: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- uint32_t numEffects = 0;
- status_t status = queryNumberEffects(&numEffects);
- reply->writeInt32(status);
- if (status == NO_ERROR) {
- reply->writeInt32((int32_t)numEffects);
- }
- return NO_ERROR;
- }
- case QUERY_EFFECT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- effect_descriptor_t desc = {};
- status_t status = queryEffect(data.readInt32(), &desc);
- reply->writeInt32(status);
- if (status == NO_ERROR) {
- reply->write(&desc, sizeof(effect_descriptor_t));
- }
- return NO_ERROR;
- }
- case GET_EFFECT_DESCRIPTOR: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- effect_uuid_t uuid = {};
- if (data.read(&uuid, sizeof(effect_uuid_t)) != NO_ERROR) {
- android_errorWriteLog(0x534e4554, "139417189");
- }
- effect_uuid_t type = {};
- if (data.read(&type, sizeof(effect_uuid_t)) != NO_ERROR) {
- android_errorWriteLog(0x534e4554, "139417189");
- }
- uint32_t preferredTypeFlag = data.readUint32();
- effect_descriptor_t desc = {};
- status_t status = getEffectDescriptor(&uuid, &type, preferredTypeFlag, &desc);
- reply->writeInt32(status);
- if (status == NO_ERROR) {
- reply->write(&desc, sizeof(effect_descriptor_t));
- }
- return NO_ERROR;
- }
- case CREATE_EFFECT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
-
- media::CreateEffectRequest request;
- media::CreateEffectResponse response;
-
- return data.readParcelable(&request)
- ?: reply->writeInt32(createEffect(request, &response))
- ?: reply->writeParcelable(response);
- } break;
- case MOVE_EFFECTS: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- audio_session_t session = (audio_session_t) data.readInt32();
- audio_io_handle_t srcOutput = (audio_io_handle_t) data.readInt32();
- audio_io_handle_t dstOutput = (audio_io_handle_t) data.readInt32();
- reply->writeInt32(moveEffects(session, srcOutput, dstOutput));
- return NO_ERROR;
- } break;
- case SET_EFFECT_SUSPENDED: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- int effectId = data.readInt32();
- audio_session_t sessionId = (audio_session_t) data.readInt32();
- bool suspended = data.readInt32() == 1;
- setEffectSuspended(effectId, sessionId, suspended);
- return NO_ERROR;
- } break;
- case LOAD_HW_MODULE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32(loadHwModule(data.readCString()));
- return NO_ERROR;
- } break;
- case GET_PRIMARY_OUTPUT_SAMPLING_RATE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32(getPrimaryOutputSamplingRate());
- return NO_ERROR;
- } break;
- case GET_PRIMARY_OUTPUT_FRAME_COUNT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt64(getPrimaryOutputFrameCount());
- return NO_ERROR;
- } break;
- case SET_LOW_RAM_DEVICE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- int32_t isLowRamDevice;
- int64_t totalMemory;
- const status_t status =
- data.readInt32(&isLowRamDevice) ?:
- data.readInt64(&totalMemory) ?:
- setLowRamDevice(isLowRamDevice != 0, totalMemory);
- (void)reply->writeInt32(status);
- return NO_ERROR;
- } break;
- case LIST_AUDIO_PORTS: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- unsigned int numPortsReq = data.readInt32();
- if (numPortsReq > MAX_ITEMS_PER_LIST) {
- numPortsReq = MAX_ITEMS_PER_LIST;
- }
- unsigned int numPorts = numPortsReq;
- struct audio_port *ports =
- (struct audio_port *)calloc(numPortsReq,
- sizeof(struct audio_port));
- if (ports == NULL) {
- reply->writeInt32(NO_MEMORY);
- reply->writeInt32(0);
- return NO_ERROR;
- }
- status_t status = listAudioPorts(&numPorts, ports);
- reply->writeInt32(status);
- reply->writeInt32(numPorts);
- if (status == NO_ERROR) {
- if (numPortsReq > numPorts) {
- numPortsReq = numPorts;
- }
- reply->write(ports, numPortsReq * sizeof(struct audio_port));
- }
- free(ports);
- return NO_ERROR;
- } break;
- case GET_AUDIO_PORT: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- struct audio_port_v7 port = {};
- status_t status = data.read(&port, sizeof(struct audio_port));
- if (status != NO_ERROR) {
- ALOGE("b/23905951");
- return status;
- }
- reply->writeInt32(status);
- if (status == NO_ERROR) {
- reply->write(&port, sizeof(struct audio_port_v7));
- }
- return NO_ERROR;
- } break;
- case CREATE_AUDIO_PATCH: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- struct audio_patch patch;
- status_t status = data.read(&patch, sizeof(struct audio_patch));
- if (status != NO_ERROR) {
- return status;
- }
- audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
- status = data.read(&handle, sizeof(audio_patch_handle_t));
- if (status != NO_ERROR) {
- ALOGE("b/23905951");
- return status;
- }
- reply->writeInt32(status);
- if (status == NO_ERROR) {
- reply->write(&handle, sizeof(audio_patch_handle_t));
- }
- return NO_ERROR;
- } break;
- case RELEASE_AUDIO_PATCH: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- audio_patch_handle_t handle;
- data.read(&handle, sizeof(audio_patch_handle_t));
- status_t status = releaseAudioPatch(handle);
- reply->writeInt32(status);
- return NO_ERROR;
- } break;
- case LIST_AUDIO_PATCHES: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- unsigned int numPatchesReq = data.readInt32();
- if (numPatchesReq > MAX_ITEMS_PER_LIST) {
- numPatchesReq = MAX_ITEMS_PER_LIST;
- }
- unsigned int numPatches = numPatchesReq;
- struct audio_patch *patches =
- (struct audio_patch *)calloc(numPatchesReq,
- sizeof(struct audio_patch));
- if (patches == NULL) {
- reply->writeInt32(NO_MEMORY);
- reply->writeInt32(0);
- return NO_ERROR;
- }
- status_t status = listAudioPatches(&numPatches, patches);
- reply->writeInt32(status);
- reply->writeInt32(numPatches);
- if (status == NO_ERROR) {
- if (numPatchesReq > numPatches) {
- numPatchesReq = numPatches;
- }
- reply->write(patches, numPatchesReq * sizeof(struct audio_patch));
- }
- free(patches);
- return NO_ERROR;
- } break;
- case SET_AUDIO_PORT_CONFIG: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- struct audio_port_config config;
- status_t status = data.read(&config, sizeof(struct audio_port_config));
- if (status != NO_ERROR) {
- return status;
- }
- reply->writeInt32(status);
- return NO_ERROR;
- } break;
- case GET_AUDIO_HW_SYNC_FOR_SESSION: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32(getAudioHwSyncForSession((audio_session_t) data.readInt32()));
- return NO_ERROR;
- } break;
- case SYSTEM_READY: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- systemReady();
- return NO_ERROR;
- } break;
- case FRAME_COUNT_HAL: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt64( frameCountHAL((audio_io_handle_t) data.readInt32()) );
- return NO_ERROR;
- } break;
- case GET_MICROPHONES: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- std::vector<media::MicrophoneInfo> microphones;
- status_t status = getMicrophones(µphones);
- reply->writeInt32(status);
- if (status == NO_ERROR) {
- reply->writeParcelableVector(microphones);
- }
- return NO_ERROR;
- }
- case SET_AUDIO_HAL_PIDS: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- std::vector<pid_t> pids;
- int32_t size;
- status_t status = data.readInt32(&size);
- if (status != NO_ERROR) {
- return status;
- }
- if (size < 0) {
- return BAD_VALUE;
- }
- if (size > MAX_ITEMS_PER_LIST) {
- size = MAX_ITEMS_PER_LIST;
- }
- for (int32_t i = 0; i < size; i++) {
- int32_t pid;
- status = data.readInt32(&pid);
- if (status != NO_ERROR) {
- return status;
- }
- pids.push_back(pid);
- }
- reply->writeInt32(setAudioHalPids(pids));
- return NO_ERROR;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
+status_t AudioFlingerClientAdapter::createTrack(const media::CreateTrackRequest& input,
+ media::CreateTrackResponse& output) {
+ return statusTFromBinderStatus(mDelegate->createTrack(input, &output));
}
-// ----------------------------------------------------------------------------
+status_t AudioFlingerClientAdapter::createRecord(const media::CreateRecordRequest& input,
+ media::CreateRecordResponse& output) {
+ return statusTFromBinderStatus(mDelegate->createRecord(input, &output));
+}
+
+uint32_t AudioFlingerClientAdapter::sampleRate(audio_io_handle_t ioHandle) const {
+ auto result = [&]() -> ConversionResult<uint32_t> {
+ int32_t ioHandleAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(ioHandle));
+ int32_t aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->sampleRate(ioHandleAidl, &aidlRet)));
+ return convertIntegral<uint32_t>(aidlRet);
+ }();
+ // Failure is ignored.
+ return result.value_or(0);
+}
+
+audio_format_t AudioFlingerClientAdapter::format(audio_io_handle_t output) const {
+ auto result = [&]() -> ConversionResult<audio_format_t> {
+ int32_t outputAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(output));
+ media::audio::common::AudioFormat aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->format(outputAidl, &aidlRet)));
+ return aidl2legacy_AudioFormat_audio_format_t(aidlRet);
+ }();
+ return result.value_or(AUDIO_FORMAT_INVALID);
+}
+
+size_t AudioFlingerClientAdapter::frameCount(audio_io_handle_t ioHandle) const {
+ auto result = [&]() -> ConversionResult<size_t> {
+ int32_t ioHandleAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(ioHandle));
+ int64_t aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->frameCount(ioHandleAidl, &aidlRet)));
+ return convertIntegral<size_t>(aidlRet);
+ }();
+ // Failure is ignored.
+ return result.value_or(0);
+}
+
+uint32_t AudioFlingerClientAdapter::latency(audio_io_handle_t output) const {
+ auto result = [&]() -> ConversionResult<uint32_t> {
+ int32_t outputAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(output));
+ int32_t aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->latency(outputAidl, &aidlRet)));
+ return convertIntegral<uint32_t>(aidlRet);
+ }();
+ // Failure is ignored.
+ return result.value_or(0);
+}
+
+status_t AudioFlingerClientAdapter::setMasterVolume(float value) {
+ return statusTFromBinderStatus(mDelegate->setMasterVolume(value));
+}
+
+status_t AudioFlingerClientAdapter::setMasterMute(bool muted) {
+ return statusTFromBinderStatus(mDelegate->setMasterMute(muted));
+}
+
+float AudioFlingerClientAdapter::masterVolume() const {
+ auto result = [&]() -> ConversionResult<float> {
+ float aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->masterVolume(&aidlRet)));
+ return aidlRet;
+ }();
+ // Failure is ignored.
+ return result.value_or(0.f);
+}
+
+bool AudioFlingerClientAdapter::masterMute() const {
+ auto result = [&]() -> ConversionResult<bool> {
+ bool aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->masterMute(&aidlRet)));
+ return aidlRet;
+ }();
+ // Failure is ignored.
+ return result.value_or(false);
+}
+
+status_t AudioFlingerClientAdapter::setMasterBalance(float balance) {
+ return statusTFromBinderStatus(mDelegate->setMasterBalance(balance));
+}
+
+status_t AudioFlingerClientAdapter::getMasterBalance(float* balance) const{
+ return statusTFromBinderStatus(mDelegate->getMasterBalance(balance));
+}
+
+status_t AudioFlingerClientAdapter::setStreamVolume(audio_stream_type_t stream, float value,
+ audio_io_handle_t output) {
+ media::AudioStreamType streamAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_stream_type_t_AudioStreamType(stream));
+ int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+ return statusTFromBinderStatus(mDelegate->setStreamVolume(streamAidl, value, outputAidl));
+}
+
+status_t AudioFlingerClientAdapter::setStreamMute(audio_stream_type_t stream, bool muted) {
+ media::AudioStreamType streamAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_stream_type_t_AudioStreamType(stream));
+ return statusTFromBinderStatus(mDelegate->setStreamMute(streamAidl, muted));
+}
+
+float AudioFlingerClientAdapter::streamVolume(audio_stream_type_t stream,
+ audio_io_handle_t output) const {
+ auto result = [&]() -> ConversionResult<float> {
+ media::AudioStreamType streamAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_stream_type_t_AudioStreamType(stream));
+ int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+ float aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->streamVolume(streamAidl, outputAidl, &aidlRet)));
+ return aidlRet;
+ }();
+ // Failure is ignored.
+ return result.value_or(0.f);
+}
+
+bool AudioFlingerClientAdapter::streamMute(audio_stream_type_t stream) const {
+ auto result = [&]() -> ConversionResult<bool> {
+ media::AudioStreamType streamAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_stream_type_t_AudioStreamType(stream));
+ bool aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->streamMute(streamAidl, &aidlRet)));
+ return aidlRet;
+ }();
+ // Failure is ignored.
+ return result.value_or(false);
+}
+
+status_t AudioFlingerClientAdapter::setMode(audio_mode_t mode) {
+ media::AudioMode modeAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_mode_t_AudioMode(mode));
+ return statusTFromBinderStatus(mDelegate->setMode(modeAidl));
+}
+
+status_t AudioFlingerClientAdapter::setMicMute(bool state) {
+ return statusTFromBinderStatus(mDelegate->setMicMute(state));
+}
+
+bool AudioFlingerClientAdapter::getMicMute() const {
+ auto result = [&]() -> ConversionResult<bool> {
+ bool aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->getMicMute(&aidlRet)));
+ return aidlRet;
+ }();
+ // Failure is ignored.
+ return result.value_or(false);
+}
+
+void AudioFlingerClientAdapter::setRecordSilenced(audio_port_handle_t portId, bool silenced) {
+ auto result = [&]() -> status_t {
+ int32_t portIdAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_port_handle_t_int32_t(portId));
+ return statusTFromBinderStatus(mDelegate->setRecordSilenced(portIdAidl, silenced));
+ }();
+ // Failure is ignored.
+ (void) result;
+}
+
+status_t AudioFlingerClientAdapter::setParameters(audio_io_handle_t ioHandle,
+ const String8& keyValuePairs) {
+ int32_t ioHandleAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(ioHandle));
+ std::string keyValuePairsAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_String8_string(keyValuePairs));
+ return statusTFromBinderStatus(mDelegate->setParameters(ioHandleAidl, keyValuePairsAidl));
+}
+
+String8 AudioFlingerClientAdapter::getParameters(audio_io_handle_t ioHandle, const String8& keys)
+const {
+ auto result = [&]() -> ConversionResult<String8> {
+ int32_t ioHandleAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(ioHandle));
+ std::string keysAidl = VALUE_OR_RETURN(legacy2aidl_String8_string(keys));
+ std::string aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->getParameters(ioHandleAidl, keysAidl, &aidlRet)));
+ return aidl2legacy_string_view_String8(aidlRet);
+ }();
+ // Failure is ignored.
+ return result.value_or(String8());
+}
+
+void AudioFlingerClientAdapter::registerClient(const sp<media::IAudioFlingerClient>& client) {
+ mDelegate->registerClient(client);
+ // Failure is ignored.
+}
+
+size_t AudioFlingerClientAdapter::getInputBufferSize(uint32_t sampleRate, audio_format_t format,
+ audio_channel_mask_t channelMask) const {
+ auto result = [&]() -> ConversionResult<size_t> {
+ int32_t sampleRateAidl = VALUE_OR_RETURN(convertIntegral<int32_t>(sampleRate));
+ media::audio::common::AudioFormat formatAidl = VALUE_OR_RETURN(
+ legacy2aidl_audio_format_t_AudioFormat(format));
+ int32_t channelMaskAidl = VALUE_OR_RETURN(
+ legacy2aidl_audio_channel_mask_t_int32_t(channelMask));
+ int64_t aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->getInputBufferSize(sampleRateAidl, formatAidl, channelMaskAidl,
+ &aidlRet)));
+ return convertIntegral<size_t>(aidlRet);
+ }();
+ // Failure is ignored.
+ return result.value_or(0);
+}
+
+status_t AudioFlingerClientAdapter::openOutput(const media::OpenOutputRequest& request,
+ media::OpenOutputResponse* response) {
+ return statusTFromBinderStatus(mDelegate->openOutput(request, response));
+}
+
+audio_io_handle_t AudioFlingerClientAdapter::openDuplicateOutput(audio_io_handle_t output1,
+ audio_io_handle_t output2) {
+ auto result = [&]() -> ConversionResult<audio_io_handle_t> {
+ int32_t output1Aidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(output1));
+ int32_t output2Aidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(output2));
+ int32_t aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->openDuplicateOutput(output1Aidl, output2Aidl, &aidlRet)));
+ return aidl2legacy_int32_t_audio_io_handle_t(aidlRet);
+ }();
+ // Failure is ignored.
+ return result.value_or(0);
+}
+
+status_t AudioFlingerClientAdapter::closeOutput(audio_io_handle_t output) {
+ int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+ return statusTFromBinderStatus(mDelegate->closeOutput(outputAidl));
+}
+
+status_t AudioFlingerClientAdapter::suspendOutput(audio_io_handle_t output) {
+ int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+ return statusTFromBinderStatus(mDelegate->suspendOutput(outputAidl));
+}
+
+status_t AudioFlingerClientAdapter::restoreOutput(audio_io_handle_t output) {
+ int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+ return statusTFromBinderStatus(mDelegate->restoreOutput(outputAidl));
+}
+
+status_t AudioFlingerClientAdapter::openInput(const media::OpenInputRequest& request,
+ media::OpenInputResponse* response) {
+ return statusTFromBinderStatus(mDelegate->openInput(request, response));
+}
+
+status_t AudioFlingerClientAdapter::closeInput(audio_io_handle_t input) {
+ int32_t inputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(input));
+ return statusTFromBinderStatus(mDelegate->closeInput(inputAidl));
+}
+
+status_t AudioFlingerClientAdapter::invalidateStream(audio_stream_type_t stream) {
+ media::AudioStreamType streamAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_stream_type_t_AudioStreamType(stream));
+ return statusTFromBinderStatus(mDelegate->invalidateStream(streamAidl));
+}
+
+status_t AudioFlingerClientAdapter::setVoiceVolume(float volume) {
+ return statusTFromBinderStatus(mDelegate->setVoiceVolume(volume));
+}
+
+status_t AudioFlingerClientAdapter::getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames,
+ audio_io_handle_t output) const {
+ int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+ media::RenderPosition aidlRet;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->getRenderPosition(outputAidl, &aidlRet)));
+ if (halFrames != nullptr) {
+ *halFrames = VALUE_OR_RETURN_STATUS(convertIntegral<uint32_t>(aidlRet.halFrames));
+ }
+ if (dspFrames != nullptr) {
+ *dspFrames = VALUE_OR_RETURN_STATUS(convertIntegral<uint32_t>(aidlRet.dspFrames));
+ }
+ return OK;
+}
+
+uint32_t AudioFlingerClientAdapter::getInputFramesLost(audio_io_handle_t ioHandle) const {
+ auto result = [&]() -> ConversionResult<uint32_t> {
+ int32_t ioHandleAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(ioHandle));
+ int32_t aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->getInputFramesLost(ioHandleAidl, &aidlRet)));
+ return convertIntegral<uint32_t>(aidlRet);
+ }();
+ // Failure is ignored.
+ return result.value_or(0);
+}
+
+audio_unique_id_t AudioFlingerClientAdapter::newAudioUniqueId(audio_unique_id_use_t use) {
+ auto result = [&]() -> ConversionResult<audio_unique_id_t> {
+ media::AudioUniqueIdUse useAidl = VALUE_OR_RETURN(
+ legacy2aidl_audio_unique_id_use_t_AudioUniqueIdUse(use));
+ int32_t aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->newAudioUniqueId(useAidl, &aidlRet)));
+ return aidl2legacy_int32_t_audio_unique_id_t(aidlRet);
+ }();
+ return result.value_or(AUDIO_UNIQUE_ID_ALLOCATE);
+}
+
+void AudioFlingerClientAdapter::acquireAudioSessionId(audio_session_t audioSession, pid_t pid,
+ uid_t uid) {
+ [&]() -> status_t {
+ int32_t audioSessionAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_session_t_int32_t(audioSession));
+ int32_t pidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(pid));
+ int32_t uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(uid));
+ return statusTFromBinderStatus(
+ mDelegate->acquireAudioSessionId(audioSessionAidl, pidAidl, uidAidl));
+ }();
+ // Failure is ignored.
+}
+
+void AudioFlingerClientAdapter::releaseAudioSessionId(audio_session_t audioSession, pid_t pid) {
+ [&]() -> status_t {
+ int32_t audioSessionAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_session_t_int32_t(audioSession));
+ int32_t pidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(pid));
+ return statusTFromBinderStatus(
+ mDelegate->releaseAudioSessionId(audioSessionAidl, pidAidl));
+ }();
+ // Failure is ignored.
+}
+
+status_t AudioFlingerClientAdapter::queryNumberEffects(uint32_t* numEffects) const {
+ int32_t aidlRet;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->queryNumberEffects(&aidlRet)));
+ if (numEffects != nullptr) {
+ *numEffects = VALUE_OR_RETURN_STATUS(convertIntegral<uint32_t>(aidlRet));
+ }
+ return OK;
+}
+
+status_t
+AudioFlingerClientAdapter::queryEffect(uint32_t index, effect_descriptor_t* pDescriptor) const {
+ int32_t indexAidl = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(index));
+ media::EffectDescriptor aidlRet;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->queryEffect(indexAidl, &aidlRet)));
+ if (pDescriptor != nullptr) {
+ *pDescriptor = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_EffectDescriptor_effect_descriptor_t(aidlRet));
+ }
+ return OK;
+}
+
+status_t AudioFlingerClientAdapter::getEffectDescriptor(const effect_uuid_t* pEffectUUID,
+ const effect_uuid_t* pTypeUUID,
+ uint32_t preferredTypeFlag,
+ effect_descriptor_t* pDescriptor) const {
+ media::AudioUuid effectUuidAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_uuid_t_AudioUuid(*pEffectUUID));
+ media::AudioUuid typeUuidAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_uuid_t_AudioUuid(*pTypeUUID));
+ int32_t preferredTypeFlagAidl = VALUE_OR_RETURN_STATUS(
+ convertReinterpret<int32_t>(preferredTypeFlag));
+ media::EffectDescriptor aidlRet;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->getEffectDescriptor(effectUuidAidl, typeUuidAidl, preferredTypeFlagAidl,
+ &aidlRet)));
+ if (pDescriptor != nullptr) {
+ *pDescriptor = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_EffectDescriptor_effect_descriptor_t(aidlRet));
+ }
+ return OK;
+}
+
+status_t AudioFlingerClientAdapter::createEffect(const media::CreateEffectRequest& request,
+ media::CreateEffectResponse* response) {
+ return statusTFromBinderStatus(mDelegate->createEffect(request, response));
+}
+
+status_t
+AudioFlingerClientAdapter::moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
+ audio_io_handle_t dstOutput) {
+ int32_t sessionAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_session_t_int32_t(session));
+ int32_t srcOutputAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_io_handle_t_int32_t(srcOutput));
+ int32_t dstOutputAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_io_handle_t_int32_t(dstOutput));
+ return statusTFromBinderStatus(
+ mDelegate->moveEffects(sessionAidl, srcOutputAidl, dstOutputAidl));
+}
+
+void AudioFlingerClientAdapter::setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended) {
+ [&]() -> status_t {
+ int32_t effectIdAidl = VALUE_OR_RETURN_STATUS(convertReinterpret<int32_t>(effectId));
+ int32_t sessionIdAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_session_t_int32_t(sessionId));
+ return statusTFromBinderStatus(
+ mDelegate->setEffectSuspended(effectIdAidl, sessionIdAidl, suspended));
+ }();
+ // Failure is ignored.
+}
+
+audio_module_handle_t AudioFlingerClientAdapter::loadHwModule(const char* name) {
+ auto result = [&]() -> ConversionResult<audio_module_handle_t> {
+ std::string nameAidl(name);
+ int32_t aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->loadHwModule(nameAidl, &aidlRet)));
+ return aidl2legacy_int32_t_audio_module_handle_t(aidlRet);
+ }();
+ // Failure is ignored.
+ return result.value_or(0);
+}
+
+uint32_t AudioFlingerClientAdapter::getPrimaryOutputSamplingRate() {
+ auto result = [&]() -> ConversionResult<uint32_t> {
+ int32_t aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->getPrimaryOutputSamplingRate(&aidlRet)));
+ return convertIntegral<uint32_t>(aidlRet);
+ }();
+ // Failure is ignored.
+ return result.value_or(0);
+}
+
+size_t AudioFlingerClientAdapter::getPrimaryOutputFrameCount() {
+ auto result = [&]() -> ConversionResult<size_t> {
+ int64_t aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->getPrimaryOutputFrameCount(&aidlRet)));
+ return convertIntegral<size_t>(aidlRet);
+ }();
+ // Failure is ignored.
+ return result.value_or(0);
+}
+
+status_t AudioFlingerClientAdapter::setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) {
+ return statusTFromBinderStatus(mDelegate->setLowRamDevice(isLowRamDevice, totalMemory));
+}
+
+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;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->getAudioPort(portAidl, &aidlRet)));
+ *port = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPort_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));
+ int32_t aidlRet;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->createAudioPatch(patchAidl, &aidlRet)));
+ if (handle != nullptr) {
+ *handle = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_patch_handle_t(aidlRet));
+ }
+ return OK;
+}
+
+status_t AudioFlingerClientAdapter::releaseAudioPatch(audio_patch_handle_t handle) {
+ int32_t handleAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_patch_handle_t_int32_t(handle));
+ return statusTFromBinderStatus(mDelegate->releaseAudioPatch(handleAidl));
+}
+
+status_t AudioFlingerClientAdapter::listAudioPatches(unsigned int* num_patches,
+ struct audio_patch* patches) {
+ std::vector<media::AudioPatch> 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);
+}
+
+status_t AudioFlingerClientAdapter::setAudioPortConfig(const struct audio_port_config* config) {
+ media::AudioPortConfig configAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_port_config_AudioPortConfig(*config));
+ return statusTFromBinderStatus(mDelegate->setAudioPortConfig(configAidl));
+}
+
+audio_hw_sync_t AudioFlingerClientAdapter::getAudioHwSyncForSession(audio_session_t sessionId) {
+ auto result = [&]() -> ConversionResult<audio_hw_sync_t> {
+ int32_t sessionIdAidl = VALUE_OR_RETURN(legacy2aidl_audio_session_t_int32_t(sessionId));
+ int32_t aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->getAudioHwSyncForSession(sessionIdAidl, &aidlRet)));
+ return aidl2legacy_int32_t_audio_hw_sync_t(aidlRet);
+ }();
+ return result.value_or(AUDIO_HW_SYNC_INVALID);
+}
+
+status_t AudioFlingerClientAdapter::systemReady() {
+ return statusTFromBinderStatus(mDelegate->systemReady());
+}
+
+size_t AudioFlingerClientAdapter::frameCountHAL(audio_io_handle_t ioHandle) const {
+ auto result = [&]() -> ConversionResult<size_t> {
+ int32_t ioHandleAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(ioHandle));
+ int64_t aidlRet;
+ RETURN_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->frameCountHAL(ioHandleAidl, &aidlRet)));
+ return convertIntegral<size_t>(aidlRet);
+ }();
+ // Failure is ignored.
+ return result.value_or(0);
+}
+
+status_t
+AudioFlingerClientAdapter::getMicrophones(std::vector<media::MicrophoneInfo>* microphones) {
+ std::vector<media::MicrophoneInfoData> 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));
+ }
+ return OK;
+}
+
+status_t AudioFlingerClientAdapter::setAudioHalPids(const std::vector<pid_t>& pids) {
+ std::vector<int32_t> pidsAidl = VALUE_OR_RETURN_STATUS(
+ convertContainer<std::vector<int32_t>>(pids, legacy2aidl_pid_t_int32_t));
+ return statusTFromBinderStatus(mDelegate->setAudioHalPids(pidsAidl));
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// AudioFlingerServerAdapter
+AudioFlingerServerAdapter::AudioFlingerServerAdapter(
+ const sp<AudioFlingerServerAdapter::Delegate>& delegate) : mDelegate(delegate) {}
+
+status_t AudioFlingerServerAdapter::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) {
+ return mDelegate->onPreTransact(static_cast<Delegate::TransactionCode>(code), data, flags)
+ ?: BnAudioFlingerService::onTransact(code, data, reply, flags);
+}
+
+status_t AudioFlingerServerAdapter::dump(int fd, const Vector<String16>& args) {
+ return mDelegate->dump(fd, args);
+}
+
+Status AudioFlingerServerAdapter::createTrack(const media::CreateTrackRequest& request,
+ media::CreateTrackResponse* _aidl_return) {
+ return Status::fromStatusT(mDelegate->createTrack(request, *_aidl_return));
+}
+
+Status AudioFlingerServerAdapter::createRecord(const media::CreateRecordRequest& request,
+ media::CreateRecordResponse* _aidl_return) {
+ return Status::fromStatusT(mDelegate->createRecord(request, *_aidl_return));
+}
+
+Status AudioFlingerServerAdapter::sampleRate(int32_t ioHandle, int32_t* _aidl_return) {
+ audio_io_handle_t ioHandleLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(ioHandle));
+ *_aidl_return = VALUE_OR_RETURN_BINDER(
+ convertIntegral<int32_t>(mDelegate->sampleRate(ioHandleLegacy)));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::format(int32_t output,
+ media::audio::common::AudioFormat* _aidl_return) {
+ audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(output));
+ *_aidl_return = VALUE_OR_RETURN_BINDER(
+ legacy2aidl_audio_format_t_AudioFormat(mDelegate->format(outputLegacy)));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::frameCount(int32_t ioHandle, int64_t* _aidl_return) {
+ audio_io_handle_t ioHandleLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(ioHandle));
+ *_aidl_return = VALUE_OR_RETURN_BINDER(
+ convertIntegral<int64_t>(mDelegate->frameCount(ioHandleLegacy)));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::latency(int32_t output, int32_t* _aidl_return) {
+ audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(output));
+ *_aidl_return = VALUE_OR_RETURN_BINDER(
+ convertIntegral<int32_t>(mDelegate->latency(outputLegacy)));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::setMasterVolume(float value) {
+ return Status::fromStatusT(mDelegate->setMasterVolume(value));
+}
+
+Status AudioFlingerServerAdapter::setMasterMute(bool muted) {
+ return Status::fromStatusT(mDelegate->setMasterMute(muted));
+}
+
+Status AudioFlingerServerAdapter::masterVolume(float* _aidl_return) {
+ *_aidl_return = mDelegate->masterVolume();
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::masterMute(bool* _aidl_return) {
+ *_aidl_return = mDelegate->masterMute();
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::setMasterBalance(float balance) {
+ return Status::fromStatusT(mDelegate->setMasterBalance(balance));
+}
+
+Status AudioFlingerServerAdapter::getMasterBalance(float* _aidl_return) {
+ return Status::fromStatusT(mDelegate->getMasterBalance(_aidl_return));
+}
+
+Status AudioFlingerServerAdapter::setStreamVolume(media::AudioStreamType stream, float value,
+ int32_t output) {
+ audio_stream_type_t streamLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(stream));
+ audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(output));
+ return Status::fromStatusT(mDelegate->setStreamVolume(streamLegacy, value, outputLegacy));
+}
+
+Status AudioFlingerServerAdapter::setStreamMute(media::AudioStreamType stream, bool muted) {
+ audio_stream_type_t streamLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(stream));
+ return Status::fromStatusT(mDelegate->setStreamMute(streamLegacy, muted));
+}
+
+Status AudioFlingerServerAdapter::streamVolume(media::AudioStreamType stream, int32_t output,
+ float* _aidl_return) {
+ audio_stream_type_t streamLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(stream));
+ audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(output));
+ *_aidl_return = mDelegate->streamVolume(streamLegacy, outputLegacy);
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::streamMute(media::AudioStreamType stream, bool* _aidl_return) {
+ audio_stream_type_t streamLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(stream));
+ *_aidl_return = mDelegate->streamMute(streamLegacy);
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::setMode(media::AudioMode mode) {
+ audio_mode_t modeLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioMode_audio_mode_t(mode));
+ return Status::fromStatusT(mDelegate->setMode(modeLegacy));
+}
+
+Status AudioFlingerServerAdapter::setMicMute(bool state) {
+ return Status::fromStatusT(mDelegate->setMicMute(state));
+}
+
+Status AudioFlingerServerAdapter::getMicMute(bool* _aidl_return) {
+ *_aidl_return = mDelegate->getMicMute();
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::setRecordSilenced(int32_t portId, bool silenced) {
+ audio_port_handle_t portIdLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_port_handle_t(portId));
+ mDelegate->setRecordSilenced(portIdLegacy, silenced);
+ return Status::ok();
+}
+
+Status
+AudioFlingerServerAdapter::setParameters(int32_t ioHandle, const std::string& keyValuePairs) {
+ audio_io_handle_t ioHandleLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(ioHandle));
+ String8 keyValuePairsLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_string_view_String8(keyValuePairs));
+ return Status::fromStatusT(mDelegate->setParameters(ioHandleLegacy, keyValuePairsLegacy));
+}
+
+Status AudioFlingerServerAdapter::getParameters(int32_t ioHandle, const std::string& keys,
+ std::string* _aidl_return) {
+ audio_io_handle_t ioHandleLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(ioHandle));
+ String8 keysLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_string_view_String8(keys));
+ *_aidl_return = VALUE_OR_RETURN_BINDER(
+ legacy2aidl_String8_string(mDelegate->getParameters(ioHandleLegacy, keysLegacy)));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::registerClient(const sp<media::IAudioFlingerClient>& client) {
+ mDelegate->registerClient(client);
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::getInputBufferSize(int32_t sampleRate,
+ media::audio::common::AudioFormat format,
+ int32_t channelMask, int64_t* _aidl_return) {
+ uint32_t sampleRateLegacy = VALUE_OR_RETURN_BINDER(convertIntegral<uint32_t>(sampleRate));
+ audio_format_t formatLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_AudioFormat_audio_format_t(format));
+ audio_channel_mask_t channelMaskLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_channel_mask_t(channelMask));
+ size_t size = mDelegate->getInputBufferSize(sampleRateLegacy, formatLegacy, channelMaskLegacy);
+ *_aidl_return = VALUE_OR_RETURN_BINDER(convertIntegral<int64_t>(size));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::openOutput(const media::OpenOutputRequest& request,
+ media::OpenOutputResponse* _aidl_return) {
+ return Status::fromStatusT(mDelegate->openOutput(request, _aidl_return));
+}
+
+Status AudioFlingerServerAdapter::openDuplicateOutput(int32_t output1, int32_t output2,
+ int32_t* _aidl_return) {
+ audio_io_handle_t output1Legacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(output1));
+ audio_io_handle_t output2Legacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(output2));
+ audio_io_handle_t result = mDelegate->openDuplicateOutput(output1Legacy, output2Legacy);
+ *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_io_handle_t_int32_t(result));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::closeOutput(int32_t output) {
+ audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(output));
+ return Status::fromStatusT(mDelegate->closeOutput(outputLegacy));
+}
+
+Status AudioFlingerServerAdapter::suspendOutput(int32_t output) {
+ audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(output));
+ return Status::fromStatusT(mDelegate->suspendOutput(outputLegacy));
+}
+
+Status AudioFlingerServerAdapter::restoreOutput(int32_t output) {
+ audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(output));
+ return Status::fromStatusT(mDelegate->restoreOutput(outputLegacy));
+}
+
+Status AudioFlingerServerAdapter::openInput(const media::OpenInputRequest& request,
+ media::OpenInputResponse* _aidl_return) {
+ return Status::fromStatusT(mDelegate->openInput(request, _aidl_return));
+}
+
+Status AudioFlingerServerAdapter::closeInput(int32_t input) {
+ audio_io_handle_t inputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(input));
+ return Status::fromStatusT(mDelegate->closeInput(inputLegacy));
+}
+
+Status AudioFlingerServerAdapter::invalidateStream(media::AudioStreamType stream) {
+ audio_stream_type_t streamLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(stream));
+ return Status::fromStatusT(mDelegate->invalidateStream(streamLegacy));
+}
+
+Status AudioFlingerServerAdapter::setVoiceVolume(float volume) {
+ return Status::fromStatusT(mDelegate->setVoiceVolume(volume));
+}
+
+Status
+AudioFlingerServerAdapter::getRenderPosition(int32_t output, media::RenderPosition* _aidl_return) {
+ audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(output));
+ uint32_t halFramesLegacy;
+ uint32_t dspFramesLegacy;
+ RETURN_BINDER_IF_ERROR(
+ mDelegate->getRenderPosition(&halFramesLegacy, &dspFramesLegacy, outputLegacy));
+ _aidl_return->halFrames = VALUE_OR_RETURN_BINDER(convertIntegral<int32_t>(halFramesLegacy));
+ _aidl_return->dspFrames = VALUE_OR_RETURN_BINDER(convertIntegral<int32_t>(dspFramesLegacy));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::getInputFramesLost(int32_t ioHandle, int32_t* _aidl_return) {
+ audio_io_handle_t ioHandleLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(ioHandle));
+ uint32_t result = mDelegate->getInputFramesLost(ioHandleLegacy);
+ *_aidl_return = VALUE_OR_RETURN_BINDER(convertIntegral<int32_t>(result));
+ return Status::ok();
+}
+
+Status
+AudioFlingerServerAdapter::newAudioUniqueId(media::AudioUniqueIdUse use, int32_t* _aidl_return) {
+ audio_unique_id_use_t useLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_AudioUniqueIdUse_audio_unique_id_use_t(use));
+ audio_unique_id_t result = mDelegate->newAudioUniqueId(useLegacy);
+ *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_unique_id_t_int32_t(result));
+ return Status::ok();
+}
+
+Status
+AudioFlingerServerAdapter::acquireAudioSessionId(int32_t audioSession, int32_t pid, int32_t uid) {
+ audio_session_t audioSessionLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_session_t(audioSession));
+ pid_t pidLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_int32_t_pid_t(pid));
+ uid_t uidLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_int32_t_uid_t(uid));
+ mDelegate->acquireAudioSessionId(audioSessionLegacy, pidLegacy, uidLegacy);
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::releaseAudioSessionId(int32_t audioSession, int32_t pid) {
+ audio_session_t audioSessionLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_session_t(audioSession));
+ pid_t pidLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_int32_t_pid_t(pid));
+ mDelegate->releaseAudioSessionId(audioSessionLegacy, pidLegacy);
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::queryNumberEffects(int32_t* _aidl_return) {
+ uint32_t result;
+ RETURN_BINDER_IF_ERROR(mDelegate->queryNumberEffects(&result));
+ *_aidl_return = VALUE_OR_RETURN_BINDER(convertIntegral<uint32_t>(result));
+ return Status::ok();
+}
+
+Status
+AudioFlingerServerAdapter::queryEffect(int32_t index, media::EffectDescriptor* _aidl_return) {
+ uint32_t indexLegacy = VALUE_OR_RETURN_BINDER(convertIntegral<uint32_t>(index));
+ effect_descriptor_t result;
+ RETURN_BINDER_IF_ERROR(mDelegate->queryEffect(indexLegacy, &result));
+ *_aidl_return = VALUE_OR_RETURN_BINDER(
+ legacy2aidl_effect_descriptor_t_EffectDescriptor(result));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::getEffectDescriptor(const media::AudioUuid& effectUUID,
+ const media::AudioUuid& typeUUID,
+ int32_t preferredTypeFlag,
+ media::EffectDescriptor* _aidl_return) {
+ effect_uuid_t effectUuidLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_AudioUuid_audio_uuid_t(effectUUID));
+ effect_uuid_t typeUuidLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_AudioUuid_audio_uuid_t(typeUUID));
+ uint32_t preferredTypeFlagLegacy = VALUE_OR_RETURN_BINDER(
+ convertReinterpret<uint32_t>(preferredTypeFlag));
+ effect_descriptor_t result;
+ RETURN_BINDER_IF_ERROR(mDelegate->getEffectDescriptor(&effectUuidLegacy, &typeUuidLegacy,
+ preferredTypeFlagLegacy, &result));
+ *_aidl_return = VALUE_OR_RETURN_BINDER(
+ legacy2aidl_effect_descriptor_t_EffectDescriptor(result));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::createEffect(const media::CreateEffectRequest& request,
+ media::CreateEffectResponse* _aidl_return) {
+ return Status::fromStatusT(mDelegate->createEffect(request, _aidl_return));
+}
+
+Status
+AudioFlingerServerAdapter::moveEffects(int32_t session, int32_t srcOutput, int32_t dstOutput) {
+ audio_session_t sessionLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_session_t(session));
+ audio_io_handle_t srcOutputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(srcOutput));
+ audio_io_handle_t dstOutputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(dstOutput));
+ return Status::fromStatusT(
+ mDelegate->moveEffects(sessionLegacy, srcOutputLegacy, dstOutputLegacy));
+}
+
+Status AudioFlingerServerAdapter::setEffectSuspended(int32_t effectId, int32_t sessionId,
+ bool suspended) {
+ int effectIdLegacy = VALUE_OR_RETURN_BINDER(convertReinterpret<int>(effectId));
+ audio_session_t sessionIdLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_session_t(sessionId));
+ mDelegate->setEffectSuspended(effectIdLegacy, sessionIdLegacy, suspended);
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::loadHwModule(const std::string& name, int32_t* _aidl_return) {
+ audio_module_handle_t result = mDelegate->loadHwModule(name.c_str());
+ *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_module_handle_t_int32_t(result));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::getPrimaryOutputSamplingRate(int32_t* _aidl_return) {
+ *_aidl_return = VALUE_OR_RETURN_BINDER(
+ convertIntegral<int32_t>(mDelegate->getPrimaryOutputSamplingRate()));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::getPrimaryOutputFrameCount(int64_t* _aidl_return) {
+ *_aidl_return = VALUE_OR_RETURN_BINDER(
+ convertIntegral<int64_t>(mDelegate->getPrimaryOutputFrameCount()));
+ return Status::ok();
+
+}
+
+Status AudioFlingerServerAdapter::setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) {
+ 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));
+ RETURN_BINDER_IF_ERROR(mDelegate->getAudioPort(&portLegacy));
+ *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_port_v7_AudioPort(portLegacy));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::createAudioPatch(const media::AudioPatch& patch,
+ int32_t* _aidl_return) {
+ audio_patch patchLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPatch_audio_patch(patch));
+ audio_patch_handle_t handleLegacy;
+ RETURN_BINDER_IF_ERROR(mDelegate->createAudioPatch(&patchLegacy, &handleLegacy));
+ *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_patch_handle_t_int32_t(handleLegacy));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::releaseAudioPatch(int32_t handle) {
+ audio_patch_handle_t handleLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_patch_handle_t(handle));
+ return Status::fromStatusT(mDelegate->releaseAudioPatch(handleLegacy));
+}
+
+Status AudioFlingerServerAdapter::listAudioPatches(int32_t maxCount,
+ std::vector<media::AudioPatch>* _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]);
+ RETURN_BINDER_IF_ERROR(mDelegate->listAudioPatches(&count, patchesLegacy.get()));
+ RETURN_BINDER_IF_ERROR(convertRange(&patchesLegacy[0],
+ &patchesLegacy[count],
+ std::back_inserter(*_aidl_return),
+ legacy2aidl_audio_patch_AudioPatch));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::setAudioPortConfig(const media::AudioPortConfig& config) {
+ audio_port_config configLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_AudioPortConfig_audio_port_config(config));
+ return Status::fromStatusT(mDelegate->setAudioPortConfig(&configLegacy));
+}
+
+Status AudioFlingerServerAdapter::getAudioHwSyncForSession(int32_t sessionId,
+ int32_t* _aidl_return) {
+ audio_session_t sessionIdLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_session_t(sessionId));
+ audio_hw_sync_t result = mDelegate->getAudioHwSyncForSession(sessionIdLegacy);
+ *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_hw_sync_t_int32_t(result));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::systemReady() {
+ return Status::fromStatusT(mDelegate->systemReady());
+}
+
+Status AudioFlingerServerAdapter::frameCountHAL(int32_t ioHandle, int64_t* _aidl_return) {
+ audio_io_handle_t ioHandleLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(ioHandle));
+ size_t result = mDelegate->frameCountHAL(ioHandleLegacy);
+ *_aidl_return = VALUE_OR_RETURN_BINDER(convertIntegral<int64_t>(result));
+ return Status::ok();
+}
+
+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));
+ return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::setAudioHalPids(const std::vector<int32_t>& pids) {
+ std::vector<pid_t> pidsLegacy = VALUE_OR_RETURN_BINDER(
+ convertContainer<std::vector<pid_t>>(pids, aidl2legacy_int32_t_pid_t));
+ RETURN_BINDER_IF_ERROR(mDelegate->setAudioHalPids(pidsLegacy));
+ return Status::ok();
+}
} // namespace android
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 4132244..0849e61 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -69,7 +69,7 @@
QUERY_DEFAULT_PRE_PROCESSING,
SET_EFFECT_ENABLED,
IS_STREAM_ACTIVE_REMOTELY,
- IS_OFFLOAD_SUPPORTED,
+ GET_OFFLOAD_MODE_SUPPORTED,
IS_DIRECT_OUTPUT_SUPPORTED,
LIST_AUDIO_PORTS,
GET_AUDIO_PORT,
@@ -666,13 +666,13 @@
return reply.readInt32();
}
- virtual bool isOffloadSupported(const audio_offload_info_t& info)
+ virtual audio_offload_mode_t getOffloadSupport(const audio_offload_info_t& info)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.write(&info, sizeof(audio_offload_info_t));
- remote()->transact(IS_OFFLOAD_SUPPORTED, data, &reply);
- return reply.readInt32();
+ remote()->transact(GET_OFFLOAD_MODE_SUPPORTED, data, &reply);
+ return static_cast<audio_offload_mode_t>(reply.readInt32());
}
virtual bool isDirectOutputSupported(const audio_config_base_t& config,
@@ -688,7 +688,7 @@
virtual status_t listAudioPorts(audio_port_role_t role,
audio_port_type_t type,
unsigned int *num_ports,
- struct audio_port *ports,
+ struct audio_port_v7 *ports,
unsigned int *generation)
{
if (num_ports == NULL || (*num_ports != 0 && ports == NULL) ||
@@ -711,27 +711,27 @@
numPortsReq = *num_ports;
}
if (numPortsReq > 0) {
- reply.read(ports, numPortsReq * sizeof(struct audio_port));
+ reply.read(ports, numPortsReq * sizeof(struct audio_port_v7));
}
*generation = reply.readInt32();
}
return status;
}
- virtual status_t getAudioPort(struct audio_port *port)
+ virtual status_t getAudioPort(struct audio_port_v7 *port)
{
if (port == NULL) {
return BAD_VALUE;
}
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
- data.write(port, sizeof(struct audio_port));
+ data.write(port, sizeof(struct audio_port_v7));
status_t status = remote()->transact(GET_AUDIO_PORT, data, &reply);
if (status != NO_ERROR ||
(status = (status_t)reply.readInt32()) != NO_ERROR) {
return status;
}
- reply.read(port, sizeof(struct audio_port));
+ reply.read(port, sizeof(struct audio_port_v7));
return status;
}
@@ -810,7 +810,7 @@
return status;
}
- virtual void registerClient(const sp<IAudioPolicyServiceClient>& client)
+ virtual void registerClient(const sp<media::IAudioPolicyServiceClient>& client)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -1591,6 +1591,7 @@
case REGISTER_EFFECT:
case UNREGISTER_EFFECT:
case SET_EFFECT_ENABLED:
+ case GET_STRATEGY_FOR_STREAM:
case GET_OUTPUT_FOR_ATTR:
case MOVE_EFFECTS_TO_IO:
ALOGW("%s: transaction %d received from PID %d",
@@ -1619,6 +1620,14 @@
case INIT_STREAM_VOLUME:
case SET_STREAM_VOLUME:
case SET_VOLUME_ATTRIBUTES:
+ case GET_STREAM_VOLUME:
+ case GET_VOLUME_ATTRIBUTES:
+ case GET_MIN_VOLUME_FOR_ATTRIBUTES:
+ case GET_MAX_VOLUME_FOR_ATTRIBUTES:
+ case IS_STREAM_ACTIVE:
+ case IS_STREAM_ACTIVE_REMOTELY:
+ case IS_SOURCE_ACTIVE:
+ case GET_DEVICES_FOR_STREAM:
case REGISTER_POLICY_MIXES:
case SET_MASTER_MONO:
case GET_SURROUND_FORMATS:
@@ -2140,12 +2149,11 @@
return status;
}
- case IS_OFFLOAD_SUPPORTED: {
+ case GET_OFFLOAD_MODE_SUPPORTED: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_offload_info_t info = {};
data.read(&info, sizeof(audio_offload_info_t));
- bool isSupported = isOffloadSupported(info);
- reply->writeInt32(isSupported);
+ reply->writeInt32(static_cast<int32_t>(getOffloadSupport(info)));
return NO_ERROR;
}
@@ -2174,8 +2182,8 @@
numPortsReq = MAX_ITEMS_PER_LIST;
}
unsigned int numPorts = numPortsReq;
- struct audio_port *ports =
- (struct audio_port *)calloc(numPortsReq, sizeof(struct audio_port));
+ struct audio_port_v7 *ports =
+ (struct audio_port_v7 *)calloc(numPortsReq, sizeof(struct audio_port_v7));
if (ports == NULL) {
reply->writeInt32(NO_MEMORY);
reply->writeInt32(0);
@@ -2190,7 +2198,7 @@
if (numPortsReq > numPorts) {
numPortsReq = numPorts;
}
- reply->write(ports, numPortsReq * sizeof(struct audio_port));
+ reply->write(ports, numPortsReq * sizeof(struct audio_port_v7));
reply->writeInt32(generation);
}
free(ports);
@@ -2199,8 +2207,8 @@
case GET_AUDIO_PORT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- struct audio_port port = {};
- status_t status = data.read(&port, sizeof(struct audio_port));
+ struct audio_port_v7 port = {};
+ status_t status = data.read(&port, sizeof(struct audio_port_v7));
if (status != NO_ERROR) {
ALOGE("b/23912202");
return status;
@@ -2211,7 +2219,7 @@
}
reply->writeInt32(status);
if (status == NO_ERROR) {
- reply->write(&port, sizeof(struct audio_port));
+ reply->write(&port, sizeof(struct audio_port_v7));
}
return NO_ERROR;
}
@@ -2296,8 +2304,8 @@
case REGISTER_CLIENT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>(
- data.readStrongBinder());
+ sp<media::IAudioPolicyServiceClient> client =
+ interface_cast<media::IAudioPolicyServiceClient>(data.readStrongBinder());
registerClient(client);
return NO_ERROR;
} break;
diff --git a/media/libaudioclient/IAudioPolicyServiceClient.cpp b/media/libaudioclient/IAudioPolicyServiceClient.cpp
deleted file mode 100644
index 0f9580c..0000000
--- a/media/libaudioclient/IAudioPolicyServiceClient.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2009 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 "IAudioPolicyServiceClient"
-#include <utils/Log.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-
-#include <media/IAudioPolicyServiceClient.h>
-#include <media/AudioSystem.h>
-
-namespace android {
-
-enum {
- PORT_LIST_UPDATE = IBinder::FIRST_CALL_TRANSACTION,
- PATCH_LIST_UPDATE,
- MIX_STATE_UPDATE,
- RECORDING_CONFIGURATION_UPDATE,
- VOLUME_GROUP_CHANGED,
-};
-
-// ----------------------------------------------------------------------
-inline void readAudioConfigBaseFromParcel(const Parcel& data, audio_config_base_t *config) {
- config->sample_rate = data.readUint32();
- config->channel_mask = (audio_channel_mask_t) data.readInt32();
- config->format = (audio_format_t) data.readInt32();
-}
-
-inline void writeAudioConfigBaseToParcel(Parcel& data, const audio_config_base_t *config)
-{
- data.writeUint32(config->sample_rate);
- data.writeInt32((int32_t) config->channel_mask);
- data.writeInt32((int32_t) config->format);
-}
-
-inline void readRecordClientInfoFromParcel(const Parcel& data, record_client_info_t *clientInfo) {
- clientInfo->riid = (audio_unique_id_t) data.readInt32();
- clientInfo->uid = (uid_t) data.readUint32();
- clientInfo->session = (audio_session_t) data.readInt32();
- clientInfo->source = (audio_source_t) data.readInt32();
- data.read(&clientInfo->port_id, sizeof(audio_port_handle_t));
- clientInfo->silenced = data.readBool();
-}
-
-inline void writeRecordClientInfoToParcel(Parcel& data, const record_client_info_t *clientInfo) {
- data.writeInt32((int32_t) clientInfo->riid);
- data.writeUint32((uint32_t) clientInfo->uid);
- data.writeInt32((int32_t) clientInfo->session);
- data.writeInt32((int32_t) clientInfo->source);
- data.write(&clientInfo->port_id, sizeof(audio_port_handle_t));
- data.writeBool(clientInfo->silenced);
-}
-
-inline void readEffectVectorFromParcel(const Parcel& data,
- std::vector<effect_descriptor_t> *effects) {
- int32_t numEffects = data.readInt32();
- for (int32_t i = 0; i < numEffects; i++) {
- effect_descriptor_t effect;
- if (data.read(&effect, sizeof(effect_descriptor_t)) != NO_ERROR) {
- break;
- }
- (*effects).push_back(effect);
- }
-}
-
-inline void writeEffectVectorToParcel(Parcel& data, std::vector<effect_descriptor_t> effects) {
- data.writeUint32((uint32_t) effects.size());
- for (const auto& effect : effects) {
- if (data.write(&effect, sizeof(effect_descriptor_t)) != NO_ERROR) {
- break;
- }
- }
-}
-
-// ----------------------------------------------------------------------
-class BpAudioPolicyServiceClient : public BpInterface<IAudioPolicyServiceClient>
-{
-public:
- explicit BpAudioPolicyServiceClient(const sp<IBinder>& impl)
- : BpInterface<IAudioPolicyServiceClient>(impl)
- {
- }
-
- void onAudioPortListUpdate()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
- remote()->transact(PORT_LIST_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
- }
-
- void onAudioPatchListUpdate()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
- remote()->transact(PATCH_LIST_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
- }
-
- void onAudioVolumeGroupChanged(volume_group_t group, int flags)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
- data.writeUint32(group);
- data.writeInt32(flags);
- remote()->transact(VOLUME_GROUP_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
- }
-
- void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
- data.writeString8(regId);
- data.writeInt32(state);
- remote()->transact(MIX_STATE_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
- }
-
- void onRecordingConfigurationUpdate(int event,
- const record_client_info_t *clientInfo,
- const audio_config_base_t *clientConfig,
- std::vector<effect_descriptor_t> clientEffects,
- const audio_config_base_t *deviceConfig,
- std::vector<effect_descriptor_t> effects,
- audio_patch_handle_t patchHandle,
- audio_source_t source) {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
- data.writeInt32(event);
- writeRecordClientInfoToParcel(data, clientInfo);
- writeAudioConfigBaseToParcel(data, clientConfig);
- writeEffectVectorToParcel(data, clientEffects);
- writeAudioConfigBaseToParcel(data, deviceConfig);
- writeEffectVectorToParcel(data, effects);
- data.writeInt32(patchHandle);
- data.writeInt32((int32_t) source);
- remote()->transact(RECORDING_CONFIGURATION_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
- }
-};
-
-IMPLEMENT_META_INTERFACE(AudioPolicyServiceClient, "android.media.IAudioPolicyServiceClient");
-
-// ----------------------------------------------------------------------
-
-status_t BnAudioPolicyServiceClient::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch (code) {
- case PORT_LIST_UPDATE: {
- CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
- onAudioPortListUpdate();
- return NO_ERROR;
- } break;
- case PATCH_LIST_UPDATE: {
- CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
- onAudioPatchListUpdate();
- return NO_ERROR;
- } break;
- case VOLUME_GROUP_CHANGED: {
- CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
- volume_group_t group = static_cast<volume_group_t>(data.readUint32());
- int flags = data.readInt32();
- onAudioVolumeGroupChanged(group, flags);
- return NO_ERROR;
- } break;
- case MIX_STATE_UPDATE: {
- CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
- String8 regId = data.readString8();
- int32_t state = data.readInt32();
- onDynamicPolicyMixStateUpdate(regId, state);
- return NO_ERROR;
- } break;
- case RECORDING_CONFIGURATION_UPDATE: {
- CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
- int event = (int) data.readInt32();
- record_client_info_t clientInfo;
- audio_config_base_t clientConfig;
- audio_config_base_t deviceConfig;
- readRecordClientInfoFromParcel(data, &clientInfo);
- readAudioConfigBaseFromParcel(data, &clientConfig);
- std::vector<effect_descriptor_t> clientEffects;
- readEffectVectorFromParcel(data, &clientEffects);
- readAudioConfigBaseFromParcel(data, &deviceConfig);
- std::vector<effect_descriptor_t> effects;
- readEffectVectorFromParcel(data, &effects);
- audio_patch_handle_t patchHandle = (audio_patch_handle_t) data.readInt32();
- audio_source_t source = (audio_source_t) data.readInt32();
- onRecordingConfigurationUpdate(event, &clientInfo, &clientConfig, clientEffects,
- &deviceConfig, effects, patchHandle, source);
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-} // namespace android
diff --git a/media/libaudioclient/PlayerBase.cpp b/media/libaudioclient/PlayerBase.cpp
index c443865..8793735 100644
--- a/media/libaudioclient/PlayerBase.cpp
+++ b/media/libaudioclient/PlayerBase.cpp
@@ -15,13 +15,14 @@
*/
#include <binder/IServiceManager.h>
+#include <media/AidlConversionUtil.h>
#include <media/PlayerBase.h>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
namespace android {
-
+using aidl_utils::binderStatusFromStatusT;
using media::VolumeShaperConfiguration;
using media::VolumeShaperOperation;
@@ -29,7 +30,8 @@
PlayerBase::PlayerBase() : BnPlayer(),
mPanMultiplierL(1.0f), mPanMultiplierR(1.0f),
mVolumeMultiplierL(1.0f), mVolumeMultiplierR(1.0f),
- mPIId(PLAYER_PIID_INVALID), mLastReportedEvent(PLAYER_STATE_UNKNOWN)
+ mPIId(PLAYER_PIID_INVALID), mLastReportedEvent(PLAYER_STATE_UNKNOWN),
+ mLastReportedDeviceId(AUDIO_PORT_HANDLE_NONE)
{
ALOGD("PlayerBase::PlayerBase()");
// use checkService() to avoid blocking if audio service is not up yet
@@ -63,14 +65,26 @@
}
//------------------------------------------------------------------------------
-void PlayerBase::servicePlayerEvent(player_state_t event) {
+void PlayerBase::servicePlayerEvent(player_state_t event, audio_port_handle_t deviceId) {
if (mAudioManager != 0) {
- // only report state change
- Mutex::Autolock _l(mPlayerStateLock);
- if (event != mLastReportedEvent
- && mPIId != PLAYER_PIID_INVALID) {
- mLastReportedEvent = event;
- mAudioManager->playerEvent(mPIId, event);
+ bool changed = false;
+ {
+ Mutex::Autolock _l(mDeviceIdLock);
+ changed = mLastReportedDeviceId != deviceId;
+ mLastReportedDeviceId = deviceId;
+ }
+
+ {
+ Mutex::Autolock _l(mPlayerStateLock);
+ // PLAYER_UPDATE_DEVICE_ID is not saved as an actual state, instead it is used to update
+ // device ID only.
+ if ((event != PLAYER_UPDATE_DEVICE_ID) && (event != mLastReportedEvent)) {
+ mLastReportedEvent = event;
+ changed = true;
+ }
+ }
+ if (changed && (mPIId != PLAYER_PIID_INVALID)) {
+ mAudioManager->playerEvent(mPIId, event, deviceId);
}
}
}
@@ -83,14 +97,18 @@
}
//FIXME temporary method while some player state is outside of this class
-void PlayerBase::reportEvent(player_state_t event) {
- servicePlayerEvent(event);
+void PlayerBase::reportEvent(player_state_t event, audio_port_handle_t deviceId) {
+ servicePlayerEvent(event, deviceId);
}
-status_t PlayerBase::startWithStatus() {
+void PlayerBase::baseUpdateDeviceId(audio_port_handle_t deviceId) {
+ servicePlayerEvent(PLAYER_UPDATE_DEVICE_ID, deviceId);
+}
+
+status_t PlayerBase::startWithStatus(audio_port_handle_t deviceId) {
status_t status = playerStart();
if (status == NO_ERROR) {
- servicePlayerEvent(PLAYER_STATE_STARTED);
+ servicePlayerEvent(PLAYER_STATE_STARTED, deviceId);
} else {
ALOGW("PlayerBase::start() error %d", status);
}
@@ -100,18 +118,18 @@
status_t PlayerBase::pauseWithStatus() {
status_t status = playerPause();
if (status == NO_ERROR) {
- servicePlayerEvent(PLAYER_STATE_PAUSED);
+ servicePlayerEvent(PLAYER_STATE_PAUSED, AUDIO_PORT_HANDLE_NONE);
} else {
ALOGW("PlayerBase::pause() error %d", status);
}
return status;
}
-
status_t PlayerBase::stopWithStatus() {
status_t status = playerStop();
+
if (status == NO_ERROR) {
- servicePlayerEvent(PLAYER_STATE_STOPPED);
+ servicePlayerEvent(PLAYER_STATE_STOPPED, AUDIO_PORT_HANDLE_NONE);
} else {
ALOGW("PlayerBase::stop() error %d", status);
}
@@ -122,7 +140,12 @@
// Implementation of IPlayer
binder::Status PlayerBase::start() {
ALOGD("PlayerBase::start() from IPlayer");
- (void)startWithStatus();
+ audio_port_handle_t deviceId;
+ {
+ Mutex::Autolock _l(mDeviceIdLock);
+ deviceId = mLastReportedDeviceId;
+ }
+ (void)startWithStatus(deviceId);
return binder::Status::ok();
}
@@ -150,7 +173,7 @@
if (status != NO_ERROR) {
ALOGW("PlayerBase::setVolume() error %d", status);
}
- return binder::Status::fromStatusT(status);
+ return binderStatusFromStatusT(status);
}
binder::Status PlayerBase::setPan(float pan) {
@@ -170,7 +193,7 @@
if (status != NO_ERROR) {
ALOGW("PlayerBase::setPan() error %d", status);
}
- return binder::Status::fromStatusT(status);
+ return binderStatusFromStatusT(status);
}
binder::Status PlayerBase::setStartDelayMs(int32_t delayMs __unused) {
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index ee78a2d..c9f3ab9 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -17,6 +17,8 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "ToneGenerator"
+#include <utility>
+
#include <math.h>
#include <utils/Log.h>
#include <cutils/properties.h>
@@ -740,6 +742,11 @@
{ .duration = 0 , .waveFreq = { 0 }, 0, 0}},
.repeatCnt = ToneGenerator::TONEGEN_INF,
.repeatSegment = 0 }, // TONE_JAPAN_RADIO_ACK
+ { .segments = { { .duration = 1000, .waveFreq = { 400, 0 }, 0, 0 },
+ { .duration = 2000, .waveFreq = { 0 }, 0, 0 },
+ { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+ .repeatCnt = ToneGenerator::TONEGEN_INF,
+ .repeatSegment = 0 }, // TONE_JAPAN_RINGTONE
{ .segments = { { .duration = 375, .waveFreq = { 400, 0 }, 0, 0 },
{ .duration = 375, .waveFreq = { 0 }, 0, 0 },
{ .duration = 0 , .waveFreq = { 0 }, 0, 0}},
@@ -881,7 +888,7 @@
TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
TONE_SUP_ERROR, // TONE_SUP_ERROR
TONE_SUP_CALL_WAITING, // TONE_SUP_CALL_WAITING
- TONE_SUP_RINGTONE // TONE_SUP_RINGTONE
+ TONE_JAPAN_RINGTONE // TONE_SUP_RINGTONE
},
{ // GB
TONE_ANSI_DIAL, // TONE_SUP_DIAL
@@ -979,7 +986,9 @@
// none
//
////////////////////////////////////////////////////////////////////////////////
-ToneGenerator::ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava) {
+ToneGenerator::ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava,
+ std::string opPackageName)
+ : mOpPackageName(std::move(opPackageName)) {
ALOGV("ToneGenerator constructor: streamType=%d, volume=%f", streamType, volume);
@@ -1250,7 +1259,7 @@
////////////////////////////////////////////////////////////////////////////////
bool ToneGenerator::initAudioTrack() {
// Open audio track in mono, PCM 16bit, default sampling rate.
- mpAudioTrack = new AudioTrack();
+ mpAudioTrack = new AudioTrack(mOpPackageName);
ALOGV("AudioTrack(%p) created", mpAudioTrack.get());
audio_attributes_t attr;
diff --git a/media/libaudioclient/TrackPlayerBase.cpp b/media/libaudioclient/TrackPlayerBase.cpp
index e571838..5c73756 100644
--- a/media/libaudioclient/TrackPlayerBase.cpp
+++ b/media/libaudioclient/TrackPlayerBase.cpp
@@ -17,7 +17,7 @@
#include <media/TrackPlayerBase.h>
namespace android {
-
+using aidl_utils::binderStatusFromStatusT;
using media::VolumeShaper;
//--------------------------------------------------------------------------------------------------
@@ -36,6 +36,10 @@
void TrackPlayerBase::init(AudioTrack* pat, player_type_t playerType, audio_usage_t usage) {
PlayerBase::init(playerType, usage);
mAudioTrack = pat;
+ if (mAudioTrack != 0) {
+ mSelfAudioDeviceCallback = new SelfAudioDeviceCallback(*this);
+ mAudioTrack->addAudioDeviceCallback(mSelfAudioDeviceCallback);
+ }
}
void TrackPlayerBase::destroy() {
@@ -43,9 +47,23 @@
baseDestroy();
}
+TrackPlayerBase::SelfAudioDeviceCallback::SelfAudioDeviceCallback(PlayerBase& self) :
+ AudioSystem::AudioDeviceCallback(), mSelf(self) {
+}
+
+TrackPlayerBase::SelfAudioDeviceCallback::~SelfAudioDeviceCallback() {
+}
+
+void TrackPlayerBase::SelfAudioDeviceCallback::onAudioDeviceUpdate(audio_io_handle_t __unused,
+ audio_port_handle_t deviceId) {
+ mSelf.baseUpdateDeviceId(deviceId);
+}
+
void TrackPlayerBase::doDestroy() {
if (mAudioTrack != 0) {
mAudioTrack->stop();
+ mAudioTrack->removeAudioDeviceCallback(mSelfAudioDeviceCallback);
+ mSelfAudioDeviceCallback.clear();
// Note that there may still be another reference in post-unlock phase of SetPlayState
mAudioTrack.clear();
}
@@ -115,7 +133,7 @@
status_t s = spConfiguration->readFromParcelable(configuration)
?: spOperation->readFromParcelable(operation);
if (s != OK) {
- return binder::Status::fromStatusT(s);
+ return binderStatusFromStatusT(s);
}
if (mAudioTrack != 0) {
@@ -124,7 +142,7 @@
if (status < 0) { // a non-negative value is the volume shaper id.
ALOGE("TrackPlayerBase::applyVolumeShaper() failed with status %d", status);
}
- return binder::Status::fromStatusT(status);
+ return binderStatusFromStatusT(status);
} else {
ALOGD("TrackPlayerBase::applyVolumeShaper()"
" no AudioTrack for volume control from IPlayer");
diff --git a/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl b/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl
index cf11528..cebd8f0 100644
--- a/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl
@@ -35,4 +35,5 @@
MMAP_NOIRQ = 12,
VOIP_RX = 13,
INCALL_MUSIC = 14,
+ GAPLESS_OFFLOAD = 15,
}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
new file mode 100644
index 0000000..e63f391
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -0,0 +1,205 @@
+/*
+ * 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;
+
+import android.media.AudioMode;
+import android.media.AudioPatch;
+import android.media.AudioPort;
+import android.media.AudioPortConfig;
+import android.media.AudioStreamType;
+import android.media.AudioUniqueIdUse;
+import android.media.AudioUuid;
+import android.media.CreateEffectRequest;
+import android.media.CreateEffectResponse;
+import android.media.CreateRecordRequest;
+import android.media.CreateRecordResponse;
+import android.media.CreateTrackRequest;
+import android.media.CreateTrackResponse;
+import android.media.OpenInputRequest;
+import android.media.OpenInputResponse;
+import android.media.OpenOutputRequest;
+import android.media.OpenOutputResponse;
+import android.media.EffectDescriptor;
+import android.media.IAudioFlingerClient;
+import android.media.IAudioRecord;
+import android.media.IAudioTrack;
+import android.media.MicrophoneInfoData;
+import android.media.RenderPosition;
+import android.media.audio.common.AudioFormat;
+
+/**
+ * {@hide}
+ */
+interface IAudioFlingerService {
+ /**
+ * Creates an audio track and registers it with AudioFlinger, or null if the track cannot be
+ * created.
+ */
+ CreateTrackResponse createTrack(in CreateTrackRequest request);
+
+ CreateRecordResponse createRecord(in CreateRecordRequest request);
+
+ // FIXME Surprisingly, format/latency don't work for input handles
+
+ /**
+ * Queries the audio hardware state. This state never changes, and therefore can be cached.
+ */
+ int sampleRate(int /* audio_io_handle_t */ ioHandle);
+
+ AudioFormat format(int /* audio_io_handle_t */ output);
+
+ long frameCount(int /* audio_io_handle_t */ ioHandle);
+
+ /**
+ * Return the estimated latency in milliseconds.
+ */
+ int latency(int /* audio_io_handle_t */ output);
+
+ /*
+ * Sets/gets the audio hardware state. This will probably be used by
+ * the preference panel, mostly.
+ */
+ void setMasterVolume(float value);
+ void setMasterMute(boolean muted);
+
+ float masterVolume();
+ boolean masterMute();
+
+ void setMasterBalance(float balance);
+ float getMasterBalance();
+
+ /*
+ * Set/gets stream type state. This will probably be used by
+ * the preference panel, mostly.
+ */
+ void setStreamVolume(AudioStreamType stream, float value, int /* audio_io_handle_t */ output);
+ void setStreamMute(AudioStreamType stream, boolean muted);
+ float streamVolume(AudioStreamType stream, int /* audio_io_handle_t */ output);
+ boolean streamMute(AudioStreamType stream);
+
+ // set audio mode.
+ void setMode(AudioMode mode);
+
+ // mic mute/state
+ void setMicMute(boolean state);
+ boolean getMicMute();
+ void setRecordSilenced(int /* audio_port_handle_t */ portId,
+ boolean silenced);
+
+ void setParameters(int /* audio_io_handle_t */ ioHandle,
+ @utf8InCpp String keyValuePairs);
+ @utf8InCpp String getParameters(int /* audio_io_handle_t */ ioHandle,
+ @utf8InCpp String keys);
+
+ // Register an object to receive audio input/output change and track notifications.
+ // For a given calling pid, AudioFlinger disregards any registrations after the first.
+ // Thus the IAudioFlingerClient must be a singleton per process.
+ void registerClient(IAudioFlingerClient client);
+
+ // Retrieve the audio recording buffer size in bytes.
+ // FIXME This API assumes a route, and so should be deprecated.
+ long getInputBufferSize(int sampleRate,
+ AudioFormat format,
+ int /* audio_channel_mask_t */ channelMask);
+
+ OpenOutputResponse openOutput(in OpenOutputRequest request);
+ int /* audio_io_handle_t */ openDuplicateOutput(int /* audio_io_handle_t */ output1,
+ int /* audio_io_handle_t */ output2);
+ void closeOutput(int /* audio_io_handle_t */ output);
+ void suspendOutput(int /* audio_io_handle_t */ output);
+ void restoreOutput(int /* audio_io_handle_t */ output);
+
+ OpenInputResponse openInput(in OpenInputRequest request);
+ void closeInput(int /* audio_io_handle_t */ input);
+
+ void invalidateStream(AudioStreamType stream);
+
+ void setVoiceVolume(float volume);
+
+ RenderPosition getRenderPosition(int /* audio_io_handle_t */ output);
+
+ int getInputFramesLost(int /* audio_io_handle_t */ ioHandle);
+
+ int /* audio_unique_id_t */ newAudioUniqueId(AudioUniqueIdUse use);
+
+ void acquireAudioSessionId(int /* audio_session_t */ audioSession,
+ int /* pid_t */ pid,
+ int /* uid_t */ uid);
+ void releaseAudioSessionId(int /* audio_session_t */ audioSession,
+ int /* pid_t */ pid);
+
+ int queryNumberEffects();
+
+ EffectDescriptor queryEffect(int index);
+
+ /** preferredTypeFlag is interpreted as a uint32_t with the "effect flag" format. */
+ EffectDescriptor getEffectDescriptor(in AudioUuid effectUUID,
+ in AudioUuid typeUUID,
+ int preferredTypeFlag);
+
+ CreateEffectResponse createEffect(in CreateEffectRequest request);
+
+ void moveEffects(int /* audio_session_t */ session,
+ int /* audio_io_handle_t */ srcOutput,
+ int /* audio_io_handle_t */ dstOutput);
+
+ void setEffectSuspended(int effectId,
+ int /* audio_session_t */ sessionId,
+ boolean suspended);
+
+ int /* audio_module_handle_t */ loadHwModule(@utf8InCpp String name);
+
+ // helpers for android.media.AudioManager.getProperty(), see description there for meaning
+ // FIXME move these APIs to AudioPolicy to permit a more accurate implementation
+ // that looks on primary device for a stream with fast flag, primary flag, or first one.
+ int getPrimaryOutputSamplingRate();
+ long getPrimaryOutputFrameCount();
+
+ // Intended for AudioService to inform AudioFlinger of device's low RAM attribute,
+ // and should be called at most once. For a definition of what "low RAM" means, see
+ // android.app.ActivityManager.isLowRamDevice(). The totalMemory parameter
+ // is obtained from android.app.ActivityManager.MemoryInfo.totalMem.
+ void setLowRamDevice(boolean isLowRamDevice, long totalMemory);
+
+ /* Get attributes for a given audio port */
+ AudioPort getAudioPort(in AudioPort port);
+
+ /* Create an audio patch between several source and sink ports */
+ int /* audio_patch_handle_t */ createAudioPatch(in AudioPatch patch);
+
+ /* Release an audio patch */
+ void releaseAudioPatch(int /* audio_patch_handle_t */ handle);
+
+ /* List existing audio patches */
+ AudioPatch[] listAudioPatches(int maxCount);
+ /* Set audio port configuration */
+ void setAudioPortConfig(in AudioPortConfig config);
+
+ /* Get the HW synchronization source used for an audio session */
+ int /* audio_hw_sync_t */ getAudioHwSyncForSession(int /* audio_session_t */ sessionId);
+
+ /* Indicate JAVA services are ready (scheduling, power management ...) */
+ oneway void systemReady();
+
+ // Returns the number of frames per audio HAL buffer.
+ long frameCountHAL(int /* audio_io_handle_t */ ioHandle);
+
+ /* List available microphones and their characteristics */
+ MicrophoneInfoData[] getMicrophones();
+
+ void setAudioHalPids(in int[] /* pid_t[] */ pids);
+}
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl
new file mode 100644
index 0000000..a7782b8
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+import android.media.AudioConfigBase;
+import android.media.AudioSourceType;
+import android.media.EffectDescriptor;
+import android.media.RecordClientInfo;
+
+/**
+ * {@hide}
+ */
+oneway interface IAudioPolicyServiceClient {
+ /** Notifies a change of volume group. */
+ void onAudioVolumeGroupChanged(int /* volume_group_t */ group,
+ int flags);
+ /** Notifies a change of audio port configuration. */
+ void onAudioPortListUpdate();
+ /** Notifies a change of audio patch configuration. */
+ void onAudioPatchListUpdate();
+ /** Notifies a change in the mixing state of a specific mix in a dynamic audio policy. */
+ void onDynamicPolicyMixStateUpdate(@utf8InCpp String regId,
+ int state);
+ /** Notifies a change of audio recording configuration. */
+ void onRecordingConfigurationUpdate(int event,
+ in RecordClientInfo clientInfo,
+ in AudioConfigBase clientConfig,
+ in EffectDescriptor[] clientEffects,
+ in AudioConfigBase deviceConfig,
+ in EffectDescriptor[] effects,
+ int /* audio_patch_handle_t */ patchHandle,
+ AudioSourceType source);
+ /** Notifies a change of audio routing */
+ void onRoutingUpdated();
+}
diff --git a/media/libaudioclient/aidl/android/media/RecordClientInfo.aidl b/media/libaudioclient/aidl/android/media/RecordClientInfo.aidl
new file mode 100644
index 0000000..3280460
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/RecordClientInfo.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+import android.media.AudioSourceType;
+
+/**
+ * {@hide}
+ */
+parcelable RecordClientInfo {
+ /** Interpreted as audio_unique_id_t. */
+ int riid;
+ /** Interpreted as uid_t. */
+ int uid;
+ /** Interpreted as audio_session_t. */
+ int session;
+ AudioSourceType source;
+ /** Interpreted as audio_port_handle_t. */
+ int portId;
+ boolean silenced;
+}
diff --git a/media/libaudioclient/aidl/android/media/RenderPosition.aidl b/media/libaudioclient/aidl/android/media/RenderPosition.aidl
new file mode 100644
index 0000000..98dc17a
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/RenderPosition.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+/**
+ * {@hide}
+ */
+parcelable RenderPosition {
+ int halFrames;
+ int dspFrames;
+}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 2dc471b..56afe93 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -34,6 +34,7 @@
#include <android/media/AudioIoConfigEvent.h>
#include <android/media/AudioIoDescriptor.h>
#include <android/media/AudioMixLatencyClass.h>
+#include <android/media/AudioMode.h>
#include <android/media/AudioOutputFlags.h>
#include <android/media/AudioPort.h>
#include <android/media/AudioPortConfigType.h>
@@ -43,12 +44,14 @@
#include <android/media/AudioPortSessionExt.h>
#include <android/media/AudioProfile.h>
#include <android/media/AudioTimestampInternal.h>
+#include <android/media/AudioUniqueIdUse.h>
#include <android/media/EffectDescriptor.h>
#include <android/media/SharedFileRegion.h>
#include <binder/IMemory.h>
#include <media/AidlConversionUtil.h>
#include <media/AudioClient.h>
+#include <media/AudioCommonTypes.h>
#include <media/AudioIoDescriptor.h>
#include <media/AudioTimestamp.h>
#include <system/audio_effect.h>
@@ -75,10 +78,15 @@
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);
-// The legacy enum is unnamed. Thus, we use int.
-ConversionResult<int> aidl2legacy_AudioPortConfigType(media::AudioPortConfigType aidl);
-// The legacy enum is unnamed. Thus, we use int.
-ConversionResult<media::AudioPortConfigType> legacy2aidl_AudioPortConfigType(int 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);
+
+// The legacy enum is unnamed. Thus, we use int32_t.
+ConversionResult<int32_t> aidl2legacy_AudioPortConfigType_int32_t(
+ media::AudioPortConfigType aidl);
+// The legacy enum is unnamed. Thus, we use int32_t.
+ConversionResult<media::AudioPortConfigType> legacy2aidl_int32_t_AudioPortConfigType(
+ int32_t legacy);
ConversionResult<unsigned int> aidl2legacy_int32_t_config_mask(int32_t aidl);
ConversionResult<int32_t> legacy2aidl_config_mask_int32_t(unsigned int legacy);
@@ -124,7 +132,7 @@
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_mask_int32_t(audio_gain_mode_t legacy);
+ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy);
ConversionResult<audio_devices_t> aidl2legacy_int32_t_audio_devices_t(int32_t aidl);
ConversionResult<int32_t> legacy2aidl_audio_devices_t_int32_t(audio_devices_t legacy);
@@ -144,20 +152,26 @@
ConversionResult<media::AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
audio_output_flags_t legacy);
-ConversionResult<audio_input_flags_t> aidl2legacy_audio_input_flags_mask(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_input_flags_mask(audio_input_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_audio_output_flags_mask(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_output_flags_mask(audio_output_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::AudioIoFlags& aidl, media::AudioPortRole role, media::AudioPortType type);
ConversionResult<media::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
const audio_io_flags& legacy, audio_port_role_t role, audio_port_type_t type);
-ConversionResult<audio_port_config_device_ext> aidl2legacy_AudioPortConfigDeviceExt(
+ConversionResult<audio_port_config_device_ext>
+aidl2legacy_AudioPortConfigDeviceExt_audio_port_config_device_ext(
const media::AudioPortConfigDeviceExt& aidl);
-ConversionResult<media::AudioPortConfigDeviceExt> legacy2aidl_AudioPortConfigDeviceExt(
+ConversionResult<media::AudioPortConfigDeviceExt>
+legacy2aidl_audio_port_config_device_ext_AudioPortConfigDeviceExt(
const audio_port_config_device_ext& legacy);
ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
@@ -178,9 +192,11 @@
ConversionResult<media::AudioPortConfigMixExt> legacy2aidl_AudioPortConfigMixExt(
const audio_port_config_mix_ext& legacy, audio_port_role_t role);
-ConversionResult<audio_port_config_session_ext> aidl2legacy_AudioPortConfigSessionExt(
+ConversionResult<audio_port_config_session_ext>
+aidl2legacy_AudioPortConfigSessionExt_audio_port_config_session_ext(
const media::AudioPortConfigSessionExt& aidl);
-ConversionResult<media::AudioPortConfigSessionExt> legacy2aidl_AudioPortConfigSessionExt(
+ConversionResult<media::AudioPortConfigSessionExt>
+legacy2aidl_audio_port_config_session_ext_AudioPortConfigSessionExt(
const audio_port_config_session_ext& legacy);
ConversionResult<audio_port_config> aidl2legacy_AudioPortConfig_audio_port_config(
@@ -199,8 +215,10 @@
ConversionResult<media::AudioIoDescriptor> legacy2aidl_AudioIoDescriptor_AudioIoDescriptor(
const sp<AudioIoDescriptor>& legacy);
-ConversionResult<AudioClient> aidl2legacy_AudioClient(const media::AudioClient& aidl);
-ConversionResult<media::AudioClient> legacy2aidl_AudioClient(const AudioClient& legacy);
+ConversionResult<AudioClient> aidl2legacy_AudioClient_AudioClient(
+ const media::AudioClient& aidl);
+ConversionResult<media::AudioClient> legacy2aidl_AudioClient_AudioClient(
+ const AudioClient& legacy);
ConversionResult<audio_content_type_t>
aidl2legacy_AudioContentType_audio_content_type_t(media::AudioContentType aidl);
@@ -258,9 +276,9 @@
legacy2aidl_NullableIMemory_SharedFileRegion(const sp<IMemory>& legacy);
ConversionResult<AudioTimestamp>
-aidl2legacy_AudioTimestamp(const media::AudioTimestampInternal& aidl);
+aidl2legacy_AudioTimestampInternal_AudioTimestamp(const media::AudioTimestampInternal& aidl);
ConversionResult<media::AudioTimestampInternal>
-legacy2aidl_AudioTimestamp(const AudioTimestamp& legacy);
+legacy2aidl_AudioTimestamp_AudioTimestampInternal(const AudioTimestamp& legacy);
ConversionResult<audio_uuid_t>
aidl2legacy_AudioUuid_audio_uuid_t(const media::AudioUuid& aidl);
@@ -326,4 +344,19 @@
ConversionResult<media::AudioPort>
legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy);
+ConversionResult<audio_mode_t>
+aidl2legacy_AudioMode_audio_mode_t(media::AudioMode aidl);
+ConversionResult<media::AudioMode>
+legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy);
+
+ConversionResult<audio_unique_id_use_t>
+aidl2legacy_AudioUniqueIdUse_audio_unique_id_use_t(media::AudioUniqueIdUse aidl);
+ConversionResult<media::AudioUniqueIdUse>
+legacy2aidl_audio_unique_id_use_t_AudioUniqueIdUse(audio_unique_id_use_t legacy);
+
+ConversionResult<volume_group_t>
+aidl2legacy_int32_t_volume_group_t(int32_t aidl);
+ConversionResult<int32_t>
+legacy2aidl_volume_group_t_int32_t(volume_group_t legacy);
+
} // namespace android
diff --git a/media/libaudioclient/include/media/AidlConversionUtil.h b/media/libaudioclient/include/media/AidlConversionUtil.h
index 6bfb743..9453673 100644
--- a/media/libaudioclient/include/media/AidlConversionUtil.h
+++ b/media/libaudioclient/include/media/AidlConversionUtil.h
@@ -21,6 +21,7 @@
#include <utility>
#include <android-base/expected.h>
+#include <binder/Status.h>
namespace android {
@@ -132,4 +133,98 @@
#define UNION_SET(u, field, value) \
(u).set<std::decay_t<decltype(u)>::Tag::field>(value)
+namespace aidl_utils {
+
+/**
+ * Return the equivalent Android status_t from a binder exception code.
+ *
+ * Generally one should use statusTFromBinderStatus() instead.
+ *
+ * Exception codes can be generated from a remote Java service exception, translate
+ * them for use on the Native side.
+ *
+ * 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) {
+ 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;
+ 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_TRANSACTION_FAILED: // Native - see error code
+ case Status::EX_SERVICE_SPECIFIC: // Java ServiceSpecificException,
+ // rethrows in Java with integer error code
+ return UNKNOWN_ERROR;
+ }
+ return UNKNOWN_ERROR;
+}
+
+/**
+ * Return the equivalent Android status_t from a binder status.
+ *
+ * Used to handle errors from a AIDL method declaration
+ *
+ * [oneway] void method(type0 param0, ...)
+ *
+ * or the following (where return_type is not a status_t)
+ *
+ * return_type method(type0 param0, ...)
+ */
+static inline status_t statusTFromBinderStatus(const ::android::binder::Status &status) {
+ return status.isOk() ? OK // check OK,
+ : status.serviceSpecificErrorCode() // service-side error, not standard Java exception
+ // (fromServiceSpecificError)
+ ?: status.transactionError() // a native binder transaction error (fromStatusT)
+ ?: statusTFromExceptionCode(status.exceptionCode()); // a service-side error with a
+ // standard Java exception (fromExceptionCode)
+}
+
+/**
+ * Return a binder::Status from native service status.
+ *
+ * This is used for methods not returning an explicit status_t,
+ * where Java callers expect an exception, not an integer return value.
+ */
+static inline ::android::binder::Status binderStatusFromStatusT(
+ 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.
+ // Exception codes and service specific errors map to nicer exceptions for
+ // Java clients.
+
+ using namespace ::android::binder;
+ switch (status) {
+ case OK:
+ return Status::ok();
+ case PERMISSION_DENIED: // throw SecurityException on Java side
+ return Status::fromExceptionCode(Status::EX_SECURITY, emptyIfNull);
+ case BAD_VALUE: // throw IllegalArgumentException on Java side
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, emptyIfNull);
+ case INVALID_OPERATION: // throw IllegalStateException on Java side
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, emptyIfNull);
+ }
+
+ // A service specific error will not show on status.transactionError() so
+ // be sure to use statusTFromBinderStatus() for reliable error handling.
+
+ // throw a ServiceSpecificException.
+ return Status::fromServiceSpecificError(status, emptyIfNull);
+}
+
+} // namespace aidl_utils
+
} // namespace android
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index dfc1982..71b1e33 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -20,12 +20,13 @@
#include <sys/types.h>
#include <android/media/BnAudioFlingerClient.h>
+#include <android/media/BnAudioPolicyServiceClient.h>
+#include <media/AidlConversionUtil.h>
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioPolicy.h>
#include <media/AudioProductStrategy.h>
#include <media/AudioVolumeGroup.h>
#include <media/AudioIoDescriptor.h>
-#include <media/IAudioPolicyServiceClient.h>
#include <media/MicrophoneInfo.h>
#include <set>
#include <system/audio.h>
@@ -37,6 +38,23 @@
namespace android {
+struct record_client_info {
+ audio_unique_id_t riid;
+ uid_t uid;
+ audio_session_t session;
+ audio_source_t source;
+ audio_port_handle_t port_id;
+ bool silenced;
+};
+
+typedef struct record_client_info record_client_info_t;
+
+// AIDL conversion functions.
+ConversionResult<record_client_info_t>
+aidl2legacy_RecordClientInfo_record_client_info_t(const media::RecordClientInfo& aidl);
+ConversionResult<media::RecordClientInfo>
+legacy2aidl_record_client_info_t_RecordClientInfo(const record_client_info_t& legacy);
+
typedef void (*audio_error_callback)(status_t err);
typedef void (*dynamic_policy_callback)(int event, String8 regId, int val);
typedef void (*record_config_callback)(int event,
@@ -47,6 +65,7 @@
std::vector<effect_descriptor_t> effects,
audio_patch_handle_t patchHandle,
audio_source_t source);
+typedef void (*routing_callback)();
class IAudioFlinger;
class IAudioPolicyService;
@@ -120,6 +139,7 @@
static void setDynPolicyCallback(dynamic_policy_callback cb);
static void setRecordConfigCallback(record_config_callback);
+ static void setRoutingCallback(routing_callback cb);
// helper function to obtain AudioFlinger service handle
static const sp<IAudioFlinger> get_audio_flinger();
@@ -319,9 +339,10 @@
static status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags);
- // Check if hw offload is possible for given format, stream type, sample rate,
- // bit rate, duration, video and streaming or offload property is enabled
- static bool isOffloadSupported(const audio_offload_info_t& info);
+ // Indicate if hw offload is possible for given format, stream type, sample rate,
+ // bit rate, duration, video and streaming or offload property is enabled and when possible
+ // if gapless transitions are supported.
+ static audio_offload_mode_t getOffloadSupport(const audio_offload_info_t& info);
// check presence of audio flinger service.
// returns NO_ERROR if binding to service succeeds, DEAD_OBJECT otherwise
@@ -331,11 +352,11 @@
static status_t listAudioPorts(audio_port_role_t role,
audio_port_type_t type,
unsigned int *num_ports,
- struct audio_port *ports,
+ struct audio_port_v7 *ports,
unsigned int *generation);
/* Get attributes for a given audio port */
- static status_t getAudioPort(struct audio_port *port);
+ static status_t getAudioPort(struct audio_port_v7 *port);
/* Create an audio patch between several source and sink ports */
static status_t createAudioPatch(const struct audio_patch *patch,
@@ -579,7 +600,7 @@
};
class AudioPolicyServiceClient: public IBinder::DeathRecipient,
- public BnAudioPolicyServiceClient
+ public media::BnAudioPolicyServiceClient
{
public:
AudioPolicyServiceClient() {
@@ -597,18 +618,21 @@
virtual void binderDied(const wp<IBinder>& who);
// IAudioPolicyServiceClient
- virtual void onAudioPortListUpdate();
- virtual void onAudioPatchListUpdate();
- virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags);
- virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
- virtual void onRecordingConfigurationUpdate(int event,
- const record_client_info_t *clientInfo,
- const audio_config_base_t *clientConfig,
- std::vector<effect_descriptor_t> clientEffects,
- const audio_config_base_t *deviceConfig,
- std::vector<effect_descriptor_t> effects,
- audio_patch_handle_t patchHandle,
- audio_source_t source);
+ binder::Status onAudioVolumeGroupChanged(int32_t group, int32_t flags) override;
+ binder::Status onAudioPortListUpdate() override;
+ binder::Status onAudioPatchListUpdate() override;
+ binder::Status onDynamicPolicyMixStateUpdate(const std::string& regId,
+ int32_t state) override;
+ binder::Status onRecordingConfigurationUpdate(
+ int32_t event,
+ const media::RecordClientInfo& clientInfo,
+ const media::AudioConfigBase& clientConfig,
+ const std::vector<media::EffectDescriptor>& clientEffects,
+ const media::AudioConfigBase& deviceConfig,
+ const std::vector<media::EffectDescriptor>& effects,
+ int32_t patchHandle,
+ media::AudioSourceType source) override;
+ binder::Status onRoutingUpdated();
private:
Mutex mLock;
@@ -635,6 +659,7 @@
static std::set<audio_error_callback> gAudioErrorCallbacks;
static dynamic_policy_callback gDynPolicyCallback;
static record_config_callback gRecordConfigCallback;
+ static routing_callback gRoutingCallback;
static size_t gInBuffSize;
// previous parameters for recording buffer size queries
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 911a34f..9a8014d 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -24,8 +24,6 @@
#include <utils/RefBase.h>
#include <utils/Errors.h>
#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <binder/Parcelable.h>
#include <media/AidlConversion.h>
#include <media/AudioClient.h>
#include <media/DeviceDescriptorBase.h>
@@ -37,6 +35,8 @@
#include <string>
#include <vector>
+#include <android/media/BnAudioFlingerService.h>
+#include <android/media/BpAudioFlingerService.h>
#include "android/media/CreateEffectRequest.h"
#include "android/media/CreateEffectResponse.h"
#include "android/media/CreateRecordRequest.h"
@@ -58,10 +58,11 @@
// ----------------------------------------------------------------------------
-class IAudioFlinger : public IInterface
-{
+class IAudioFlinger : public RefBase {
public:
- DECLARE_META_INTERFACE(AudioFlinger);
+ static constexpr char DEFAULT_SERVICE_NAME[] = "media.audio_flinger";
+
+ virtual ~IAudioFlinger() = default;
/* CreateTrackInput contains all input arguments sent by AudioTrack to AudioFlinger
* when calling createTrack() including arguments that will be updated by AudioFlinger
@@ -162,7 +163,8 @@
sp<media::IAudioRecord> audioRecord;
ConversionResult<media::CreateRecordResponse> toAidl() const;
- static ConversionResult<CreateRecordOutput> fromAidl(const media::CreateRecordResponse& aidl);
+ static ConversionResult<CreateRecordOutput>
+ fromAidl(const media::CreateRecordResponse& aidl);
};
/* create an audio track and registers it with AudioFlinger.
@@ -300,10 +302,6 @@
// is obtained from android.app.ActivityManager.MemoryInfo.totalMem.
virtual status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) = 0;
- /* List available audio ports and their attributes */
- virtual status_t listAudioPorts(unsigned int *num_ports,
- struct audio_port *ports) = 0;
-
/* Get attributes for a given audio port */
virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
@@ -333,85 +331,284 @@
virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
virtual status_t setAudioHalPids(const std::vector<pid_t>& pids) = 0;
-
-protected:
- enum {
- CREATE_TRACK = IBinder::FIRST_CALL_TRANSACTION,
- CREATE_RECORD,
- SAMPLE_RATE,
- RESERVED, // obsolete, was CHANNEL_COUNT
- FORMAT,
- FRAME_COUNT,
- LATENCY,
- SET_MASTER_VOLUME,
- SET_MASTER_MUTE,
- MASTER_VOLUME,
- MASTER_MUTE,
- SET_STREAM_VOLUME,
- SET_STREAM_MUTE,
- STREAM_VOLUME,
- STREAM_MUTE,
- SET_MODE,
- SET_MIC_MUTE,
- GET_MIC_MUTE,
- SET_RECORD_SILENCED,
- SET_PARAMETERS,
- GET_PARAMETERS,
- REGISTER_CLIENT,
- GET_INPUTBUFFERSIZE,
- OPEN_OUTPUT,
- OPEN_DUPLICATE_OUTPUT,
- CLOSE_OUTPUT,
- SUSPEND_OUTPUT,
- RESTORE_OUTPUT,
- OPEN_INPUT,
- CLOSE_INPUT,
- INVALIDATE_STREAM,
- SET_VOICE_VOLUME,
- GET_RENDER_POSITION,
- GET_INPUT_FRAMES_LOST,
- NEW_AUDIO_UNIQUE_ID,
- ACQUIRE_AUDIO_SESSION_ID,
- RELEASE_AUDIO_SESSION_ID,
- QUERY_NUM_EFFECTS,
- QUERY_EFFECT,
- GET_EFFECT_DESCRIPTOR,
- CREATE_EFFECT,
- MOVE_EFFECTS,
- LOAD_HW_MODULE,
- GET_PRIMARY_OUTPUT_SAMPLING_RATE,
- GET_PRIMARY_OUTPUT_FRAME_COUNT,
- SET_LOW_RAM_DEVICE,
- LIST_AUDIO_PORTS,
- GET_AUDIO_PORT,
- CREATE_AUDIO_PATCH,
- RELEASE_AUDIO_PATCH,
- LIST_AUDIO_PATCHES,
- SET_AUDIO_PORT_CONFIG,
- GET_AUDIO_HW_SYNC_FOR_SESSION,
- SYSTEM_READY,
- FRAME_COUNT_HAL,
- GET_MICROPHONES,
- SET_MASTER_BALANCE,
- GET_MASTER_BALANCE,
- SET_EFFECT_SUSPENDED,
- SET_AUDIO_HAL_PIDS
- };
};
-
-// ----------------------------------------------------------------------------
-
-class BnAudioFlinger : public BnInterface<IAudioFlinger>
-{
+/**
+ * A client-side adapter, wrapping an IAudioFlingerService instance and presenting it as an
+ * IAudioFlinger. Intended to be used by legacy client code that was written against IAudioFlinger,
+ * before IAudioFlingerService was introduced as an AIDL service.
+ * New clients should not use this adapter, but rather IAudioFlingerService directly, via
+ * BpAudioFlingerService.
+ */
+class AudioFlingerClientAdapter : public IAudioFlinger {
public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
+ explicit AudioFlingerClientAdapter(const sp<media::IAudioFlingerService> delegate);
+
+ status_t createTrack(const media::CreateTrackRequest& input,
+ media::CreateTrackResponse& output) override;
+ status_t createRecord(const media::CreateRecordRequest& input,
+ media::CreateRecordResponse& output) override;
+ uint32_t sampleRate(audio_io_handle_t ioHandle) const override;
+ audio_format_t format(audio_io_handle_t output) const override;
+ size_t frameCount(audio_io_handle_t ioHandle) const override;
+ uint32_t latency(audio_io_handle_t output) const override;
+ status_t setMasterVolume(float value) override;
+ status_t setMasterMute(bool muted) override;
+ float masterVolume() const override;
+ bool masterMute() const override;
+ status_t setMasterBalance(float balance) override;
+ status_t getMasterBalance(float* balance) const override;
+ status_t setStreamVolume(audio_stream_type_t stream, float value,
+ audio_io_handle_t output) override;
+ status_t setStreamMute(audio_stream_type_t stream, bool muted) override;
+ float streamVolume(audio_stream_type_t stream,
+ audio_io_handle_t output) const override;
+ bool streamMute(audio_stream_type_t stream) const override;
+ status_t setMode(audio_mode_t mode) override;
+ status_t setMicMute(bool state) override;
+ bool getMicMute() const override;
+ void setRecordSilenced(audio_port_handle_t portId, bool silenced) override;
+ status_t setParameters(audio_io_handle_t ioHandle,
+ const String8& keyValuePairs) override;
+ String8 getParameters(audio_io_handle_t ioHandle, const String8& keys)
+ const override;
+ void registerClient(const sp<media::IAudioFlingerClient>& client) override;
+ size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
+ audio_channel_mask_t channelMask) const override;
+ status_t openOutput(const media::OpenOutputRequest& request,
+ media::OpenOutputResponse* response) override;
+ audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
+ audio_io_handle_t output2) override;
+ status_t closeOutput(audio_io_handle_t output) override;
+ status_t suspendOutput(audio_io_handle_t output) override;
+ status_t restoreOutput(audio_io_handle_t output) override;
+ status_t openInput(const media::OpenInputRequest& request,
+ media::OpenInputResponse* response) override;
+ status_t closeInput(audio_io_handle_t input) override;
+ status_t invalidateStream(audio_stream_type_t stream) override;
+ status_t setVoiceVolume(float volume) override;
+ status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames,
+ audio_io_handle_t output) const override;
+ uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const override;
+ audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) override;
+ void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid) override;
+ void releaseAudioSessionId(audio_session_t audioSession, pid_t pid) override;
+ status_t queryNumberEffects(uint32_t* numEffects) const override;
+ status_t queryEffect(uint32_t index, effect_descriptor_t* pDescriptor) const override;
+ status_t getEffectDescriptor(const effect_uuid_t* pEffectUUID,
+ const effect_uuid_t* pTypeUUID,
+ uint32_t preferredTypeFlag,
+ effect_descriptor_t* pDescriptor) const override;
+ status_t createEffect(const media::CreateEffectRequest& request,
+ media::CreateEffectResponse* response) override;
+ status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
+ audio_io_handle_t dstOutput) override;
+ void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended) override;
+ audio_module_handle_t loadHwModule(const char* name) override;
+ uint32_t getPrimaryOutputSamplingRate() override;
+ size_t getPrimaryOutputFrameCount() override;
+ status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) override;
+ status_t getAudioPort(struct audio_port_v7* port) override;
+ status_t createAudioPatch(const struct audio_patch* patch,
+ audio_patch_handle_t* handle) override;
+ status_t releaseAudioPatch(audio_patch_handle_t handle) override;
+ status_t listAudioPatches(unsigned int* num_patches,
+ struct audio_patch* patches) override;
+ status_t setAudioPortConfig(const struct audio_port_config* config) override;
+ audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId) override;
+ status_t systemReady() override;
+ size_t frameCountHAL(audio_io_handle_t ioHandle) const override;
+ status_t getMicrophones(std::vector<media::MicrophoneInfo>* microphones) override;
+ status_t setAudioHalPids(const std::vector<pid_t>& pids) override;
+
+private:
+ const sp<media::IAudioFlingerService> mDelegate;
};
-// ----------------------------------------------------------------------------
+/**
+ * A server-side adapter, wrapping an IAudioFlinger instance and presenting it as an
+ * IAudioFlingerService. Intended to be used by legacy server code that was written against
+ * IAudioFlinger, before IAudioFlingerService was introduced as an AIDL service.
+ * New servers should not use this adapter, but rather implement IAudioFlingerService directly, via
+ * BnAudioFlingerService.
+ */
+class AudioFlingerServerAdapter : public media::BnAudioFlingerService {
+public:
+ using Status = binder::Status;
+
+ /**
+ * Legacy server should implement this interface in order to be wrapped.
+ */
+ class Delegate : public IAudioFlinger {
+ protected:
+ friend class AudioFlingerServerAdapter;
+
+ enum class TransactionCode {
+ CREATE_TRACK = media::BnAudioFlingerService::TRANSACTION_createTrack,
+ CREATE_RECORD = media::BnAudioFlingerService::TRANSACTION_createRecord,
+ SAMPLE_RATE = media::BnAudioFlingerService::TRANSACTION_sampleRate,
+ FORMAT = media::BnAudioFlingerService::TRANSACTION_format,
+ FRAME_COUNT = media::BnAudioFlingerService::TRANSACTION_frameCount,
+ LATENCY = media::BnAudioFlingerService::TRANSACTION_latency,
+ SET_MASTER_VOLUME = media::BnAudioFlingerService::TRANSACTION_setMasterVolume,
+ SET_MASTER_MUTE = media::BnAudioFlingerService::TRANSACTION_setMasterMute,
+ MASTER_VOLUME = media::BnAudioFlingerService::TRANSACTION_masterVolume,
+ MASTER_MUTE = media::BnAudioFlingerService::TRANSACTION_masterMute,
+ SET_STREAM_VOLUME = media::BnAudioFlingerService::TRANSACTION_setStreamVolume,
+ SET_STREAM_MUTE = media::BnAudioFlingerService::TRANSACTION_setStreamMute,
+ STREAM_VOLUME = media::BnAudioFlingerService::TRANSACTION_streamVolume,
+ STREAM_MUTE = media::BnAudioFlingerService::TRANSACTION_streamMute,
+ SET_MODE = media::BnAudioFlingerService::TRANSACTION_setMode,
+ SET_MIC_MUTE = media::BnAudioFlingerService::TRANSACTION_setMicMute,
+ GET_MIC_MUTE = media::BnAudioFlingerService::TRANSACTION_getMicMute,
+ SET_RECORD_SILENCED = media::BnAudioFlingerService::TRANSACTION_setRecordSilenced,
+ SET_PARAMETERS = media::BnAudioFlingerService::TRANSACTION_setParameters,
+ GET_PARAMETERS = media::BnAudioFlingerService::TRANSACTION_getParameters,
+ REGISTER_CLIENT = media::BnAudioFlingerService::TRANSACTION_registerClient,
+ GET_INPUTBUFFERSIZE = media::BnAudioFlingerService::TRANSACTION_getInputBufferSize,
+ OPEN_OUTPUT = media::BnAudioFlingerService::TRANSACTION_openOutput,
+ OPEN_DUPLICATE_OUTPUT = media::BnAudioFlingerService::TRANSACTION_openDuplicateOutput,
+ CLOSE_OUTPUT = media::BnAudioFlingerService::TRANSACTION_closeOutput,
+ SUSPEND_OUTPUT = media::BnAudioFlingerService::TRANSACTION_suspendOutput,
+ RESTORE_OUTPUT = media::BnAudioFlingerService::TRANSACTION_restoreOutput,
+ OPEN_INPUT = media::BnAudioFlingerService::TRANSACTION_openInput,
+ CLOSE_INPUT = media::BnAudioFlingerService::TRANSACTION_closeInput,
+ INVALIDATE_STREAM = media::BnAudioFlingerService::TRANSACTION_invalidateStream,
+ SET_VOICE_VOLUME = media::BnAudioFlingerService::TRANSACTION_setVoiceVolume,
+ GET_RENDER_POSITION = media::BnAudioFlingerService::TRANSACTION_getRenderPosition,
+ GET_INPUT_FRAMES_LOST = media::BnAudioFlingerService::TRANSACTION_getInputFramesLost,
+ NEW_AUDIO_UNIQUE_ID = media::BnAudioFlingerService::TRANSACTION_newAudioUniqueId,
+ ACQUIRE_AUDIO_SESSION_ID = media::BnAudioFlingerService::TRANSACTION_acquireAudioSessionId,
+ RELEASE_AUDIO_SESSION_ID = media::BnAudioFlingerService::TRANSACTION_releaseAudioSessionId,
+ QUERY_NUM_EFFECTS = media::BnAudioFlingerService::TRANSACTION_queryNumberEffects,
+ QUERY_EFFECT = media::BnAudioFlingerService::TRANSACTION_queryEffect,
+ GET_EFFECT_DESCRIPTOR = media::BnAudioFlingerService::TRANSACTION_getEffectDescriptor,
+ CREATE_EFFECT = media::BnAudioFlingerService::TRANSACTION_createEffect,
+ MOVE_EFFECTS = media::BnAudioFlingerService::TRANSACTION_moveEffects,
+ LOAD_HW_MODULE = media::BnAudioFlingerService::TRANSACTION_loadHwModule,
+ GET_PRIMARY_OUTPUT_SAMPLING_RATE = media::BnAudioFlingerService::TRANSACTION_getPrimaryOutputSamplingRate,
+ GET_PRIMARY_OUTPUT_FRAME_COUNT = media::BnAudioFlingerService::TRANSACTION_getPrimaryOutputFrameCount,
+ SET_LOW_RAM_DEVICE = media::BnAudioFlingerService::TRANSACTION_setLowRamDevice,
+ GET_AUDIO_PORT = media::BnAudioFlingerService::TRANSACTION_getAudioPort,
+ CREATE_AUDIO_PATCH = media::BnAudioFlingerService::TRANSACTION_createAudioPatch,
+ RELEASE_AUDIO_PATCH = media::BnAudioFlingerService::TRANSACTION_releaseAudioPatch,
+ LIST_AUDIO_PATCHES = media::BnAudioFlingerService::TRANSACTION_listAudioPatches,
+ SET_AUDIO_PORT_CONFIG = media::BnAudioFlingerService::TRANSACTION_setAudioPortConfig,
+ GET_AUDIO_HW_SYNC_FOR_SESSION = media::BnAudioFlingerService::TRANSACTION_getAudioHwSyncForSession,
+ SYSTEM_READY = media::BnAudioFlingerService::TRANSACTION_systemReady,
+ FRAME_COUNT_HAL = media::BnAudioFlingerService::TRANSACTION_frameCountHAL,
+ GET_MICROPHONES = media::BnAudioFlingerService::TRANSACTION_getMicrophones,
+ SET_MASTER_BALANCE = media::BnAudioFlingerService::TRANSACTION_setMasterBalance,
+ GET_MASTER_BALANCE = media::BnAudioFlingerService::TRANSACTION_getMasterBalance,
+ SET_EFFECT_SUSPENDED = media::BnAudioFlingerService::TRANSACTION_setEffectSuspended,
+ SET_AUDIO_HAL_PIDS = media::BnAudioFlingerService::TRANSACTION_setAudioHalPids,
+ };
+
+ /**
+ * And optional hook, called on every transaction, before unparceling the data and
+ * dispatching to the respective method. Useful for bulk operations, such as logging or
+ * permission checks.
+ * If an error status is returned, the transaction will return immediately and will not be
+ * processed.
+ */
+ virtual status_t onPreTransact(TransactionCode code, const Parcel& data, uint32_t flags) {
+ (void) code;
+ (void) data;
+ (void) flags;
+ return OK;
+ };
+
+ /**
+ * An optional hook for implementing diagnostics dumping.
+ */
+ virtual status_t dump(int fd, const Vector<String16>& args) {
+ (void) fd;
+ (void) args;
+ return OK;
+ }
+ };
+
+ explicit AudioFlingerServerAdapter(
+ const sp<AudioFlingerServerAdapter::Delegate>& delegate);
+
+ status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
+ status_t dump(int fd, const Vector<String16>& args) override;
+
+ Status createTrack(const media::CreateTrackRequest& request,
+ media::CreateTrackResponse* _aidl_return) override;
+ Status createRecord(const media::CreateRecordRequest& request,
+ media::CreateRecordResponse* _aidl_return) override;
+ Status sampleRate(int32_t ioHandle, int32_t* _aidl_return) override;
+ Status format(int32_t output, media::audio::common::AudioFormat* _aidl_return) override;
+ Status frameCount(int32_t ioHandle, int64_t* _aidl_return) override;
+ Status latency(int32_t output, int32_t* _aidl_return) override;
+ Status setMasterVolume(float value) override;
+ Status setMasterMute(bool muted) override;
+ Status masterVolume(float* _aidl_return) override;
+ Status masterMute(bool* _aidl_return) override;
+ Status setMasterBalance(float balance) override;
+ Status getMasterBalance(float* _aidl_return) override;
+ Status setStreamVolume(media::AudioStreamType stream, float value, int32_t output) override;
+ Status setStreamMute(media::AudioStreamType stream, bool muted) override;
+ Status
+ streamVolume(media::AudioStreamType stream, int32_t output, float* _aidl_return) override;
+ Status streamMute(media::AudioStreamType stream, bool* _aidl_return) override;
+ Status setMode(media::AudioMode mode) override;
+ Status setMicMute(bool state) override;
+ Status getMicMute(bool* _aidl_return) override;
+ Status setRecordSilenced(int32_t portId, bool silenced) override;
+ Status setParameters(int32_t ioHandle, const std::string& keyValuePairs) override;
+ Status
+ getParameters(int32_t ioHandle, const std::string& keys, std::string* _aidl_return) override;
+ Status registerClient(const sp<media::IAudioFlingerClient>& client) override;
+ Status getInputBufferSize(int32_t sampleRate, media::audio::common::AudioFormat format,
+ int32_t channelMask, int64_t* _aidl_return) override;
+ Status openOutput(const media::OpenOutputRequest& request,
+ media::OpenOutputResponse* _aidl_return) override;
+ Status openDuplicateOutput(int32_t output1, int32_t output2, int32_t* _aidl_return) override;
+ Status closeOutput(int32_t output) override;
+ Status suspendOutput(int32_t output) override;
+ Status restoreOutput(int32_t output) override;
+ Status openInput(const media::OpenInputRequest& request,
+ media::OpenInputResponse* _aidl_return) override;
+ Status closeInput(int32_t input) override;
+ Status invalidateStream(media::AudioStreamType stream) override;
+ Status setVoiceVolume(float volume) override;
+ Status getRenderPosition(int32_t output, media::RenderPosition* _aidl_return) override;
+ Status getInputFramesLost(int32_t ioHandle, int32_t* _aidl_return) override;
+ Status newAudioUniqueId(media::AudioUniqueIdUse use, int32_t* _aidl_return) override;
+ Status acquireAudioSessionId(int32_t audioSession, int32_t pid, int32_t uid) override;
+ Status releaseAudioSessionId(int32_t audioSession, int32_t pid) override;
+ Status queryNumberEffects(int32_t* _aidl_return) override;
+ Status queryEffect(int32_t index, media::EffectDescriptor* _aidl_return) override;
+ Status getEffectDescriptor(const media::AudioUuid& effectUUID, const media::AudioUuid& typeUUID,
+ int32_t preferredTypeFlag,
+ media::EffectDescriptor* _aidl_return) override;
+ Status createEffect(const media::CreateEffectRequest& request,
+ media::CreateEffectResponse* _aidl_return) override;
+ Status moveEffects(int32_t session, int32_t srcOutput, int32_t dstOutput) override;
+ Status setEffectSuspended(int32_t effectId, int32_t sessionId, bool suspended) override;
+ Status loadHwModule(const std::string& name, int32_t* _aidl_return) override;
+ 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 releaseAudioPatch(int32_t handle) override;
+ Status listAudioPatches(int32_t maxCount,
+ std::vector<media::AudioPatch>* _aidl_return) override;
+ Status setAudioPortConfig(const media::AudioPortConfig& config) override;
+ Status getAudioHwSyncForSession(int32_t sessionId, int32_t* _aidl_return) override;
+ Status systemReady() override;
+ Status frameCountHAL(int32_t ioHandle, int64_t* _aidl_return) override;
+ Status getMicrophones(std::vector<media::MicrophoneInfoData>* _aidl_return) override;
+ Status setAudioHalPids(const std::vector<int32_t>& pids) override;
+
+private:
+ const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
+};
}; // namespace android
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 837375d..3018364 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -20,14 +20,15 @@
#include <stdint.h>
#include <sys/types.h>
#include <unistd.h>
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
+
+#include <android/media/IAudioPolicyServiceClient.h>
#include <binder/IInterface.h>
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioSystem.h>
#include <media/AudioPolicy.h>
-#include <media/IAudioPolicyServiceClient.h>
#include <system/audio_policy.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
#include <vector>
namespace android {
@@ -150,7 +151,7 @@
virtual status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags) = 0;
// Check if offload is possible for given format, stream type, sample rate,
// bit rate, duration, video and streaming or offload property is enabled
- virtual bool isOffloadSupported(const audio_offload_info_t& info) = 0;
+ virtual audio_offload_mode_t getOffloadSupport(const audio_offload_info_t& info) = 0;
// Check if direct playback is possible for given format, sample rate, channel mask and flags.
virtual bool isDirectOutputSupported(const audio_config_base_t& config,
@@ -160,11 +161,11 @@
virtual status_t listAudioPorts(audio_port_role_t role,
audio_port_type_t type,
unsigned int *num_ports,
- struct audio_port *ports,
+ struct audio_port_v7 *ports,
unsigned int *generation) = 0;
/* Get attributes for a given audio port */
- virtual status_t getAudioPort(struct audio_port *port) = 0;
+ virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
/* Create an audio patch between several source and sink ports */
virtual status_t createAudioPatch(const struct audio_patch *patch,
@@ -180,7 +181,7 @@
/* Set audio port configuration */
virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
- virtual void registerClient(const sp<IAudioPolicyServiceClient>& client) = 0;
+ virtual void registerClient(const sp<media::IAudioPolicyServiceClient>& client) = 0;
virtual void setAudioPortCallbacksEnabled(bool enabled) = 0;
diff --git a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
deleted file mode 100644
index 47b31ee..0000000
--- a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2009 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_IAUDIOPOLICYSERVICECLIENT_H
-#define ANDROID_IAUDIOPOLICYSERVICECLIENT_H
-
-#include <vector>
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <system/audio.h>
-#include <system/audio_effect.h>
-#include <media/AudioPolicy.h>
-#include <media/AudioVolumeGroup.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-struct record_client_info {
- audio_unique_id_t riid;
- uid_t uid;
- audio_session_t session;
- audio_source_t source;
- audio_port_handle_t port_id;
- bool silenced;
-};
-
-typedef struct record_client_info record_client_info_t;
-
-// ----------------------------------------------------------------------------
-
-class IAudioPolicyServiceClient : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(AudioPolicyServiceClient);
-
- // Notifies a change of volume group
- virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags) = 0;
- // Notifies a change of audio port configuration.
- virtual void onAudioPortListUpdate() = 0;
- // Notifies a change of audio patch configuration.
- virtual void onAudioPatchListUpdate() = 0;
- // Notifies a change in the mixing state of a specific mix in a dynamic audio policy
- virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;
- // Notifies a change of audio recording configuration
- virtual void onRecordingConfigurationUpdate(int event,
- const record_client_info_t *clientInfo,
- const audio_config_base_t *clientConfig,
- std::vector<effect_descriptor_t> clientEffects,
- const audio_config_base_t *deviceConfig,
- std::vector<effect_descriptor_t> effects,
- audio_patch_handle_t patchHandle,
- audio_source_t source) = 0;
-};
-
-
-// ----------------------------------------------------------------------------
-
-class BnAudioPolicyServiceClient : public BnInterface<IAudioPolicyServiceClient>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_IAUDIOPOLICYSERVICECLIENT_H
diff --git a/media/libaudioclient/include/media/PlayerBase.h b/media/libaudioclient/include/media/PlayerBase.h
index 4aad9b4..1a42b88 100644
--- a/media/libaudioclient/include/media/PlayerBase.h
+++ b/media/libaudioclient/include/media/PlayerBase.h
@@ -44,12 +44,14 @@
const media::VolumeShaperConfiguration& configuration,
const media::VolumeShaperOperation& operation) override;
- status_t startWithStatus();
+ status_t startWithStatus(audio_port_handle_t deviceId);
status_t pauseWithStatus();
status_t stopWithStatus();
//FIXME temporary method while some player state is outside of this class
- void reportEvent(player_state_t event);
+ void reportEvent(player_state_t event, audio_port_handle_t deviceId);
+
+ void baseUpdateDeviceId(audio_port_handle_t deviceId);
protected:
@@ -71,7 +73,7 @@
private:
// report events to AudioService
- void servicePlayerEvent(player_state_t event);
+ void servicePlayerEvent(player_state_t event, audio_port_handle_t deviceId);
void serviceReleasePlayer();
// native interface to AudioService
@@ -83,6 +85,9 @@
// Mutex for state reporting
Mutex mPlayerStateLock;
player_state_t mLastReportedEvent;
+
+ Mutex mDeviceIdLock;
+ audio_port_handle_t mLastReportedDeviceId;
};
} // namespace android
diff --git a/media/libaudioclient/include/media/ToneGenerator.h b/media/libaudioclient/include/media/ToneGenerator.h
index 04357a8..a575616 100644
--- a/media/libaudioclient/include/media/ToneGenerator.h
+++ b/media/libaudioclient/include/media/ToneGenerator.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_TONEGENERATOR_H_
#define ANDROID_TONEGENERATOR_H_
+#include <string>
+
#include <media/AudioSystem.h>
#include <media/AudioTrack.h>
#include <utils/Compat.h>
@@ -152,7 +154,8 @@
NUM_SUP_TONES = LAST_SUP_TONE-FIRST_SUP_TONE+1
};
- ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava = false);
+ ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava = false,
+ std::string opPackageName = {});
~ToneGenerator();
bool startTone(tone_type toneType, int durationMs = -1);
@@ -193,6 +196,7 @@
TONE_JAPAN_DIAL, // Dial tone: 400Hz, continuous
TONE_JAPAN_BUSY, // Busy tone: 400Hz, 500ms ON, 500ms OFF...
TONE_JAPAN_RADIO_ACK, // Radio path acknowlegment: 400Hz, 1s ON, 2s OFF...
+ TONE_JAPAN_RINGTONE, // Ring Tone: 400 Hz repeated in a 1 s on, 2 s off pattern.
// GB Supervisory tones
TONE_GB_BUSY, // Busy tone: 400 Hz, 375ms ON, 375ms OFF...
TONE_GB_CONGESTION, // Congestion Tone: 400 Hz, 400ms ON, 350ms OFF, 225ms ON, 525ms OFF...
@@ -343,6 +347,8 @@
};
KeyedVector<uint16_t, WaveGenerator *> mWaveGens; // list of active wave generators.
+
+ std::string mOpPackageName;
};
}
diff --git a/media/libaudioclient/include/media/TrackPlayerBase.h b/media/libaudioclient/include/media/TrackPlayerBase.h
index 6d26e63..b40d1eb 100644
--- a/media/libaudioclient/include/media/TrackPlayerBase.h
+++ b/media/libaudioclient/include/media/TrackPlayerBase.h
@@ -53,8 +53,20 @@
void doDestroy();
status_t doSetVolume();
+ class SelfAudioDeviceCallback : public AudioSystem::AudioDeviceCallback {
+ public:
+ SelfAudioDeviceCallback(PlayerBase& self);
+ virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId);
+ private:
+ virtual ~SelfAudioDeviceCallback();
+ PlayerBase& mSelf;
+ };
+
// volume coming from the player volume API
float mPlayerVolumeL, mPlayerVolumeR;
+
+ sp<SelfAudioDeviceCallback> mSelfAudioDeviceCallback;
};
} // namespace android
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index 350a780..21d18d3 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -7,6 +7,18 @@
}
cc_test {
+ name: "audio_aidl_status_tests",
+ defaults: ["libaudioclient_tests_defaults"],
+ srcs: ["audio_aidl_status_tests.cpp"],
+ shared_libs: [
+ "libaudioclient_aidl_conversion",
+ "libbinder",
+ "libcutils",
+ "libutils",
+ ],
+}
+
+cc_test {
name: "test_create_audiotrack",
defaults: ["libaudioclient_tests_defaults"],
srcs: ["test_create_audiotrack.cpp",
diff --git a/media/libaudioclient/tests/audio_aidl_status_tests.cpp b/media/libaudioclient/tests/audio_aidl_status_tests.cpp
new file mode 100644
index 0000000..5517091
--- /dev/null
+++ b/media/libaudioclient/tests/audio_aidl_status_tests.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+#include <media/AidlConversionUtil.h>
+#include <utils/Errors.h>
+
+using namespace android;
+using namespace android::aidl_utils;
+using android::binder::Status;
+
+// Tests for statusTFromBinderStatus() and binderStatusFromStatusT().
+
+// STATUS_T_SMALL_VALUE_LIMIT is an arbitrary limit where we exhaustively check status_t errors.
+// It is known that this limit doesn't cover UNKNOWN_ERROR ~ INT32_MIN.
+constexpr status_t STATUS_T_SMALL_VALUE_LIMIT = -1000;
+
+// Small status values are preserved on round trip
+TEST(audio_aidl_status_tests, statusRoundTripSmallValues) {
+ for (status_t status = 0; status > STATUS_T_SMALL_VALUE_LIMIT; --status) {
+ ASSERT_EQ(status, statusTFromBinderStatus(binderStatusFromStatusT(status)));
+ }
+}
+
+// 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}) {
+ ASSERT_EQ(status, statusTFromBinderStatus(binderStatusFromStatusT(status)));
+ }
+}
+
+// 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().
+ }) {
+ 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}) {
+ ASSERT_EQ(status, statusTFromBinderStatus(Status::fromStatusT(status)));
+ }
+}
+
+// Binder service specific errors show in status_t; these come fromServiceSpecificError().
+TEST(audio_aidl_status_tests, binderStatusServiceSpecificError) {
+ // fromServiceSpecificError() still stores exception code if status is 0.
+ for (status_t status = -1; status > STATUS_T_SMALL_VALUE_LIMIT; --status) {
+ ASSERT_EQ(status, statusTFromBinderStatus(Status::fromServiceSpecificError(status)));
+ }
+}
+
+// Binder status with message.
+TEST(audio_aidl_status_tests, binderStatusMessage) {
+ const String8 message("abcd");
+ for (status_t status = -1; status > STATUS_T_SMALL_VALUE_LIMIT; --status) {
+ const Status binderStatus = binderStatusFromStatusT(status, message.c_str());
+ ASSERT_EQ(status, statusTFromBinderStatus(binderStatus));
+ ASSERT_EQ(message, binderStatus.exceptionMessage());
+ }
+}
diff --git a/media/libaudiofoundation/AudioGain.cpp b/media/libaudiofoundation/AudioGain.cpp
index 56343d8..1dee938 100644
--- a/media/libaudiofoundation/AudioGain.cpp
+++ b/media/libaudiofoundation/AudioGain.cpp
@@ -140,7 +140,7 @@
parcelable->useInChannelMask = mUseInChannelMask;
parcelable->useForVolume = mUseForVolume;
parcelable->mode = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_gain_mode_t_mask_int32_t(mGain.mode));
+ legacy2aidl_audio_gain_mode_t_int32_t_mask(mGain.mode));
parcelable->channelMask = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_channel_mask_t_int32_t(mGain.channel_mask));
parcelable->minValue = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(mGain.min_value));
diff --git a/media/libaudiofoundation/AudioPort.cpp b/media/libaudiofoundation/AudioPort.cpp
index 6b63675..20d8632 100644
--- a/media/libaudiofoundation/AudioPort.cpp
+++ b/media/libaudiofoundation/AudioPort.cpp
@@ -291,7 +291,7 @@
parcelable->id = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(mId));
parcelable->gain.index = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(mGain.index));
parcelable->gain.mode = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_gain_mode_t_mask_int32_t(mGain.mode));
+ legacy2aidl_audio_gain_mode_t_int32_t_mask(mGain.mode));
parcelable->gain.channelMask = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_channel_mask_t_int32_t(mGain.channel_mask));
parcelable->gain.rampDurationMs = VALUE_OR_RETURN_STATUS(
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
index 3b47fed..65f7388 100644
--- a/media/libaudiofoundation/AudioProfile.cpp
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -355,4 +355,31 @@
return convertContainer<std::vector<media::AudioProfile>>(legacy, legacy2aidl_AudioProfile);
}
+AudioProfileVector intersectAudioProfiles(const AudioProfileVector& profiles1,
+ const AudioProfileVector& profiles2)
+{
+ std::map<audio_format_t, std::pair<ChannelMaskSet, SampleRateSet>> infos2;
+ for (const auto& profile : profiles2) {
+ infos2.emplace(profile->getFormat(),
+ std::make_pair(profile->getChannels(), profile->getSampleRates()));
+ }
+ AudioProfileVector profiles;
+ for (const auto& profile : profiles1) {
+ const auto it = infos2.find(profile->getFormat());
+ if (it == infos2.end()) {
+ continue;
+ }
+ ChannelMaskSet channelMasks = SetIntersection(profile->getChannels(), it->second.first);
+ if (channelMasks.empty()) {
+ continue;
+ }
+ SampleRateSet sampleRates = SetIntersection(profile->getSampleRates(), it->second.second);
+ if (sampleRates.empty()) {
+ continue;
+ }
+ profiles.push_back(new AudioProfile(profile->getFormat(), channelMasks, sampleRates));
+ }
+ return profiles;
+}
+
} // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index aa7ca69..204b365 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -50,6 +50,15 @@
return intersection;
}
+template<typename T>
+static std::set<T> SetIntersection(const std::set<T>& a, const std::set<T> b) {
+ std::set<T> intersection;
+ std::set_intersection(a.begin(), a.end(),
+ b.begin(), b.end(),
+ std::inserter(intersection, intersection.begin()));
+ return intersection;
+}
+
static inline ChannelMaskSet asInMask(const ChannelMaskSet& channelMasks) {
ChannelMaskSet inMaskSet;
for (const auto &channel : channelMasks) {
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
index 57592bc..5051233 100644
--- a/media/libaudiofoundation/include/media/AudioProfile.h
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -137,5 +137,7 @@
ConversionResult<std::vector<media::AudioProfile>>
legacy2aidl_AudioProfileVector(const AudioProfileVector& legacy);
+AudioProfileVector intersectAudioProfiles(const AudioProfileVector& profiles1,
+ const AudioProfileVector& profiles2);
} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index 77c2550..0108816 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -215,7 +215,7 @@
const struct audio_config *config, size_t *size) {
if (mDevice == 0) return NO_INIT;
AudioConfig hidlConfig;
- HidlUtils::audioConfigFromHal(*config, &hidlConfig);
+ HidlUtils::audioConfigFromHal(*config, true /*isInput*/, &hidlConfig);
Result retval;
Return<void> ret = mDevice->getInputBufferSize(
hidlConfig,
@@ -240,7 +240,7 @@
status_t status = deviceAddressFromHal(deviceType, address, &hidlDevice);
if (status != OK) return status;
AudioConfig hidlConfig;
- HidlUtils::audioConfigFromHal(*config, &hidlConfig);
+ HidlUtils::audioConfigFromHal(*config, false /*isInput*/, &hidlConfig);
Result retval = Result::NOT_INITIALIZED;
Return<void> ret = mDevice->openOutputStream(
handle,
@@ -275,7 +275,7 @@
status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
if (status != OK) return status;
AudioConfig hidlConfig;
- HidlUtils::audioConfigFromHal(*config, &hidlConfig);
+ HidlUtils::audioConfigFromHal(*config, true /*isInput*/, &hidlConfig);
Result retval = Result::NOT_INITIALIZED;
#if MAJOR_VERSION == 2
auto sinkMetadata = AudioSource(source);
diff --git a/media/libaudiohal/impl/DeviceHalLocal.h b/media/libaudiohal/impl/DeviceHalLocal.h
index 195204b..46b510b 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.h
+++ b/media/libaudiohal/impl/DeviceHalLocal.h
@@ -117,6 +117,8 @@
void closeOutputStream(struct audio_stream_out *stream_out);
void closeInputStream(struct audio_stream_in *stream_in);
+ uint32_t version() const { return mDev->common.version; }
+
private:
audio_hw_device_t *mDev;
@@ -127,8 +129,6 @@
// The destructor automatically closes the device.
virtual ~DeviceHalLocal();
-
- uint32_t version() const { return mDev->common.version; }
};
} // namespace CPP_VERSION
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 2726e36..09a7c1c 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -25,6 +25,7 @@
#include "DeviceHalHidl.h"
#include "EffectHalHidl.h"
+#include "HidlUtils.h"
#include "StreamHalHidl.h"
#include "VersionUtils.h"
@@ -610,12 +611,25 @@
const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
CPP_VERSION::SourceMetadata halMetadata = {
.tracks = transformToHidlVec(sourceMetadata.tracks,
- [](const playback_track_metadata& metadata) -> PlaybackTrackMetadata {
- return {
- .usage=static_cast<AudioUsage>(metadata.usage),
- .contentType=static_cast<AudioContentType>(metadata.content_type),
- .gain=metadata.gain,
+ [](const playback_track_metadata_v7& metadata) -> PlaybackTrackMetadata {
+ PlaybackTrackMetadata halTrackMetadata = {
+ .usage=static_cast<AudioUsage>(metadata.base.usage),
+ .contentType=static_cast<AudioContentType>(metadata.base.content_type),
+ .gain=metadata.base.gain,
};
+#if MAJOR_VERSION >= 7
+ HidlUtils::audioChannelMaskFromHal(metadata.channel_mask, false /*isInput*/,
+ &halTrackMetadata.channelMask);
+
+ std::istringstream tags{metadata.tags};
+ std::string tag;
+ while (std::getline(tags, tag, HidlUtils::sAudioTagSeparator)) {
+ if (!tag.empty()) {
+ halTrackMetadata.tags.push_back(tag);
+ }
+ }
+#endif
+ return halTrackMetadata;
})};
return processReturn("updateSourceMetadata", mStream->updateSourceMetadata(halMetadata));
}
@@ -902,11 +916,23 @@
StreamInHalInterface::SinkMetadata& sinkMetadata) {
CPP_VERSION::SinkMetadata halMetadata = {
.tracks = transformToHidlVec(sinkMetadata.tracks,
- [](const record_track_metadata& metadata) -> RecordTrackMetadata {
- return {
- .source=static_cast<AudioSource>(metadata.source),
- .gain=metadata.gain,
+ [](const record_track_metadata_v7& metadata) -> RecordTrackMetadata {
+ RecordTrackMetadata halTrackMetadata = {
+ .source=static_cast<AudioSource>(metadata.base.source),
+ .gain=metadata.base.gain,
};
+#if MAJOR_VERSION >= 7
+ HidlUtils::audioChannelMaskFromHal(metadata.channel_mask, true /*isInput*/,
+ &halTrackMetadata.channelMask);
+ std::istringstream tags{metadata.tags};
+ std::string tag;
+ while (std::getline(tags, tag, HidlUtils::sAudioTagSeparator)) {
+ if (!tag.empty()) {
+ halTrackMetadata.tags.push_back(tag);
+ }
+ }
+#endif
+ return halTrackMetadata;
})};
return processReturn("updateSinkMetadata", mStream->updateSinkMetadata(halMetadata));
}
diff --git a/media/libaudiohal/impl/StreamHalLocal.cpp b/media/libaudiohal/impl/StreamHalLocal.cpp
index 69be303..f544e06 100644
--- a/media/libaudiohal/impl/StreamHalLocal.cpp
+++ b/media/libaudiohal/impl/StreamHalLocal.cpp
@@ -241,19 +241,55 @@
return mStream->get_presentation_position(mStream, frames, timestamp);
}
-status_t StreamOutHalLocal::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
- if (mStream->update_source_metadata == nullptr) {
- return INVALID_OPERATION;
+void StreamOutHalLocal::doUpdateSourceMetadata(const SourceMetadata& sourceMetadata) {
+ std::vector<playback_track_metadata> halTracks;
+ halTracks.reserve(sourceMetadata.tracks.size());
+ for (auto& metadata : sourceMetadata.tracks) {
+ playback_track_metadata halTrackMetadata;
+ playback_track_metadata_from_v7(&halTrackMetadata, &metadata);
+ halTracks.push_back(halTrackMetadata);
}
+ const source_metadata_t halMetadata = {
+ .track_count = halTracks.size(),
+ .tracks = halTracks.data(),
+ };
+ mStream->update_source_metadata(mStream, &halMetadata);
+}
+
+#if MAJOR_VERSION >= 7
+void StreamOutHalLocal::doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata) {
const source_metadata_t metadata {
.track_count = sourceMetadata.tracks.size(),
// const cast is fine as it is in a const structure
- .tracks = const_cast<playback_track_metadata*>(sourceMetadata.tracks.data()),
+ .tracks = const_cast<playback_track_metadata_v7*>(sourceMetadata.tracks.data()),
};
- mStream->update_source_metadata(mStream, &metadata);
+ mStream->update_source_metadata_v7(mStream, &metadata);
+}
+#endif
+
+status_t StreamOutHalLocal::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
+#if MAJOR_VERSION < 7
+ if (mStream->update_source_metadata == nullptr) {
+ return INVALID_OPERATION;
+ }
+ doUpdateSourceMetadata(sourceMetadata);
+#else
+ if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2)
+ if (mStream->update_source_metadata == nullptr) {
+ return INVALID_OPERATION;
+ }
+ doUpdateSourceMetadata(sourceMetadata);
+ } else {
+ if (mStream->update_source_metadata_v7 == nullptr) {
+ return INVALID_OPERATION;
+ }
+ doUpdateSourceMetadataV7(sourceMetadata);
+ }
+#endif
return OK;
}
+
status_t StreamOutHalLocal::start() {
if (mStream->start == NULL) return INVALID_OPERATION;
return mStream->start(mStream);
@@ -352,16 +388,52 @@
return mStream->get_capture_position(mStream, frames, time);
}
-status_t StreamInHalLocal::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
- if (mStream->update_sink_metadata == nullptr) {
- return INVALID_OPERATION;
+void StreamInHalLocal::doUpdateSinkMetadata(const SinkMetadata& sinkMetadata) {
+ std::vector<record_track_metadata> halTracks;
+ halTracks.reserve(sinkMetadata.tracks.size());
+ for (auto& metadata : sinkMetadata.tracks) {
+ record_track_metadata halTrackMetadata;
+ record_track_metadata_from_v7(&halTrackMetadata, &metadata);
+ halTracks.push_back(halTrackMetadata);
}
- const sink_metadata_t metadata {
+ const sink_metadata_t halMetadata = {
+ .track_count = halTracks.size(),
+ .tracks = halTracks.data(),
+ };
+ mStream->update_sink_metadata(mStream, &halMetadata);
+}
+
+#if MAJOR_VERSION >= 7
+void StreamInHalLocal::doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata) {
+ const sink_metadata_v7_t halMetadata {
.track_count = sinkMetadata.tracks.size(),
// const cast is fine as it is in a const structure
- .tracks = const_cast<record_track_metadata*>(sinkMetadata.tracks.data()),
+ .tracks = const_cast<record_track_metadata_v7*>(sinkMetadata.tracks.data()),
};
- mStream->update_sink_metadata(mStream, &metadata);
+ mStream->update_sink_metadata_v7(mStream, &halMetadata);
+}
+#endif
+
+status_t StreamInHalLocal::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
+#if MAJOR_VERSION < 7
+
+ if (mStream->update_sink_metadata == nullptr) {
+ return INVALID_OPERATION; // not supported by the HAL
+ }
+ doUpdateSinkMetadata(sinkMetadata);
+#else
+ if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2)
+ if (mStream->update_sink_metadata == nullptr) {
+ return INVALID_OPERATION; // not supported by the HAL
+ }
+ doUpdateSinkMetadata(sinkMetadata);
+ } else {
+ if (mStream->update_sink_metadata_v7 == nullptr) {
+ return INVALID_OPERATION; // not supported by the HAL
+ }
+ doUpdateSinkMetadataV7(sinkMetadata);
+ }
+#endif
return OK;
}
diff --git a/media/libaudiohal/impl/StreamHalLocal.h b/media/libaudiohal/impl/StreamHalLocal.h
index d17f9f3..8e5180f 100644
--- a/media/libaudiohal/impl/StreamHalLocal.h
+++ b/media/libaudiohal/impl/StreamHalLocal.h
@@ -173,6 +173,9 @@
static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
static int asyncEventCallback(stream_event_callback_type_t event, void *param, void *cookie);
+
+ void doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata);
+ void doUpdateSourceMetadata(const SourceMetadata& sourceMetadata);
};
class StreamInHalLocal : public StreamInHalInterface, public StreamHalLocal {
@@ -227,6 +230,9 @@
StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device);
virtual ~StreamInHalLocal();
+
+ void doUpdateSinkMetadata(const SinkMetadata& sinkMetadata);
+ void doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata);
};
} // namespace CPP_VERSION
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index e30cb72..523705e 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -158,7 +158,7 @@
virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) = 0;
struct SourceMetadata {
- std::vector<playback_track_metadata_t> tracks;
+ std::vector<playback_track_metadata_v7_t> tracks;
};
/**
* Called when the metadata of the stream's source has been changed.
@@ -197,7 +197,7 @@
virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
struct SinkMetadata {
- std::vector<record_track_metadata_t> tracks;
+ std::vector<record_track_metadata_v7_t> tracks;
};
/**
* Called when the metadata of the stream's sink has been changed.
diff --git a/media/libeffects/downmix/tests/build_and_run_all_unit_tests.sh b/media/libeffects/downmix/tests/build_and_run_all_unit_tests.sh
index d0faebe..8aadfbf 100755
--- a/media/libeffects/downmix/tests/build_and_run_all_unit_tests.sh
+++ b/media/libeffects/downmix/tests/build_and_run_all_unit_tests.sh
@@ -39,8 +39,7 @@
echo "testing Downmix"
adb shell mkdir $testdir
-adb push $ANDROID_BUILD_TOP/cts/tests/tests/media/res/raw/sinesweepraw.raw \
-$testdir
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/libeffects/res/raw/sinesweepraw.raw $testdir
adb push $OUT/testcases/downmixtest/arm64/downmixtest $testdir
#run the downmix test application for test.
diff --git a/media/libeffects/lvm/benchmarks/Android.bp b/media/libeffects/lvm/benchmarks/Android.bp
index 420e172..930292f 100644
--- a/media/libeffects/lvm/benchmarks/Android.bp
+++ b/media/libeffects/lvm/benchmarks/Android.bp
@@ -14,3 +14,24 @@
"libhardware_headers",
],
}
+
+cc_benchmark {
+ name: "reverb_benchmark",
+ vendor: true,
+ include_dirs: [
+ "frameworks/av/media/libeffects/lvm/wrapper/Reverb",
+ ],
+ srcs: ["reverb_benchmark.cpp"],
+ static_libs: [
+ "libreverb",
+ "libreverbwrapper",
+ ],
+ shared_libs: [
+ "libaudioutils",
+ "liblog",
+ ],
+ header_libs: [
+ "libaudioeffects",
+ "libhardware_headers",
+ ],
+}
diff --git a/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp b/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp
new file mode 100644
index 0000000..00a7ff2
--- /dev/null
+++ b/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+#include <array>
+#include <climits>
+#include <cstdlib>
+#include <random>
+#include <vector>
+#include <log/log.h>
+#include <benchmark/benchmark.h>
+#include <hardware/audio_effect.h>
+#include <system/audio.h>
+#include "EffectReverb.h"
+
+extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
+constexpr effect_uuid_t kEffectUuids[] = {
+ {0x172cdf00,
+ 0xa3bc,
+ 0x11df,
+ 0xa72f,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // preset-insert mode
+ {0xf29a1400,
+ 0xa3bb,
+ 0x11df,
+ 0x8ddc,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // preset-aux mode
+};
+
+constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
+
+constexpr size_t kFrameCount = 2048;
+
+constexpr int kPresets[] = {
+ REVERB_PRESET_NONE, REVERB_PRESET_SMALLROOM, REVERB_PRESET_MEDIUMROOM,
+ REVERB_PRESET_LARGEROOM, REVERB_PRESET_MEDIUMHALL, REVERB_PRESET_LARGEHALL,
+ REVERB_PRESET_PLATE,
+};
+
+constexpr size_t kNumPresets = std::size(kPresets);
+
+constexpr int kSampleRate = 44100;
+
+int reverbSetConfigParam(uint32_t paramType, uint32_t paramValue, effect_handle_t effectHandle) {
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ uint32_t paramData[2] = {paramType, paramValue};
+ auto effectParam = (effect_param_t*)malloc(sizeof(effect_param_t) + sizeof(paramData));
+ memcpy(&effectParam->data[0], ¶mData[0], sizeof(paramData));
+ effectParam->psize = sizeof(paramData[0]);
+ effectParam->vsize = sizeof(paramData[1]);
+ int status = (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_SET_PARAM,
+ sizeof(effect_param_t) + sizeof(paramData), effectParam,
+ &replySize, &reply);
+ free(effectParam);
+ if (status != 0) {
+ ALOGE("Reverb set config returned an error = %d\n", status);
+ return status;
+ }
+ return reply;
+}
+
+/*******************************************************************
+ * A test result running on Pixel 3 with for comparison.
+ * The first parameter indicates the preset level id.
+ * The second parameter indicates the effect.
+ * 0: preset-insert mode, 1: preset-aux mode
+ * --------------------------------------------------------
+ * Benchmark Time CPU Iterations
+ * --------------------------------------------------------
+ * BM_REVERB/0/0 19312 ns 19249 ns 36282
+ * BM_REVERB/0/1 5613 ns 5596 ns 125032
+ * BM_REVERB/1/0 605453 ns 603714 ns 1131
+ * BM_REVERB/1/1 589421 ns 587758 ns 1161
+ * BM_REVERB/2/0 605760 ns 604006 ns 1131
+ * BM_REVERB/2/1 589434 ns 587777 ns 1161
+ * BM_REVERB/3/0 605574 ns 603828 ns 1131
+ * BM_REVERB/3/1 589566 ns 587862 ns 1162
+ * BM_REVERB/4/0 605634 ns 603894 ns 1131
+ * BM_REVERB/4/1 589506 ns 587856 ns 1161
+ * BM_REVERB/5/0 605644 ns 603929 ns 1131
+ * BM_REVERB/5/1 589592 ns 587863 ns 1161
+ * BM_REVERB/6/0 610544 ns 608561 ns 1131
+ * BM_REVERB/6/1 589686 ns 587871 ns 1161
+ *******************************************************************/
+
+static void BM_REVERB(benchmark::State& state) {
+ const size_t chMask = AUDIO_CHANNEL_OUT_STEREO;
+ const size_t preset = kPresets[state.range(0)];
+ const effect_uuid_t uuid = kEffectUuids[state.range(1)];
+ const size_t channelCount = audio_channel_count_from_out_mask(chMask);
+
+ // Initialize input buffer with deterministic pseudo-random values
+ std::minstd_rand gen(chMask);
+ std::uniform_real_distribution<> dis(-1.0f, 1.0f);
+ std::vector<float> input(kFrameCount * channelCount);
+ std::vector<float> output(kFrameCount * channelCount);
+ for (auto& in : input) {
+ in = dis(gen);
+ }
+
+ effect_handle_t effectHandle = nullptr;
+ if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&uuid, 1, 1, &effectHandle);
+ status != 0) {
+ ALOGE("create_effect returned an error = %d\n", status);
+ return;
+ }
+
+ effect_config_t config{};
+ config.inputCfg.samplingRate = config.outputCfg.samplingRate = kSampleRate;
+ config.inputCfg.channels = config.outputCfg.channels = chMask;
+ 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, 0, nullptr, &replySize, &reply);
+ status != 0) {
+ ALOGE("Command enable call returned error %d\n", reply);
+ return;
+ }
+
+ if (int status = reverbSetConfigParam(REVERB_PARAM_PRESET, preset, effectHandle); status != 0) {
+ ALOGE("Invalid reverb preset. Error %d\n", status);
+ return;
+ }
+
+ // Run the test
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(input.data());
+ benchmark::DoNotOptimize(output.data());
+
+ audio_buffer_t inBuffer = {.frameCount = kFrameCount, .f32 = input.data()};
+ audio_buffer_t outBuffer = {.frameCount = kFrameCount, .f32 = output.data()};
+ (*effectHandle)->process(effectHandle, &inBuffer, &outBuffer);
+
+ benchmark::ClobberMemory();
+ }
+
+ state.SetComplexityN(state.range(0));
+
+ 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 REVERBArgs(benchmark::internal::Benchmark* b) {
+ for (int i = 0; i < kNumPresets; i++) {
+ for (int j = 0; j < kNumEffectUuids; ++j) {
+ b->Args({i, j});
+ }
+ }
+}
+
+BENCHMARK(BM_REVERB)->Apply(REVERBArgs);
+
+BENCHMARK_MAIN();
diff --git a/media/libeffects/lvm/lib/Android.bp b/media/libeffects/lvm/lib/Android.bp
index 8f2f016..8d248a3 100644
--- a/media/libeffects/lvm/lib/Android.bp
+++ b/media/libeffects/lvm/lib/Android.bp
@@ -69,28 +69,19 @@
"Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp",
"Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp",
"Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.cpp",
- "Common/src/Int16LShiftToInt32_16x32.cpp",
- "Common/src/From2iToMono_16.cpp",
"Common/src/Copy_16.cpp",
- "Common/src/MonoTo2I_16.cpp",
"Common/src/MonoTo2I_32.cpp",
- "Common/src/LoadConst_16.cpp",
"Common/src/LoadConst_32.cpp",
"Common/src/dB_to_Lin32.cpp",
"Common/src/Shift_Sat_v16xv16.cpp",
"Common/src/Shift_Sat_v32xv32.cpp",
- "Common/src/Abs_32.cpp",
- "Common/src/Int32RShiftToInt16_Sat_32x16.cpp",
"Common/src/From2iToMono_32.cpp",
- "Common/src/mult3s_16x16.cpp",
"Common/src/Mult3s_32x16.cpp",
"Common/src/NonLinComp_D16.cpp",
"Common/src/DelayMix_16x16.cpp",
"Common/src/MSTo2i_Sat_16x16.cpp",
"Common/src/From2iToMS_16x16.cpp",
- "Common/src/Mac3s_Sat_16x16.cpp",
"Common/src/Mac3s_Sat_32x16.cpp",
- "Common/src/Add2_Sat_16x16.cpp",
"Common/src/Add2_Sat_32x32.cpp",
"Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp",
"Common/src/LVC_MixSoft_1St_D16C31_SAT.cpp",
@@ -131,12 +122,15 @@
shared_libs: [
"liblog",
],
+ static_libs: [
+ "libaudioutils",
+ ],
header_libs: [
"libhardware_headers",
],
cppflags: [
+ "-DBIQUAD_OPT",
"-fvisibility=hidden",
-
"-Wall",
"-Werror",
],
@@ -163,18 +157,14 @@
"Reverb/src/LVREV_Process.cpp",
"Reverb/src/LVREV_SetControlParameters.cpp",
"Reverb/src/LVREV_Tables.cpp",
- "Common/src/Abs_32.cpp",
"Common/src/InstAlloc.cpp",
- "Common/src/LoadConst_16.cpp",
"Common/src/LoadConst_32.cpp",
"Common/src/From2iToMono_32.cpp",
"Common/src/Mult3s_32x16.cpp",
"Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp",
"Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp",
- "Common/src/DelayAllPass_Sat_32x16To32.cpp",
"Common/src/Copy_16.cpp",
"Common/src/Mac3s_Sat_32x16.cpp",
- "Common/src/DelayWrite_32.cpp",
"Common/src/Shift_Sat_v32xv32.cpp",
"Common/src/Add2_Sat_32x32.cpp",
"Common/src/JoinTo2i_32x32.cpp",
@@ -201,10 +191,12 @@
"Reverb/lib",
"Common/lib",
],
-
+ static_libs: [
+ "libaudioutils",
+ ],
cppflags: [
+ "-DBIQUAD_OPT",
"-fvisibility=hidden",
-
"-Wall",
"-Werror",
],
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
index 5b47aa6..814280f 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
@@ -21,6 +21,10 @@
/* */
/****************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#include <system/audio.h>
+#endif
#include "LVDBE.h"
#include "LVDBE_Private.h"
#include "VectorArithmetic.h"
@@ -107,22 +111,37 @@
/*
* Setup the high pass filter
*/
+#ifdef BIQUAD_OPT
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ LVDBE_HPF_Table[Offset].A0, LVDBE_HPF_Table[Offset].A1, LVDBE_HPF_Table[Offset].A2,
+ -(LVDBE_HPF_Table[Offset].B1), -(LVDBE_HPF_Table[Offset].B2)};
+ pInstance->pHPFBiquad
+ ->setCoefficients<std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(coefs);
+#else
LoadConst_Float(0, /* Clear the history, value 0 */
(LVM_FLOAT*)&pInstance->pData->HPFTaps, /* Destination */
sizeof(pInstance->pData->HPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance, /* Initialise the filter */
&pInstance->pData->HPFTaps,
(BQ_FLOAT_Coefs_t*)&LVDBE_HPF_Table[Offset]);
+#endif
/*
* Setup the band pass filter
*/
+#ifdef BIQUAD_OPT
+ coefs = {LVDBE_BPF_Table[Offset].A0, 0.0, -(LVDBE_BPF_Table[Offset].A0),
+ -(LVDBE_BPF_Table[Offset].B1), -(LVDBE_BPF_Table[Offset].B2)};
+ pInstance->pBPFBiquad
+ ->setCoefficients<std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(coefs);
+#else
LoadConst_Float(0, /* Clear the history, value 0 */
(LVM_FLOAT*)&pInstance->pData->BPFTaps, /* Destination */
sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance, /* Initialise the filter */
&pInstance->pData->BPFTaps,
(BP_FLOAT_Coefs_t*)&LVDBE_BPF_Table[Offset]);
+#endif
}
/************************************************************************************/
@@ -275,6 +294,14 @@
LVDBE_Instance_t* pInstance = (LVDBE_Instance_t*)hInstance;
LVMixer3_2St_FLOAT_st* pBypassMixer_Instance = &pInstance->pData->BypassMixer;
+#ifdef BIQUAD_OPT
+ /*
+ * Create biquad instance
+ */
+ pInstance->pHPFBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(
+ (FCC_1 == pParams->NrChannels) ? FCC_2 : pParams->NrChannels));
+#endif
+
/*
* Update the filters
*/
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
index 12af162..6bdb7fe 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
@@ -20,8 +20,11 @@
/* Includes */
/* */
/****************************************************************************************/
-#include <stdlib.h>
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
+#include <stdlib.h>
#include "LVDBE.h"
#include "LVDBE_Private.h"
@@ -89,10 +92,19 @@
if (pInstance->pData == NULL) {
return LVDBE_NULLADDRESS;
}
+#ifdef BIQUAD_OPT
+ /*
+ * Create biquad instance
+ */
+ pInstance->pHPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+ pInstance->pBPFBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1));
+#else
pInstance->pCoef = (LVDBE_Coef_FLOAT_t*)calloc(1, sizeof(*(pInstance->pCoef)));
if (pInstance->pCoef == NULL) {
return LVDBE_NULLADDRESS;
}
+#endif
/*
* Initialise the filters
@@ -182,10 +194,12 @@
free(pInstance->pData);
pInstance->pData = LVM_NULL;
}
+#ifndef BIQUAD_OPT
if (pInstance->pCoef != LVM_NULL) {
free(pInstance->pCoef);
pInstance->pCoef = LVM_NULL;
}
+#endif
free(pInstance);
*phInstance = LVM_NULL;
}
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
index 4fef1ef..23be2aa 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
@@ -33,6 +33,9 @@
/* */
/****************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
#include "LVDBE.h" /* Calling or Application layer definitions */
#include "BIQUAD.h"
#include "LVC_Mixer.h"
@@ -63,19 +66,24 @@
AGC_MIX_VOL_2St1Mon_FLOAT_t AGCInstance; /* AGC instance parameters */
/* Process variables */
+#ifndef BIQUAD_OPT
Biquad_2I_Order2_FLOAT_Taps_t HPFTaps; /* High pass filter taps */
Biquad_1I_Order2_FLOAT_Taps_t BPFTaps; /* Band pass filter taps */
+#endif
LVMixer3_1St_FLOAT_st BypassVolume; /* Bypass volume scaler */
LVMixer3_2St_FLOAT_st BypassMixer; /* Bypass Mixer for Click Removal */
} LVDBE_Data_FLOAT_t;
+#ifndef BIQUAD_OPT
/* Coefs structure */
typedef struct {
/* Process variables */
Biquad_FLOAT_Instance_t HPFInstance; /* High pass filter instance */
Biquad_FLOAT_Instance_t BPFInstance; /* Band pass filter instance */
} LVDBE_Coef_FLOAT_t;
+#endif
+
/* Instance structure */
typedef struct {
/* Public parameters */
@@ -84,8 +92,16 @@
/* Data and coefficient pointers */
LVDBE_Data_FLOAT_t* pData; /* Instance data */
+#ifndef BIQUAD_OPT
LVDBE_Coef_FLOAT_t* pCoef; /* Instance coefficients */
+#endif
void* pScratch; /* scratch pointer */
+#ifdef BIQUAD_OPT
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pHPFBiquad; /* Biquad filter instance for HPF */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pBPFBiquad; /* Biquad filter instance for BPF */
+#endif
} LVDBE_Instance_t;
/****************************************************************************************/
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
index f4a4d6f..e8541fd 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
@@ -20,6 +20,9 @@
/* Includes */
/* */
/****************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
#include <string.h> // memset
#include "LVDBE.h"
@@ -125,10 +128,14 @@
* Apply the high pass filter if selected
*/
if (pInstance->Params.HPFSelect == LVDBE_HPF_ON) {
+#ifdef BIQUAD_OPT
+ pInstance->pHPFBiquad->process(pScratch, pScratch, NrFrames);
+#else
BQ_MC_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance, /* Filter instance */
pScratch, /* Source */
pScratch, /* Destination */
(LVM_INT16)NrFrames, (LVM_INT16)NrChannels);
+#endif
}
/*
@@ -142,10 +149,14 @@
/*
* Apply the band pass filter
*/
+#ifdef BIQUAD_OPT
+ pInstance->pBPFBiquad->process(pMono, pMono, NrFrames);
+#else
BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance */
pMono, /* Source */
pMono, /* Destination */
(LVM_INT16)NrFrames);
+#endif
/*
* Apply the AGC and mix
@@ -156,15 +167,6 @@
pScratch, /* Destination */
NrFrames, /* Number of frames */
NrChannels); /* Number of channels */
-
- for (LVM_INT32 ii = 0; ii < NrSamples; ++ii) {
- // TODO: replace with existing clamping function
- if (pScratch[ii] < -1.0) {
- pScratch[ii] = -1.0;
- } else if (pScratch[ii] > 1.0) {
- pScratch[ii] = 1.0;
- }
- }
} else {
// clear DBE processed path
memset(pScratch, 0, sizeof(*pScratch) * NrSamples);
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
index 3118e77..7e8664a 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
@@ -276,6 +276,16 @@
*/
Offset = (LVM_INT16)(EffectLevel - 1 +
TrebleBoostSteps * (pParams->SampleRate - TrebleBoostMinRate));
+#ifdef BIQUAD_OPT
+ /*
+ * Create biquad instance
+ */
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ LVM_TrebleBoostCoefs[Offset].A0, LVM_TrebleBoostCoefs[Offset].A1, 0.0,
+ -(LVM_TrebleBoostCoefs[Offset].B1), 0.0};
+ pInstance->pTEBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(pParams->NrChannels, coefs));
+#else
FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
&pInstance->pTE_Taps->TrebleBoost_Taps,
&LVM_TrebleBoostCoefs[Offset]);
@@ -288,6 +298,7 @@
Cast to void: no dereferencing in function */
(LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps) /
sizeof(LVM_FLOAT))); /* Number of words */
+#endif
}
} else {
/*
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
index bb962df..bbfa0dc 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
@@ -174,6 +174,7 @@
/*
* Treble Enhancement
*/
+#ifndef BIQUAD_OPT
pInstance->pTE_Taps = (LVM_TE_Data_t*)calloc(1, sizeof(*(pInstance->pTE_Taps)));
if (pInstance->pTE_Taps == LVM_NULL) {
return LVM_NULLADDRESS;
@@ -182,6 +183,7 @@
if (pInstance->pTE_State == LVM_NULL) {
return LVM_NULLADDRESS;
}
+#endif
pInstance->Params.TE_OperatingMode = LVM_TE_OFF;
pInstance->Params.TE_EffectLevel = 0;
pInstance->TE_Active = LVM_FALSE;
@@ -494,6 +496,7 @@
/*
* Treble Enhancement
*/
+#ifndef BIQUAD_OPT
if (pInstance->pTE_Taps != LVM_NULL) {
free(pInstance->pTE_Taps);
pInstance->pTE_Taps = LVM_NULL;
@@ -502,6 +505,7 @@
free(pInstance->pTE_State);
pInstance->pTE_State = LVM_NULL;
}
+#endif
/*
* Free the default EQNB pre-gain and pointer to the band definitions
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
index 90a1f19..56bbfd1 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
@@ -33,6 +33,9 @@
/* */
/************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
#include "LVM.h" /* LifeVibes */
#include "LVM_Common.h" /* LifeVibes common */
#include "BIQUAD.h" /* Biquad library */
@@ -127,6 +130,7 @@
LVM_INT16 SamplesToOutput; /* Samples to write to the output */
} LVM_Buffer_t;
+#ifndef BIQUAD_OPT
/* Filter taps */
typedef struct {
Biquad_2I_Order1_FLOAT_Taps_t TrebleBoost_Taps; /* Treble boost Taps */
@@ -136,6 +140,7 @@
typedef struct {
Biquad_FLOAT_Instance_t TrebleBoost_State; /* State for the treble boost filter */
} LVM_TE_Coefs_t;
+#endif
typedef struct {
/* Public parameters */
@@ -185,8 +190,13 @@
LVM_INT16 VC_AVLFixedVolume; /* AVL fixed volume */
/* Treble Enhancement */
+#ifdef BIQUAD_OPT
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pTEBiquad; /* Biquad filter instance */
+#else
LVM_TE_Data_t* pTE_Taps; /* Treble boost Taps */
LVM_TE_Coefs_t* pTE_State; /* State for the treble boost filter */
+#endif
LVM_INT16 TE_Active; /* Control flag */
/* Headroom */
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
index c94c469..acd594f 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
@@ -190,9 +190,13 @@
/*
* Apply the filter
*/
+#ifdef BIQUAD_OPT
+ pInstance->pTEBiquad->process(pProcessed, pProcessed, NrFrames);
+#else
FO_Mc_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
pProcessed, pProcessed, (LVM_INT16)NrFrames,
(LVM_INT16)NrChannels);
+#endif
}
/*
* Volume balance
diff --git a/media/libeffects/lvm/lib/Common/lib/AGC.h b/media/libeffects/lvm/lib/Common/lib/AGC.h
index c20b49a..31c8200 100644
--- a/media/libeffects/lvm/lib/Common/lib/AGC.h
+++ b/media/libeffects/lvm/lib/Common/lib/AGC.h
@@ -48,11 +48,6 @@
/* Function Prototypes */
/* */
/**********************************************************************************/
-void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t* pInstance, /* Instance pointer */
- const LVM_FLOAT* pStSrc, /* Stereo source */
- const LVM_FLOAT* pMonoSrc, /* Mono source */
- LVM_FLOAT* pDst, /* Stereo destination */
- LVM_UINT16 n); /* Number of samples */
void AGC_MIX_VOL_Mc1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t* pInstance, /* Instance pointer */
const LVM_FLOAT* pStSrc, /* Source */
const LVM_FLOAT* pMonoSrc, /* Mono source */
diff --git a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
index b38e9fb..08772e1 100644
--- a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
+++ b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
@@ -72,6 +72,7 @@
LVM_FLOAT G; /* Gain */
} PK_FLOAT_Coefs_t;
+#ifndef BIQUAD_OPT
/**********************************************************************************
TAPS TYPE DEFINITIONS
***********************************************************************************/
@@ -100,6 +101,7 @@
#define BQ_2I_D32F32Cll_TRC_WRA_01_Init Init_BQ_2I_D32F32Cll_TRC_WRA_01
#define BP_1I_D32F32C30_TRC_WRA_02 TWO_BP_1I_D32F32C30_TRC_WRA_02
+
/**********************************************************************************
FUNCTION PROTOTYPES: BIQUAD FILTERS
***********************************************************************************/
@@ -161,8 +163,6 @@
Biquad_2I_Order1_FLOAT_Taps_t* pTaps,
FO_FLOAT_LShx_Coefs_t* pCoef);
-void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
/*** 32 bit data path *************************************************************/
void FO_1I_D32F32Cll_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
Biquad_1I_Order1_FLOAT_Taps_t* pTaps, FO_FLOAT_Coefs_t* pCoef);
@@ -170,6 +170,7 @@
LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
void FO_Mc_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
LVM_FLOAT* pDataOut, LVM_INT16 NrFrames, LVM_INT16 NrChannels);
+
/**********************************************************************************
FUNCTION PROTOTYPES: BAND PASS FILTERS
***********************************************************************************/
@@ -183,6 +184,7 @@
Biquad_1I_Order2_FLOAT_Taps_t* pTaps, BP_FLOAT_Coefs_t* pCoef);
void BP_1I_D16F32C30_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
+
/*** 32 bit data path *************************************************************/
void BP_1I_D32F32Cll_TRC_WRA_02_Init(Biquad_FLOAT_Instance_t* pInstance,
Biquad_1I_Order2_FLOAT_Taps_t* pTaps, BP_FLOAT_Coefs_t* pCoef);
@@ -193,10 +195,9 @@
void PK_2I_D32F32CssGss_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
Biquad_2I_Order2_FLOAT_Taps_t* pTaps,
PK_FLOAT_Coefs_t* pCoef);
-void PK_2I_D32F32C14G11_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
void PK_Mc_D32F32C14G11_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
LVM_FLOAT* pDataOut, LVM_INT16 NrFrames, LVM_INT16 NrChannels);
+#endif
/**********************************************************************************
FUNCTION PROTOTYPES: DC REMOVAL FILTERS
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
index fb797be..b95d076 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
@@ -26,7 +26,7 @@
#define LVM_TYPES_H
#include <stdint.h>
-
+#include <system/audio.h>
/****************************************************************************************/
/* */
/* definitions */
@@ -82,7 +82,7 @@
#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_FLOAT
typedef float effect_buffer_t;
-#define LVM_MAX_CHANNELS 8 // FCC_8
+#define LVM_MAX_CHANNELS FCC_24
/****************************************************************************************/
/* */
diff --git a/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
index 04b180c..36c4cd2 100644
--- a/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
+++ b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
@@ -21,7 +21,7 @@
/*######################################################################################*/
/* Include files */
/*######################################################################################*/
-
+#include <math.h>
#include "LVM_Types.h"
/*######################################################################################*/
@@ -30,7 +30,13 @@
/* Absolute value including the corner case for the extreme negative value */
-LVM_FLOAT Abs_Float(LVM_FLOAT input);
+static inline LVM_FLOAT Abs_Float(LVM_FLOAT input) {
+ return fabs(input);
+}
+
+static inline LVM_FLOAT LVM_Clamp(LVM_FLOAT val) {
+ return fmin(fmax(val, -1.0f), 1.0f);
+}
/****************************************************************************************
* Name : dB_to_Lin32()
diff --git a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
index 66e3e79..281d941 100644
--- a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
+++ b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
@@ -32,45 +32,16 @@
void Copy_Float_Stereo_Mc(const LVM_FLOAT* src, LVM_FLOAT* StereoOut, LVM_FLOAT* dst,
LVM_INT16 NrFrames, LVM_INT32 NrChannels);
-/*********************************************************************************
- * note: In Mult3s_16x16() saturation of result is not taken care when *
- * overflow occurs. *
- * For example when *src = 0x8000, val = *0x8000 *
- * The function gives the output as 0x8000 instead of 0x7fff *
- * This is the only case which will give wrong result. *
- * For more information refer to Vector_Arithmetic.doc in /doc folder *
- *********************************************************************************/
void Mult3s_Float(const LVM_FLOAT* src, const LVM_FLOAT val, LVM_FLOAT* dst, LVM_INT16 n);
-/*********************************************************************************
- * note: In Mult3s_32x16() saturation of result is not taken care when *
- * overflow occurs. *
- * For example when *src = 0x8000000, val = *0x8000 *
- * The function gives the output as 0x8000000 instead of 0x7fffffff *
- * This is the only extreme condition which is giving unexpected result *
- * For more information refer to Vector_Arithmetic.doc in /doc folder *
- *********************************************************************************/
-void Mult3s_32x16(const LVM_INT32* src, const LVM_INT16 val, LVM_INT32* dst, LVM_INT16 n);
void DelayMix_Float(const LVM_FLOAT* src, /* Source 1, to be delayed */
LVM_FLOAT* delay, /* Delay buffer */
LVM_INT16 size, /* Delay size */
LVM_FLOAT* dst, /* Source/destination */
LVM_INT16* pOffset, /* Delay offset */
LVM_INT16 n); /* Number of stereo samples */
-void DelayWrite_32(const LVM_INT32* src, /* Source 1, to be delayed */
- LVM_INT32* delay, /* Delay buffer */
- LVM_UINT16 size, /* Delay size */
- LVM_UINT16* pOffset, /* Delay offset */
- LVM_INT16 n);
void Add2_Sat_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n);
void Mac3s_Sat_Float(const LVM_FLOAT* src, const LVM_FLOAT val, LVM_FLOAT* dst, LVM_INT16 n);
-void DelayAllPass_Sat_32x16To32(LVM_INT32* delay, /* Delay buffer */
- LVM_UINT16 size, /* Delay size */
- LVM_INT16 coeff, /* All pass filter coefficient */
- LVM_UINT16 DelayOffset, /* Simple delay offset */
- LVM_UINT16* pAllPassOffset, /* All pass filter delay offset */
- LVM_INT32* dst, /* Source/destination */
- LVM_INT16 n);
/**********************************************************************************
SHIFT FUNCTIONS
@@ -87,15 +58,6 @@
void From2iToMS_Float(const LVM_FLOAT* src, LVM_FLOAT* dstM, LVM_FLOAT* dstS, LVM_INT16 n);
void JoinTo2i_Float(const LVM_FLOAT* srcL, const LVM_FLOAT* srcR, LVM_FLOAT* dst, LVM_INT16 n);
-/**********************************************************************************
- DATA TYPE CONVERSION FUNCTIONS
-***********************************************************************************/
-
-void Int16LShiftToInt32_16x32(const LVM_INT16* src, LVM_INT32* dst, LVM_INT16 n, LVM_INT16 shift);
-
-void Int32RShiftToInt16_Sat_32x16(const LVM_INT32* src, LVM_INT16* dst, LVM_INT16 n,
- LVM_INT16 shift);
-
/**********************************************************************************/
#endif /* _VECTOR_ARITHMETIC_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp
index ae8cdad..78f329e 100644
--- a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp
+++ b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp
@@ -20,7 +20,6 @@
/* Includes */
/* */
/****************************************************************************************/
-
#include "AGC.h"
#include "ScalarArithmetic.h"
@@ -37,135 +36,6 @@
/****************************************************************************************/
/* */
-/* FUNCTION: AGC_MIX_VOL_2St1Mon_D32_WRA */
-/* */
-/* DESCRIPTION: */
-/* Apply AGC and mix signals */
-/* */
-/* */
-/* StSrc ------------------| */
-/* | */
-/* ______ _|_ ________ */
-/* | | | | | | */
-/* MonoSrc -->| AGC |---->| + |----->| Volume |------------------------------+---> */
-/* | Gain | |___| | Gain | | */
-/* |______| |________| | */
-/* /|\ __________ ________ | */
-/* | | | | | | */
-/* |-------------------------------| AGC Gain |<--| Peak |<--| */
-/* | Update | | Detect | */
-/* |__________| |________| */
-/* */
-/* */
-/* PARAMETERS: */
-/* pInstance Instance pointer */
-/* pStereoIn Stereo source */
-/* pMonoIn Mono band pass source */
-/* pStereoOut Stereo destination */
-/* */
-/* RETURNS: */
-/* Void */
-/* */
-/* NOTES: */
-/* */
-/****************************************************************************************/
-void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t* pInstance, /* Instance pointer */
- const LVM_FLOAT* pStSrc, /* Stereo source */
- const LVM_FLOAT* pMonoSrc, /* Mono source */
- LVM_FLOAT* pDst, /* Stereo destination */
- LVM_UINT16 NumSamples) /* Number of samples */
-{
- /*
- * General variables
- */
- LVM_UINT16 i; /* Sample index */
- LVM_FLOAT Left; /* Left sample */
- LVM_FLOAT Right; /* Right sample */
- LVM_FLOAT Mono; /* Mono sample */
- LVM_FLOAT AbsPeak; /* Absolute peak signal */
- LVM_FLOAT AGC_Mult; /* Short AGC gain */
- LVM_FLOAT Vol_Mult; /* Short volume */
-
- /*
- * Instance control variables
- */
- LVM_FLOAT AGC_Gain = pInstance->AGC_Gain; /* Get the current AGC gain */
- LVM_FLOAT AGC_MaxGain = pInstance->AGC_MaxGain; /* Get maximum AGC gain */
- LVM_FLOAT AGC_Attack = pInstance->AGC_Attack; /* Attack scaler */
- LVM_FLOAT AGC_Decay = (pInstance->AGC_Decay * (1 << (DECAY_SHIFT))); /* Decay scaler */
- LVM_FLOAT AGC_Target = pInstance->AGC_Target; /* Get the target level */
- LVM_FLOAT Vol_Current = pInstance->Volume; /* Actual volume setting */
- LVM_FLOAT Vol_Target = pInstance->Target; /* Target volume setting */
- LVM_FLOAT Vol_TC = pInstance->VolumeTC; /* Time constant */
-
- /*
- * Process on a sample by sample basis
- */
- for (i = 0; i < NumSamples; i++) /* For each sample */
- {
- /*
- * Get the short scalers
- */
- AGC_Mult = (LVM_FLOAT)(AGC_Gain); /* Get the short AGC gain */
- Vol_Mult = (LVM_FLOAT)(Vol_Current); /* Get the short volume gain */
-
- /*
- * Get the input samples
- */
- Left = *pStSrc++; /* Get the left sample */
- Right = *pStSrc++; /* Get the right sample */
- Mono = *pMonoSrc++; /* Get the mono sample */
-
- /*
- * Apply the AGC gain to the mono input and mix with the stereo signal
- */
- Left += (Mono * AGC_Mult); /* Mix in the mono signal */
- Right += (Mono * AGC_Mult);
-
- /*
- * Apply the volume and write to the output stream
- */
- Left = Left * Vol_Mult;
- Right = Right * Vol_Mult;
- *pDst++ = Left; /* Save the results */
- *pDst++ = Right;
-
- /*
- * Update the AGC gain
- */
- AbsPeak = Abs_Float(Left) > Abs_Float(Right) ? Abs_Float(Left) : Abs_Float(Right);
- if (AbsPeak > AGC_Target) {
- /*
- * The signal is too large so decrease the gain
- */
- AGC_Gain = AGC_Gain * AGC_Attack;
- } else {
- /*
- * The signal is too small so increase the gain
- */
- if (AGC_Gain > AGC_MaxGain) {
- AGC_Gain -= (AGC_Decay);
- } else {
- AGC_Gain += (AGC_Decay);
- }
- }
-
- /*
- * Update the gain
- */
- Vol_Current += (Vol_Target - Vol_Current) * ((LVM_FLOAT)Vol_TC / VOL_TC_FLOAT);
- }
-
- /*
- * Update the parameters
- */
- pInstance->Volume = Vol_Current; /* Actual volume setting */
- pInstance->AGC_Gain = AGC_Gain;
-
- return;
-}
-/****************************************************************************************/
-/* */
/* FUNCTION: AGC_MIX_VOL_Mc1Mon_D32_WRA */
/* */
/* DESCRIPTION: */
@@ -255,7 +125,7 @@
*/
SampleVal = SampleVal * Vol_Mult;
- *pDst++ = SampleVal; /* Save the results */
+ *pDst++ = LVM_Clamp(SampleVal); /* Save the results */
/*
* Update the AGC gain
diff --git a/media/libeffects/lvm/lib/Common/src/Abs_32.cpp b/media/libeffects/lvm/lib/Common/src/Abs_32.cpp
deleted file mode 100644
index 3e37d89..0000000
--- a/media/libeffects/lvm/lib/Common/src/Abs_32.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*######################################################################################*/
-/* Include files */
-/*######################################################################################*/
-
-#include "ScalarArithmetic.h"
-
-/****************************************************************************************
- * Name : Abs_32()
- * Input : Signed 32-bit integer
- * Output :
- * Returns : Absolute value
- * Description : Absolute value with maximum negative value corner case
- * Remarks :
- ****************************************************************************************/
-
-LVM_INT32 Abs_32(LVM_INT32 input) {
- if (input < 0) {
- if (input == (LVM_INT32)(0x80000000U)) {
- /* The corner case, so set to the maximum positive value */
- input = (LVM_INT32)0x7fffffff;
- } else {
- /* Negative input, so invert */
- input = (LVM_INT32)(-input);
- }
- }
- return input;
-}
-LVM_FLOAT Abs_Float(LVM_FLOAT input) {
- if (input < 0) {
- /* Negative input, so invert */
- input = (LVM_FLOAT)(-input);
- }
- return input;
-}
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.cpp b/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.cpp
deleted file mode 100644
index be20521..0000000
--- a/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION ADD2_SAT_16X16
-***********************************************************************************/
-
-void Add2_Sat_16x16(const LVM_INT16* src, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT32 Temp;
- LVM_INT16 ii;
- for (ii = n; ii != 0; ii--) {
- Temp = ((LVM_INT32)*src) + ((LVM_INT32)*dst);
- src++;
-
- if (Temp > 0x00007FFF) {
- *dst = 0x7FFF;
- } else if (Temp < -0x00008000) {
- *dst = -0x8000;
- } else {
- *dst = (LVM_INT16)Temp;
- }
- dst++;
- }
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp
index 420f93e..1981edd 100644
--- a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp
@@ -18,53 +18,15 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
+#include "ScalarArithmetic.h"
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION ADD2_SAT_32X32
-***********************************************************************************/
-
-void Add2_Sat_32x32(const LVM_INT32* src, LVM_INT32* dst, LVM_INT16 n) {
- LVM_INT32 a, b, c;
- LVM_INT16 ii;
- for (ii = n; ii != 0; ii--) {
- a = *src;
- src++;
-
- b = *dst;
- c = a + b;
- if ((((c ^ a) & (c ^ b)) >> 31) != 0) /* overflow / underflow */
- {
- if (a < 0) {
- c = 0x80000000L;
- } else {
- c = 0x7FFFFFFFL;
- }
- }
-
- *dst = c;
- dst++;
- }
- return;
-}
-
void Add2_Sat_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_FLOAT Temp;
LVM_INT16 ii;
for (ii = n; ii != 0; ii--) {
- Temp = ((LVM_FLOAT)*src) + ((LVM_FLOAT)*dst);
- src++;
-
- if (Temp > 1.000000f) {
- *dst = 1.000000f;
- } else if (Temp < -1.000000f) {
- *dst = -1.000000f;
- } else {
- *dst = Temp;
- }
- dst++;
+ Temp = *src++ + *dst;
+ *dst++ = LVM_Clamp(Temp);
}
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp
index 198a6a1..bc9a2c5 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
@@ -67,3 +67,4 @@
*pDataOut++ = ynL; // Write Left output
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp
index 6d36302..571676b 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
*/
/*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
@@ -47,5 +48,6 @@
pBiquadState->coefs[1] = pCoef->B2;
pBiquadState->coefs[2] = pCoef->B1;
}
+#endif
/*-------------------------------------------------------------------------*/
/* End Of File: BP_1I_D16F16Css_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
index a41c855..c19e2f4 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#ifndef _BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
#define _BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
@@ -32,3 +33,4 @@
} Filter_State_FLOAT;
typedef Filter_State_FLOAT* PFilter_State_FLOAT;
#endif /*_BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_*/
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp
index d4d4eb1..ff3221a 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
@@ -68,3 +68,4 @@
*pDataOut++ = (ynL); // Write Left output
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp
index d322a8e..26a4793 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
*/
/*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
@@ -57,5 +58,6 @@
pBiquadState->coefs[1] = pCoef->B2;
pBiquadState->coefs[2] = pCoef->B1;
}
+#endif
/*-------------------------------------------------------------------------*/
/* End Of File: BP_1I_D16F32Cll_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
index 0603256..ae52cf2 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
@@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#ifndef _BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_
#define _BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_
@@ -31,3 +32,4 @@
} Filter_State_Float;
typedef Filter_State_Float* PFilter_State_FLOAT;
#endif /*_BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_*/
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp
index 0670334..6462092 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
#include "LVM_Macros.h"
@@ -68,3 +69,4 @@
*pDataOut++ = ynL; // Write Left output in Q0
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp
index 146cc63..9b4cccc 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp
@@ -16,6 +16,7 @@
*/
/*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
@@ -49,5 +50,6 @@
pBiquadState->coefs[2] = pCoef->B1;
}
+#endif
/*-------------------------------------------------------------------------*/
/* End Of File: BP_1I_D32F32Cll_TRC_WRA_02_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
index ea83c0b..93a7bfd 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
@@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#ifndef _BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_
#define _BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_
@@ -32,3 +33,4 @@
typedef Filter_State_Float* PFilter_State_FLOAT;
#endif /*_BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_*/
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp
index a46b1ef..85a7453 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
@@ -71,3 +72,4 @@
*pDataOut++ = (LVM_FLOAT)ynL; // Write Left output in Q0
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp
index e8bfcd8..7ad0793 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
*/
/*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
@@ -54,5 +55,6 @@
temp = pCoef->B1;
pBiquadState->coefs[4] = temp;
}
+#endif
/*-------------------------------------------------------------------------*/
/* End Of File: BQ_1I_D16F16Css_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
index ac2819e..9d1a3b6 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#ifndef _BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
#define _BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
@@ -33,3 +34,4 @@
} Filter_State_FLOAT;
typedef Filter_State_FLOAT* PFilter_State_FLOAT;
#endif /*_BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp
index c60dcf8..58320f7 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
@@ -71,3 +72,4 @@
*pDataOut++ = (LVM_FLOAT)(ynL); // Write Left output
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
index af0efc8..3293b2e 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
@@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#ifndef _BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
#define _BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
@@ -33,3 +34,4 @@
} Filter_State_FLOAT;
typedef Filter_State_FLOAT* PFilter_State_FLOAT;
#endif /*_BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_*/
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp
index ecf44ca..0d36e67 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp
@@ -16,6 +16,7 @@
*/
/*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
@@ -55,5 +56,6 @@
temp = pCoef->B1;
pBiquadState->coefs[4] = temp;
}
+#endif
/*-------------------------------------------------------------------------*/
/* End Of File: BQ_1I_D16F32Css_TRC_WRA_01_Init */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp
index d047e91..9ec9046 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
@@ -98,3 +99,4 @@
*pDataOut++ = (LVM_FLOAT)ynR; // Write Right output
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp
index 399b5ec..2478016 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
@@ -98,3 +99,4 @@
*pDataOut++ = (LVM_FLOAT)ynR; // Write Right output
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp
index e0cd934..8b2de31 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
*/
/*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
@@ -57,3 +58,4 @@
}
/*-------------------------------------------------------------------------*/
/* End Of File: BQ_2I_D16F16Css_TRC_WRA_01_Init.c */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
index 94cc794..f9a31a6 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#ifndef _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
#define _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
@@ -35,3 +36,4 @@
typedef Filter_State_FLOAT* PFilter_State_FLOAT;
#endif /* _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp
index 3b7eb5e..7a66bf9 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
@@ -102,3 +103,4 @@
pDataOut++;
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp
index 8c43430..db57150 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
@@ -102,3 +103,4 @@
pDataOut++;
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp
index 84fbadf..bc9e2df 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
@@ -102,3 +103,4 @@
pDataOut++;
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
index 1cc7618..de06cb1 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#ifndef _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
#define _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
@@ -35,3 +36,4 @@
typedef Filter_State_FLOAT* PFilter_State_FLOAT;
#endif /* _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp
index 6817d9f..0b9fb5a 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
@@ -55,3 +56,4 @@
}
/*-------------------------------------------------------------------------*/
/* End Of File: BQ_2I_D16F32Css_TRC_WRA_01_Init */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp
index 4eeaaa8..2097c4f 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
@@ -184,3 +185,4 @@
}
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp
index 1e27391..2d2a61f 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
*/
/*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
@@ -54,5 +55,6 @@
temp = pCoef->B1;
pBiquadState->coefs[4] = temp;
}
+#endif
/*-------------------------------------------------------------------------*/
/* End Of File: BQ_2I_D32F32C32_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
index 4a2149d..029c89d 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#ifndef _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
#define _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
@@ -35,3 +36,4 @@
typedef Filter_State_FLOAT* PFilter_State_FLOAT;
#endif /* _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_*/
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/Copy_16.cpp b/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
index 8887890..7046a94 100644
--- a/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
@@ -18,53 +18,11 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
+#include <string.h>
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION COPY_16
-***********************************************************************************/
-
-void Copy_16(const LVM_INT16* src, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT16 ii;
-
- if (src > dst) {
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst++;
- src++;
- }
- } else {
- src += n - 1;
- dst += n - 1;
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst--;
- src--;
- }
- }
-
- return;
-}
void Copy_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n) {
- LVM_INT16 ii;
-
- if (src > dst) {
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst++;
- src++;
- }
- } else {
- src += n - 1;
- dst += n - 1;
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst--;
- src--;
- }
- }
-
+ memmove(dst, src, n * sizeof(LVM_FLOAT));
return;
}
// Extract out the stereo channel pair from multichannel source.
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp
index be9e49b..b7f4b55 100644
--- a/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp
@@ -18,9 +18,9 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
#include "Mixer_private.h"
#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
/**********************************************************************************
FUNCTION CORE_MIXSOFT_1ST_D32C31_WRA
@@ -52,14 +52,7 @@
Temp2 = *dst;
Temp3 = Temp1 * (pInstance->Current);
- Temp1 = Temp2 + Temp3;
-
- if (Temp1 > 1.0f)
- Temp1 = 1.0f;
- else if (Temp1 < -1.0f)
- Temp1 = -1.0f;
-
- *dst++ = Temp1;
+ *dst++ = LVM_Clamp(Temp2 + Temp3);
}
}
@@ -72,13 +65,7 @@
Temp2 = *dst;
Temp3 = Temp1 * (pInstance->Current);
- Temp1 = Temp2 + Temp3;
-
- if (Temp1 > 1.0f)
- Temp1 = 1.0f;
- else if (Temp1 < -1.0f)
- Temp1 = -1.0f;
- *dst++ = Temp1;
+ *dst++ = LVM_Clamp(Temp2 + Temp3);
}
}
}
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp
index 2861be6..6e859f4 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp
@@ -14,51 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include "BIQUAD.h"
#include "DC_2I_D16_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
-void DC_2I_D16_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT LeftDC, RightDC;
- LVM_FLOAT Diff;
- LVM_INT32 j;
- PFilter_FLOAT_State pBiquadState = (PFilter_FLOAT_State)pInstance;
-
- LeftDC = pBiquadState->LeftDC;
- RightDC = pBiquadState->RightDC;
- for (j = NrSamples - 1; j >= 0; j--) {
- /* Subtract DC and saturate */
- Diff = *(pDataIn++) - (LeftDC);
- if (Diff > 1.0f) {
- Diff = 1.0f;
- } else if (Diff < -1.0f) {
- Diff = -1.0f;
- }
- *(pDataOut++) = (LVM_FLOAT)Diff;
- if (Diff < 0) {
- LeftDC -= DC_FLOAT_STEP;
- } else {
- LeftDC += DC_FLOAT_STEP;
- }
-
- /* Subtract DC an saturate */
- Diff = *(pDataIn++) - (RightDC);
- if (Diff > 1.0f) {
- Diff = 1.0f;
- } else if (Diff < -1.0f) {
- Diff = -1.0f;
- }
- *(pDataOut++) = (LVM_FLOAT)Diff;
- if (Diff < 0) {
- RightDC -= DC_FLOAT_STEP;
- } else {
- RightDC += DC_FLOAT_STEP;
- }
- }
- pBiquadState->LeftDC = LeftDC;
- pBiquadState->RightDC = RightDC;
-}
+#include "ScalarArithmetic.h"
/*
* FUNCTION: DC_Mc_D16_TRC_WRA_01
*
@@ -89,12 +48,7 @@
/* Subtract DC and saturate */
for (i = NrChannels - 1; i >= 0; i--) {
Diff = *(pDataIn++) - (ChDC[i]);
- if (Diff > 1.0f) {
- Diff = 1.0f;
- } else if (Diff < -1.0f) {
- Diff = -1.0f;
- }
- *(pDataOut++) = (LVM_FLOAT)Diff;
+ *(pDataOut++) = LVM_Clamp(Diff);
if (Diff < 0) {
ChDC[i] -= DC_FLOAT_STEP;
} else {
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp
index 2828cb3..c16718c 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp
@@ -17,11 +17,6 @@
#include "BIQUAD.h"
#include "DC_2I_D16_TRC_WRA_01_Private.h"
-void DC_2I_D16_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance) {
- PFilter_FLOAT_State pBiquadState = (PFilter_FLOAT_State)pInstance;
- pBiquadState->LeftDC = 0.0f;
- pBiquadState->RightDC = 0.0f;
-}
void DC_Mc_D16_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance) {
PFilter_FLOAT_State_Mc pBiquadState = (PFilter_FLOAT_State_Mc)pInstance;
LVM_INT32 i;
diff --git a/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.cpp b/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.cpp
deleted file mode 100644
index 5daef59..0000000
--- a/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION DelayAllPass_32x32
-***********************************************************************************/
-
-void DelayAllPass_Sat_32x16To32(LVM_INT32* delay, /* Delay buffer */
- LVM_UINT16 size, /* Delay size */
- LVM_INT16 coeff, /* All pass filter coefficient */
- LVM_UINT16 DelayOffset, /* Simple delay offset */
- LVM_UINT16* pAllPassOffset, /* All pass filter delay offset */
- LVM_INT32* dst, /* Source/destination */
- LVM_INT16 n) /* Number of samples */
-{
- LVM_INT16 i;
- LVM_UINT16 AllPassOffset = *pAllPassOffset;
- LVM_INT32 temp;
- LVM_INT32 a, b, c;
-
- for (i = 0; i < n; i++) {
- MUL32x16INTO32(delay[AllPassOffset], coeff, temp, 15) a = temp;
- b = delay[DelayOffset];
- DelayOffset++;
-
- c = a + b;
- if ((((c ^ a) & (c ^ b)) >> 31) != 0) /* overflow / underflow */
- {
- if (a < 0) {
- c = 0x80000000L;
- } else {
- c = 0x7FFFFFFFL;
- }
- }
- *dst = c;
- dst++;
-
- MUL32x16INTO32(c, -coeff, temp, 15) a = temp;
- b = delay[AllPassOffset];
- c = a + b;
- if ((((c ^ a) & (c ^ b)) >> 31) != 0) /* overflow / underflow */
- {
- if (a < 0) {
- c = 0x80000000L;
- } else {
- c = 0x7FFFFFFFL;
- }
- }
- delay[AllPassOffset] = c;
- AllPassOffset++;
-
- /* Make the delay buffer a circular buffer */
- if (DelayOffset >= size) {
- DelayOffset = 0;
- }
-
- if (AllPassOffset >= size) {
- AllPassOffset = 0;
- }
- }
-
- /* Update the offset */
- *pAllPassOffset = AllPassOffset;
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp
index da75982..d2537eb 100644
--- a/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp
@@ -21,51 +21,6 @@
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION DelayMix_16x16
-***********************************************************************************/
-
-void DelayMix_16x16(const LVM_INT16* src, /* Source 1, to be delayed */
- LVM_INT16* delay, /* Delay buffer */
- LVM_INT16 size, /* Delay size */
- LVM_INT16* dst, /* Source/destination */
- LVM_INT16* pOffset, /* Delay offset */
- LVM_INT16 n) /* Number of stereo samples */
-{
- LVM_INT16 i;
- LVM_INT16 Offset = *pOffset;
- LVM_INT16 temp;
-
- for (i = 0; i < n; i++) {
- /* Left channel */
- temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) + (LVM_INT32)delay[Offset]) >> 1);
- *dst = temp;
- dst++;
-
- delay[Offset] = *src;
- Offset++;
- src++;
-
- /* Right channel */
- temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) - (LVM_INT32)delay[Offset]) >> 1);
- *dst = temp;
- dst++;
-
- delay[Offset] = *src;
- Offset++;
- src++;
-
- /* Make the reverb delay buffer a circular buffer */
- if (Offset >= size) {
- Offset = 0;
- }
- }
-
- /* Update the offset */
- *pOffset = Offset;
-
- return;
-}
void DelayMix_Float(const LVM_FLOAT* src, /* Source 1, to be delayed */
LVM_FLOAT* delay, /* Delay buffer */
LVM_INT16 size, /* Delay size */
@@ -107,4 +62,3 @@
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DelayWrite_32.cpp b/media/libeffects/lvm/lib/Common/src/DelayWrite_32.cpp
deleted file mode 100644
index 47cffbf..0000000
--- a/media/libeffects/lvm/lib/Common/src/DelayWrite_32.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION DelayMix_16x16
-***********************************************************************************/
-
-void DelayWrite_32(const LVM_INT32* src, /* Source 1, to be delayed */
- LVM_INT32* delay, /* Delay buffer */
- LVM_UINT16 size, /* Delay size */
- LVM_UINT16* pOffset, /* Delay offset */
- LVM_INT16 n) /* Number of samples */
-{
- LVM_INT16 i;
- LVM_INT16 Offset = (LVM_INT16)*pOffset;
-
- for (i = 0; i < n; i++) {
- delay[Offset] = *src;
- Offset++;
- src++;
-
- /* Make the delay buffer a circular buffer */
- if (Offset >= size) {
- Offset = 0;
- }
- }
-
- /* Update the offset */
- *pOffset = (LVM_UINT16)Offset;
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp
index df8fadc..c85dfb6 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
@@ -62,3 +63,4 @@
*pDataOut++ = (LVM_FLOAT)ynL; // Write Left output
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp
index 10604bf..0cff849 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
*/
/*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
@@ -52,3 +53,4 @@
}
/*------------------------------------------------*/
/* End Of File: FO_1I_D16F16Css_TRC_WRA_01_Init.c */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
index d1819fc..50b09b6 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#ifndef _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
#define _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
@@ -35,3 +36,4 @@
typedef Filter_State_FLOAT* PFilter_State_FLOAT;
#endif /* _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp
index 4c75e04..dac090f 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
@@ -63,3 +64,4 @@
*pDataOut++ = (LVM_FLOAT)ynL; // Write Left output in Q0
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp
index bf2e5e1..efd6bc0 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
@@ -50,5 +51,6 @@
temp = pCoef->B1;
pBiquadState->coefs[2] = temp;
}
+#endif
/*------------------------------------------------*/
/* End Of File: FO_1I_D32F32Cll_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
index 8645593..95705be 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#ifndef _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
#define _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
@@ -34,3 +35,4 @@
typedef Filter_State_FLOAT* PFilter_State_FLOAT;
#endif /* _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp
index dad070b..1e3f1e8 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
@@ -24,86 +25,6 @@
COEFS-
pBiquadState->coefs[0] is A1,
pBiquadState->coefs[1] is A0,
-pBiquadState->coefs[2] is -B1, these are in Q15 format
-pBiquadState->Shift is Shift value
-DELAYS-
-pBiquadState->pDelays[0] is x(n-1)L in Q15 format
-pBiquadState->pDelays[1] is y(n-1)L in Q30 format
-pBiquadState->pDelays[2] is x(n-1)R in Q15 format
-pBiquadState->pDelays[3] is y(n-1)R in Q30 format
-***************************************************************************/
-void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL, ynR;
- LVM_FLOAT Temp;
- LVM_FLOAT NegSatValue;
- LVM_INT16 ii;
-
- PFilter_Float_State pBiquadState = (PFilter_Float_State)pInstance;
-
- NegSatValue = -1.0f;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
-
- // ynL =A1 * x(n-1)L
- ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[0];
- // ynR =A1 * x(n-1)R
- ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
- // ynL+=A0 * x(n)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[1] * (*pDataIn);
- // ynR+=A0 * x(n)L
- ynR += (LVM_FLOAT)pBiquadState->coefs[1] * (*(pDataIn + 1));
-
- // ynL += (-B1 * y(n-1)L )
- Temp = pBiquadState->pDelays[1] * pBiquadState->coefs[2];
- ynL += Temp;
- // ynR += (-B1 * y(n-1)R ) )
- Temp = pBiquadState->pDelays[3] * pBiquadState->coefs[2];
- ynR += Temp;
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[1] = ynL; // Update y(n-1)L
- pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
- pBiquadState->pDelays[3] = ynR; // Update y(n-1)R
- pBiquadState->pDelays[2] = (*pDataIn++); // Update x(n-1)R
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
-
- /*Saturate results*/
- if (ynL > 1.0f) {
- ynL = 1.0f;
- } else {
- if (ynL < NegSatValue) {
- ynL = NegSatValue;
- }
- }
-
- if (ynR > 1.0f) {
- ynR = 1.0f;
- } else {
- if (ynR < NegSatValue) {
- ynR = NegSatValue;
- }
- }
-
- *pDataOut++ = (LVM_FLOAT)ynL;
- *pDataOut++ = (LVM_FLOAT)ynR;
- }
-}
-/**************************************************************************
-ASSUMPTIONS:
-COEFS-
-pBiquadState->coefs[0] is A1,
-pBiquadState->coefs[1] is A0,
pBiquadState->coefs[2] is -B1,
DELAYS-
pBiquadState->pDelays[2*ch + 0] is x(n-1) of the 'ch' - channel
@@ -173,3 +94,4 @@
pDelays -= NrChannels * 2;
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp
index 552aeda..54fbe4a 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
*/
/*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
@@ -51,5 +52,6 @@
temp = pCoef->B1;
pBiquadState->coefs[2] = temp;
}
+#endif
/*-------------------------------------------------------------------------*/
/* End Of File: FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
index 0103328..a71fa32 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#ifndef _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_
#define _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_
@@ -27,3 +28,4 @@
typedef Filter_Float_State* PFilter_Float_State;
#endif /* _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp
index b050267..e2f8c67 100644
--- a/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp
@@ -21,33 +21,6 @@
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION From2iToMS_16x16
-***********************************************************************************/
-
-void From2iToMS_16x16(const LVM_INT16* src, LVM_INT16* dstM, LVM_INT16* dstS, LVM_INT16 n) {
- LVM_INT32 temp1, left, right;
- LVM_INT16 ii;
- for (ii = n; ii != 0; ii--) {
- left = (LVM_INT32)*src;
- src++;
-
- right = (LVM_INT32)*src;
- src++;
-
- /* Compute M signal*/
- temp1 = (left + right) >> 1;
- *dstM = (LVM_INT16)temp1;
- dstM++;
-
- /* Compute S signal*/
- temp1 = (left - right) >> 1;
- *dstS = (LVM_INT16)temp1;
- dstS++;
- }
-
- return;
-}
void From2iToMS_Float(const LVM_FLOAT* src, LVM_FLOAT* dstM, LVM_FLOAT* dstS, LVM_INT16 n) {
LVM_FLOAT temp1, left, right;
LVM_INT16 ii;
@@ -71,4 +44,3 @@
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_16.cpp b/media/libeffects/lvm/lib/Common/src/From2iToMono_16.cpp
deleted file mode 100644
index 9a54ee4..0000000
--- a/media/libeffects/lvm/lib/Common/src/From2iToMono_16.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION From2iToMono_16
-***********************************************************************************/
-
-void From2iToMono_16(const LVM_INT16* src, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- LVM_INT32 Temp;
- for (ii = n; ii != 0; ii--) {
- Temp = (LVM_INT32)*src;
- src++;
-
- Temp += (LVM_INT32)*src;
- src++;
-
- *dst = (LVM_INT16)(Temp >> 1);
- dst++;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp
index 6ede958..039ee14 100644
--- a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp
@@ -21,27 +21,6 @@
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION From2iToMono_32
-***********************************************************************************/
-
-void From2iToMono_32(const LVM_INT32* src, LVM_INT32* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- LVM_INT32 Temp;
-
- for (ii = n; ii != 0; ii--) {
- Temp = (*src >> 1);
- src++;
-
- Temp += (*src >> 1);
- src++;
-
- *dst = Temp;
- dst++;
- }
-
- return;
-}
void From2iToMono_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_INT16 ii;
LVM_FLOAT Temp;
@@ -93,5 +72,3 @@
return;
}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.cpp b/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.cpp
deleted file mode 100644
index 9ddcbe4..0000000
--- a/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION INT16LSHIFTTOINT32_16X32
-***********************************************************************************/
-
-void Int16LShiftToInt32_16x32(const LVM_INT16* src, LVM_INT32* dst, LVM_INT16 n, LVM_INT16 shift) {
- LVM_INT16 ii;
-
- src += n - 1;
- dst += n - 1;
-
- for (ii = n; ii != 0; ii--) {
- *dst = (((LVM_INT32)*src) << shift);
- src--;
- dst--;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.cpp b/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.cpp
deleted file mode 100644
index 2584117..0000000
--- a/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION INT32RSHIFTTOINT16_SAT_32X16
-***********************************************************************************/
-
-void Int32RShiftToInt16_Sat_32x16(const LVM_INT32* src, LVM_INT16* dst, LVM_INT16 n,
- LVM_INT16 shift) {
- LVM_INT32 temp;
- LVM_INT16 ii;
-
- for (ii = n; ii != 0; ii--) {
- temp = *src >> shift;
- src++;
-
- if (temp > 0x00007FFF) {
- *dst = 0x7FFF;
- } else if (temp < -0x00008000) {
- *dst = -0x8000;
- } else {
- *dst = (LVM_INT16)temp;
- }
-
- dst++;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp
index 0721b76..6c7c8ae 100644
--- a/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp
+++ b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp
@@ -21,29 +21,6 @@
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION JoinTo2i_32x32
-***********************************************************************************/
-
-void JoinTo2i_32x32(const LVM_INT32* srcL, const LVM_INT32* srcR, LVM_INT32* dst, LVM_INT16 n) {
- LVM_INT16 ii;
-
- srcL += n - 1;
- srcR += n - 1;
- dst += ((2 * n) - 1);
-
- for (ii = n; ii != 0; ii--) {
- *dst = *srcR;
- dst--;
- srcR--;
-
- *dst = *srcL;
- dst--;
- srcL--;
- }
-
- return;
-}
void JoinTo2i_Float(const LVM_FLOAT* srcL, const LVM_FLOAT* srcR, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_INT16 ii;
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp
index 8b00925..d670b3d 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp
@@ -18,39 +18,10 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
#include "LVC_Mixer_Private.h"
#include "LVM_Macros.h"
#include "ScalarArithmetic.h"
-/**********************************************************************************
- FUNCTION LVC_Core_MixHard_1St_2i_D16C31_SAT
-***********************************************************************************/
-void LVC_Core_MixHard_1St_2i_D16C31_SAT(LVMixer3_FLOAT_st* ptrInstance1,
- LVMixer3_FLOAT_st* ptrInstance2, const LVM_FLOAT* src,
- LVM_FLOAT* dst, LVM_INT16 n) {
- LVM_FLOAT Temp;
- LVM_INT16 ii;
- Mix_Private_FLOAT_st* pInstance1 = (Mix_Private_FLOAT_st*)(ptrInstance1->PrivateParams);
- Mix_Private_FLOAT_st* pInstance2 = (Mix_Private_FLOAT_st*)(ptrInstance2->PrivateParams);
- for (ii = n; ii != 0; ii--) {
- Temp = ((LVM_FLOAT) * (src++) * (LVM_FLOAT)pInstance1->Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
-
- Temp = ((LVM_FLOAT) * (src++) * (LVM_FLOAT)pInstance2->Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
- }
-}
void LVC_Core_MixHard_1St_MC_float_SAT(Mix_Private_FLOAT_st** ptrInstance, const LVM_FLOAT* src,
LVM_FLOAT* dst, LVM_INT16 NrFrames, LVM_INT16 NrChannels) {
LVM_FLOAT Temp;
@@ -58,14 +29,8 @@
for (ii = NrFrames; ii != 0; ii--) {
for (jj = 0; jj < NrChannels; jj++) {
Mix_Private_FLOAT_st* pInstance1 = (Mix_Private_FLOAT_st*)(ptrInstance[jj]);
- Temp = ((LVM_FLOAT) * (src++) * (LVM_FLOAT)pInstance1->Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
+ Temp = *src++ * pInstance1->Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp
index 31cd805..417c1f0 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp
@@ -18,8 +18,8 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
#include "LVC_Mixer_Private.h"
+#include "ScalarArithmetic.h"
/**********************************************************************************
FUNCTION LVCore_MIXHARD_2ST_D16C31_SAT
@@ -34,18 +34,12 @@
Mix_Private_FLOAT_st* pInstance1 = (Mix_Private_FLOAT_st*)(ptrInstance1->PrivateParams);
Mix_Private_FLOAT_st* pInstance2 = (Mix_Private_FLOAT_st*)(ptrInstance2->PrivateParams);
- Current1 = (pInstance1->Current);
- Current2 = (pInstance2->Current);
+ Current1 = pInstance1->Current;
+ Current2 = pInstance2->Current;
for (ii = n; ii != 0; ii--) {
- Temp = (((LVM_FLOAT) * (src1++) * (LVM_FLOAT)Current1)) +
- (((LVM_FLOAT) * (src2++) * (LVM_FLOAT)Current2));
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *src1++ * Current1 + *src2++ * Current2;
+ *dst++ = LVM_Clamp(Temp);
}
}
/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp
index b7865d9..d8c25c9 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp
@@ -18,9 +18,9 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
#include "LVC_Mixer_Private.h"
#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
/**********************************************************************************
FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
@@ -46,13 +46,8 @@
if (Current > Target) Current = Target;
for (ii = OutLoop; ii != 0; ii--) {
- Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT) * (src++) * Current));
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
@@ -62,13 +57,8 @@
if (Current > Target) Current = Target;
for (jj = 4; jj != 0; jj--) {
- Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT) * (src++) * Current));
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
} else {
@@ -77,13 +67,8 @@
if (Current < Target) Current = Target;
for (ii = OutLoop; ii != 0; ii--) {
- Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT) * (src++) * Current));
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
@@ -92,13 +77,8 @@
if (Current < Target) Current = Target;
for (jj = 4; jj != 0; jj--) {
- Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT) * (src++) * Current));
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
}
@@ -148,13 +128,8 @@
if (Current > Target) Current = Target;
for (ii = OutLoop * NrChannels; ii != 0; ii--) {
- Temp = (*dst) + (*(src++) * Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
@@ -164,21 +139,11 @@
if (Current > Target) Current = Target;
for (jj = NrChannels; jj != 0; jj--) {
- Temp = (*dst) + (*(src++) * Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
- Temp = (*dst) + (*(src++) * Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
} else {
@@ -187,13 +152,8 @@
if (Current < Target) Current = Target;
for (ii = OutLoop * NrChannels; ii != 0; ii--) {
- Temp = (*dst) + (*(src++) * Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
@@ -202,21 +162,11 @@
if (Current < Target) Current = Target;
for (jj = NrChannels; jj != 0; jj--) {
- Temp = (*dst) + (*(src++) * Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
- Temp = (*dst) + (*(src++) * Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp
index d45845a..0968cf8 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp
@@ -18,107 +18,16 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
#include "LVC_Mixer_Private.h"
-#include "ScalarArithmetic.h"
#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
-/**********************************************************************************
- FUNCTION LVC_Core_MixSoft_1St_2i_D16C31_WRA
-***********************************************************************************/
-static LVM_FLOAT ADD2_SAT_FLOAT(LVM_FLOAT a, LVM_FLOAT b, LVM_FLOAT c) {
- LVM_FLOAT temp;
- temp = a + b;
- if (temp < -1.0f)
- c = -1.0f;
- else if (temp > 1.0f)
- c = 1.0f;
- else
- c = temp;
- return c;
-}
-void LVC_Core_MixSoft_1St_2i_D16C31_WRA(LVMixer3_FLOAT_st* ptrInstance1,
- LVMixer3_FLOAT_st* ptrInstance2, const LVM_FLOAT* src,
- LVM_FLOAT* dst, LVM_INT16 n) {
- LVM_INT16 OutLoop;
- LVM_INT16 InLoop;
- LVM_INT32 ii;
- Mix_Private_FLOAT_st* pInstanceL = (Mix_Private_FLOAT_st*)(ptrInstance1->PrivateParams);
- Mix_Private_FLOAT_st* pInstanceR = (Mix_Private_FLOAT_st*)(ptrInstance2->PrivateParams);
-
- LVM_FLOAT DeltaL = pInstanceL->Delta;
- LVM_FLOAT CurrentL = pInstanceL->Current;
- LVM_FLOAT TargetL = pInstanceL->Target;
-
- LVM_FLOAT DeltaR = pInstanceR->Delta;
- LVM_FLOAT CurrentR = pInstanceR->Current;
- LVM_FLOAT TargetR = pInstanceR->Target;
-
- LVM_FLOAT Temp = 0;
-
- InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
- OutLoop = (LVM_INT16)(n - (InLoop << 2));
-
- if (OutLoop) {
- if (CurrentL < TargetL) {
- ADD2_SAT_FLOAT(CurrentL, DeltaL, Temp);
- CurrentL = Temp;
- if (CurrentL > TargetL) CurrentL = TargetL;
- } else {
- CurrentL -= DeltaL;
- if (CurrentL < TargetL) CurrentL = TargetL;
- }
-
- if (CurrentR < TargetR) {
- ADD2_SAT_FLOAT(CurrentR, DeltaR, Temp);
- CurrentR = Temp;
- if (CurrentR > TargetR) CurrentR = TargetR;
- } else {
- CurrentR -= DeltaR;
- if (CurrentR < TargetR) CurrentR = TargetR;
- }
-
- for (ii = OutLoop * 2; ii != 0; ii -= 2) {
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
- }
- }
-
- for (ii = InLoop * 2; ii != 0; ii -= 2) {
- if (CurrentL < TargetL) {
- ADD2_SAT_FLOAT(CurrentL, DeltaL, Temp);
- CurrentL = Temp;
- if (CurrentL > TargetL) CurrentL = TargetL;
- } else {
- CurrentL -= DeltaL;
- if (CurrentL < TargetL) CurrentL = TargetL;
- }
-
- if (CurrentR < TargetR) {
- ADD2_SAT_FLOAT(CurrentR, DeltaR, Temp);
- CurrentR = Temp;
- if (CurrentR > TargetR) CurrentR = TargetR;
- } else {
- CurrentR -= DeltaR;
- if (CurrentR < TargetR) CurrentR = TargetR;
- }
-
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
- }
- pInstanceL->Current = CurrentL;
- pInstanceR->Current = CurrentR;
+static inline LVM_FLOAT ADD2_SAT_FLOAT(LVM_FLOAT a, LVM_FLOAT b) {
+ return LVM_Clamp(a + b);
}
void LVC_Core_MixSoft_1St_MC_float_WRA(Mix_Private_FLOAT_st** ptrInstance, const LVM_FLOAT* src,
LVM_FLOAT* dst, LVM_INT16 NrFrames, LVM_INT16 NrChannels) {
LVM_INT32 ii, ch;
- LVM_FLOAT Temp = 0.0f;
LVM_FLOAT tempCurrent[NrChannels];
for (ch = 0; ch < NrChannels; ch++) {
tempCurrent[ch] = ptrInstance[ch]->Current;
@@ -130,8 +39,7 @@
LVM_FLOAT Current = tempCurrent[ch];
const LVM_FLOAT Target = pInstance->Target;
if (Current < Target) {
- ADD2_SAT_FLOAT(Current, Delta, Temp);
- Current = Temp;
+ Current = ADD2_SAT_FLOAT(Current, Delta);
if (Current > Target) Current = Target;
} else {
Current -= Delta;
@@ -145,4 +53,3 @@
ptrInstance[ch]->Current = tempCurrent[ch];
}
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp
index f8c0a9d..fc464e6 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp
@@ -18,7 +18,6 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
#include "LVC_Mixer_Private.h"
#include "LVM_Macros.h"
#include "ScalarArithmetic.h"
@@ -35,20 +34,13 @@
LVM_FLOAT Delta = (LVM_FLOAT)pInstance->Delta;
LVM_FLOAT Current = (LVM_FLOAT)pInstance->Current;
LVM_FLOAT Target = (LVM_FLOAT)pInstance->Target;
- LVM_FLOAT Temp;
InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
OutLoop = (LVM_INT16)(n - (InLoop << 2));
if (Current < Target) {
if (OutLoop) {
- Temp = Current + Delta;
- if (Temp > 1.0f)
- Temp = 1.0f;
- else if (Temp < -1.0f)
- Temp = -1.0f;
-
- Current = Temp;
+ Current = LVM_Clamp(Current + Delta);
if (Current > Target) Current = Target;
for (ii = OutLoop; ii != 0; ii--) {
@@ -57,14 +49,8 @@
}
for (ii = InLoop; ii != 0; ii--) {
- Temp = Current + Delta;
+ Current = LVM_Clamp(Current + Delta);
- if (Temp > 1.0f)
- Temp = 1.0f;
- else if (Temp < -1.0f)
- Temp = -1.0f;
-
- Current = Temp;
if (Current > Target) Current = Target;
*(dst++) = (((LVM_FLOAT) * (src++) * Current));
@@ -121,7 +107,6 @@
LVM_FLOAT Delta = (LVM_FLOAT)pInstance->Delta;
LVM_FLOAT Current = (LVM_FLOAT)pInstance->Current;
LVM_FLOAT Target = (LVM_FLOAT)pInstance->Target;
- LVM_FLOAT Temp;
/*
* Same operation is performed on consecutive frames.
@@ -134,13 +119,7 @@
if (Current < Target) {
if (OutLoop) {
- Temp = Current + Delta;
- if (Temp > 1.0f)
- Temp = 1.0f;
- else if (Temp < -1.0f)
- Temp = -1.0f;
-
- Current = Temp;
+ Current = LVM_Clamp(Current + Delta);
if (Current > Target) Current = Target;
for (ii = OutLoop; ii != 0; ii--) {
@@ -151,14 +130,7 @@
}
for (ii = InLoop; ii != 0; ii--) {
- Temp = Current + Delta;
-
- if (Temp > 1.0f)
- Temp = 1.0f;
- else if (Temp < -1.0f)
- Temp = -1.0f;
-
- Current = Temp;
+ Current = LVM_Clamp(Current + Delta);
if (Current > Target) Current = Target;
for (jj = NrChannels; jj != 0; jj--) {
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp
index c74c8c6..58bc06e 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp
@@ -35,7 +35,7 @@
#define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof(*(a))))
/**********************************************************************************
- FUNCTION LVC_MixSoft_1St_2i_D16C31_SAT
+ FUNCTION LVC_MixSoft_1St_MC_float_SAT
***********************************************************************************/
/* This threshold is used to decide on the processing to be applied on
* front center and back center channels
@@ -192,106 +192,3 @@
}
}
}
-void LVC_MixSoft_1St_2i_D16C31_SAT(LVMixer3_2St_FLOAT_st* ptrInstance, const LVM_FLOAT* src,
- LVM_FLOAT* dst, LVM_INT16 n) {
- char HardMixing = TRUE;
- LVM_FLOAT TargetGain;
- Mix_Private_FLOAT_st* pInstance1 =
- (Mix_Private_FLOAT_st*)(ptrInstance->MixerStream[0].PrivateParams);
- Mix_Private_FLOAT_st* pInstance2 =
- (Mix_Private_FLOAT_st*)(ptrInstance->MixerStream[1].PrivateParams);
-
- if (n <= 0) return;
-
- /******************************************************************************
- SOFT MIXING
- *******************************************************************************/
- if ((pInstance1->Current != pInstance1->Target) ||
- (pInstance2->Current != pInstance2->Target)) {
- if (pInstance1->Delta == 1.0f) {
- pInstance1->Current = pInstance1->Target;
- TargetGain = pInstance1->Target;
- LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
- } else if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta) {
- pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
- Make them equal. */
- TargetGain = pInstance1->Target;
- LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
- } else {
- /* Soft mixing has to be applied */
- HardMixing = FALSE;
- }
-
- if (HardMixing == TRUE) {
- if (pInstance2->Delta == 1.0f) {
- pInstance2->Current = pInstance2->Target;
- TargetGain = pInstance2->Target;
- LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
- } else if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta) {
- pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.
- \ Make them equal. */
- TargetGain = pInstance2->Target;
- LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
- } else {
- /* Soft mixing has to be applied */
- HardMixing = FALSE;
- }
- }
-
- if (HardMixing == FALSE) {
- LVC_Core_MixSoft_1St_2i_D16C31_WRA(&(ptrInstance->MixerStream[0]),
- &(ptrInstance->MixerStream[1]), src, dst, n);
- }
- }
-
- /******************************************************************************
- HARD MIXING
- *******************************************************************************/
-
- if (HardMixing) {
- if ((pInstance1->Target == 1.0f) && (pInstance2->Target == 1.0f)) {
- if (src != dst) {
- Copy_Float(src, dst, n);
- }
- } else {
- LVC_Core_MixHard_1St_2i_D16C31_SAT(&(ptrInstance->MixerStream[0]),
- &(ptrInstance->MixerStream[1]), src, dst, n);
- }
- }
-
- /******************************************************************************
- CALL BACK
- *******************************************************************************/
-
- if (ptrInstance->MixerStream[0].CallbackSet) {
- if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta) {
- pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
- Make them equal. */
- TargetGain = pInstance1->Target;
- LVC_Mixer_SetTarget(&ptrInstance->MixerStream[0], TargetGain);
- ptrInstance->MixerStream[0].CallbackSet = FALSE;
- if (ptrInstance->MixerStream[0].pCallBack != 0) {
- (*ptrInstance->MixerStream[0].pCallBack)(
- ptrInstance->MixerStream[0].pCallbackHandle,
- ptrInstance->MixerStream[0].pGeneralPurpose,
- ptrInstance->MixerStream[0].CallbackParam);
- }
- }
- }
- if (ptrInstance->MixerStream[1].CallbackSet) {
- if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta) {
- pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.
- Make them equal. */
- TargetGain = pInstance2->Target;
- LVC_Mixer_SetTarget(&ptrInstance->MixerStream[1], TargetGain);
- ptrInstance->MixerStream[1].CallbackSet = FALSE;
- if (ptrInstance->MixerStream[1].pCallBack != 0) {
- (*ptrInstance->MixerStream[1].pCallBack)(
- ptrInstance->MixerStream[1].pCallbackHandle,
- ptrInstance->MixerStream[1].pGeneralPurpose,
- ptrInstance->MixerStream[1].CallbackParam);
- }
- }
- }
-}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
index 55255a6..1eb2dea 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
@@ -101,9 +101,6 @@
void LVC_MixSoft_1St_MC_float_SAT(LVMixer3_2St_FLOAT_st* pInstance, const LVM_FLOAT* src,
LVM_FLOAT* dst, /* dst can be equal to src */
LVM_INT16 NrFrames, LVM_INT32 NrChannels, LVM_INT32 ChMask);
-void LVC_MixSoft_1St_2i_D16C31_SAT(LVMixer3_2St_FLOAT_st* pInstance, const LVM_FLOAT* src,
- LVM_FLOAT* dst, /* dst can be equal to src */
- LVM_INT16 n); /* Number of stereo samples */
/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
index 5f22d77..9206fae 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
@@ -65,9 +65,6 @@
/**********************************************************************************/
void LVC_Core_MixSoft_1St_MC_float_WRA(Mix_Private_FLOAT_st** ptrInstance, const LVM_FLOAT* src,
LVM_FLOAT* dst, LVM_INT16 NrFrames, LVM_INT16 NrChannels);
-void LVC_Core_MixSoft_1St_2i_D16C31_WRA(LVMixer3_FLOAT_st* ptrInstance1,
- LVMixer3_FLOAT_st* ptrInstance2, const LVM_FLOAT* src,
- LVM_FLOAT* dst, LVM_INT16 n);
/**********************************************************************************/
/* For applying different gains to Left and right chennals */
@@ -77,11 +74,5 @@
/**********************************************************************************/
void LVC_Core_MixHard_1St_MC_float_SAT(Mix_Private_FLOAT_st** ptrInstance, const LVM_FLOAT* src,
LVM_FLOAT* dst, LVM_INT16 NrFrames, LVM_INT16 NrChannels);
-void LVC_Core_MixHard_1St_2i_D16C31_SAT(LVMixer3_FLOAT_st* ptrInstance1,
- LVMixer3_FLOAT_st* ptrInstance2, const LVM_FLOAT* src,
- LVM_FLOAT* dst, LVM_INT16 n);
-
-/*** 32 bit functions *************************************************************/
-/**********************************************************************************/
#endif //#ifndef __LVC_MIXER_PRIVATE_H__
diff --git a/media/libeffects/lvm/lib/Common/src/LoadConst_16.cpp b/media/libeffects/lvm/lib/Common/src/LoadConst_16.cpp
deleted file mode 100644
index a39fa2f..0000000
--- a/media/libeffects/lvm/lib/Common/src/LoadConst_16.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION LoadConst_16
-***********************************************************************************/
-
-void LoadConst_16(const LVM_INT16 val, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT16 ii;
-
- for (ii = n; ii != 0; ii--) {
- *dst = val;
- dst++;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp
index a19e66f..e5c6f15 100644
--- a/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp
@@ -18,49 +18,9 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
+#include "ScalarArithmetic.h"
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION MSTO2I_SAT_16X16
-***********************************************************************************/
-
-void MSTo2i_Sat_16x16(const LVM_INT16* srcM, const LVM_INT16* srcS, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT32 temp, mVal, sVal;
- LVM_INT16 ii;
-
- for (ii = n; ii != 0; ii--) {
- mVal = (LVM_INT32)*srcM;
- srcM++;
-
- sVal = (LVM_INT32)*srcS;
- srcS++;
-
- temp = mVal + sVal;
-
- if (temp > 0x00007FFF) {
- *dst = 0x7FFF;
- } else if (temp < -0x00008000) {
- *dst = -0x8000;
- } else {
- *dst = (LVM_INT16)temp;
- }
- dst++;
-
- temp = mVal - sVal;
-
- if (temp > 0x00007FFF) {
- *dst = 0x7FFF;
- } else if (temp < -0x00008000) {
- *dst = -0x8000;
- } else {
- *dst = (LVM_INT16)temp;
- }
- dst++;
- }
-
- return;
-}
void MSTo2i_Sat_Float(const LVM_FLOAT* srcM, const LVM_FLOAT* srcS, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_FLOAT temp, mVal, sVal;
LVM_INT16 ii;
@@ -73,28 +33,11 @@
srcS++;
temp = mVal + sVal;
-
- if (temp > 1.0f) {
- *dst = 1.0f;
- } else if (temp < -1.0f) {
- *dst = -1.0f;
- } else {
- *dst = (LVM_FLOAT)temp;
- }
- dst++;
+ *dst++ = LVM_Clamp(temp);
temp = mVal - sVal;
-
- if (temp > 1.0f) {
- *dst = 1.0f;
- } else if (temp < -1.0f) {
- *dst = -1.0f;
- } else {
- *dst = (LVM_FLOAT)temp;
- }
- dst++;
+ *dst++ = LVM_Clamp(temp);
}
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.cpp b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.cpp
deleted file mode 100644
index 1d450b0..0000000
--- a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
-
- %created_by: sra % (CM/S)
- %name: Mac3s_Sat_16x16.c % (CM/S)
- %version: 1 % (CM/S)
- %date_created: Fri Nov 13 12:07:13 2009 % (CM/S)
-
-***********************************************************************************/
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-#include "LVM_Macros.h"
-
-/**********************************************************************************
- FUNCTION Mac3S_16X16
-***********************************************************************************/
-
-void Mac3s_Sat_16x16(const LVM_INT16* src, const LVM_INT16 val, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- LVM_INT16 srcval;
- LVM_INT32 Temp, dInVal;
-
- for (ii = n; ii != 0; ii--) {
- srcval = *src;
- src++;
-
- Temp = (srcval * val) >> 15;
-
- dInVal = (LVM_INT32)*dst;
-
- Temp = Temp + dInVal;
-
- if (Temp > 0x00007FFF) {
- *dst = 0x7FFF;
- } else if (Temp < -0x00008000) {
- *dst = -0x8000;
- } else {
- *dst = (LVM_INT16)Temp;
- }
-
- dst++;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp
index 0fe9fef..24bdf3e 100644
--- a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp
@@ -18,66 +18,19 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
+#include "ScalarArithmetic.h"
#include "VectorArithmetic.h"
#include "LVM_Macros.h"
-/**********************************************************************************
- FUNCTION MAC3S_16X16
-***********************************************************************************/
-
-void Mac3s_Sat_32x16(const LVM_INT32* src, const LVM_INT16 val, LVM_INT32* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- LVM_INT32 srcval, temp, dInVal, dOutVal;
-
- for (ii = n; ii != 0; ii--) {
- srcval = *src;
- src++;
-
- MUL32x16INTO32(srcval, val, temp, 15)
-
- dInVal = *dst;
- dOutVal = temp + dInVal;
-
- if ((((dOutVal ^ temp) & (dOutVal ^ dInVal)) >> 31) != 0) /* overflow / underflow */
- {
- if (temp < 0) {
- dOutVal = 0x80000000L;
- } else {
- dOutVal = 0x7FFFFFFFL;
- }
- }
-
- *dst = dOutVal;
- dst++;
- }
-
- return;
-}
void Mac3s_Sat_Float(const LVM_FLOAT* src, const LVM_FLOAT val, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_INT16 ii;
- LVM_FLOAT srcval;
- LVM_FLOAT Temp, dInVal;
for (ii = n; ii != 0; ii--) {
- srcval = *src;
- src++;
+ LVM_FLOAT Temp = *src++ * val;
+ Temp += *dst;
- Temp = srcval * val;
-
- dInVal = (LVM_FLOAT)*dst;
- Temp = Temp + dInVal;
-
- if (Temp > 1.000000f) {
- *dst = 1.000000f;
- } else if (Temp < -1.000000f) {
- *dst = -1.000000f;
- } else {
- *dst = Temp;
- }
- dst++;
+ *dst++ = LVM_Clamp(Temp);
}
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.cpp b/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.cpp
deleted file mode 100644
index 7ab5d49..0000000
--- a/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION MonoTo2I_16
-***********************************************************************************/
-
-void MonoTo2I_16(const LVM_INT16* src, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- src += (n - 1);
- dst += ((n * 2) - 1);
-
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst--;
-
- *dst = *src;
- dst--;
- src--;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp
index 1ba669f..ef3e633 100644
--- a/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp
+++ b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp
@@ -21,26 +21,6 @@
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION MonoTo2I_32
-***********************************************************************************/
-
-void MonoTo2I_32(const LVM_INT32* src, LVM_INT32* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- src += (n - 1);
- dst += ((n * 2) - 1);
-
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst--;
-
- *dst = *src;
- dst--;
- src--;
- }
-
- return;
-}
void MonoTo2I_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_INT16 ii;
src += (n - 1);
@@ -57,4 +37,3 @@
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp
index 4589703..babfef3 100644
--- a/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp
@@ -22,26 +22,6 @@
#include "VectorArithmetic.h"
#include "LVM_Macros.h"
-/**********************************************************************************
-FUNCTION MULT3S_16X16
-***********************************************************************************/
-
-void Mult3s_32x16(const LVM_INT32* src, const LVM_INT16 val, LVM_INT32* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- LVM_INT32 srcval, temp;
-
- for (ii = n; ii != 0; ii--) {
- srcval = *src;
- src++;
-
- MUL32x16INTO32(srcval, val, temp, 15)
-
- * dst = temp;
- dst++;
- }
-
- return;
-}
void Mult3s_Float(const LVM_FLOAT* src, const LVM_FLOAT val, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_INT16 ii;
LVM_FLOAT temp;
@@ -54,4 +34,3 @@
}
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp
index fba0666..f3a1a67 100644
--- a/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp
@@ -61,43 +61,6 @@
/* */
/****************************************************************************************/
-void NonLinComp_D16(LVM_INT16 Gain, LVM_INT16* pDataIn, LVM_INT16* pDataOut,
- LVM_INT32 BlockLength) {
- LVM_INT16 Sample; /* Input samples */
- LVM_INT32 SampleNo; /* Sample index */
- LVM_INT16 Temp;
-
- /*
- * Process a block of samples
- */
- for (SampleNo = 0; SampleNo < BlockLength; SampleNo++) {
- /*
- * Read the input
- */
- Sample = *pDataIn;
- pDataIn++;
-
- /*
- * Apply the compander, this compresses the signal at the expense of
- * harmonic distortion. The amount of compression is control by the
- * gain factor
- */
- if ((LVM_INT32)Sample != -32768) {
- Temp = (LVM_INT16)((Sample * Sample) >> 15);
- if (Sample > 0) {
- Sample = (LVM_INT16)(Sample + ((Gain * (Sample - Temp)) >> 15));
- } else {
- Sample = (LVM_INT16)(Sample + ((Gain * (Sample + Temp)) >> 15));
- }
- }
-
- /*
- * Save the output
- */
- *pDataOut = Sample;
- pDataOut++;
- }
-}
void NonLinComp_Float(LVM_FLOAT Gain, LVM_FLOAT* pDataIn, LVM_FLOAT* pDataOut,
LVM_INT32 BlockLength) {
LVM_FLOAT Sample; /* Input samples */
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp
index 0afaad2..2a5540e 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp
@@ -15,102 +15,12 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A0,
- pBiquadState->coefs[1] is -B2,
- pBiquadState->coefs[2] is -B1, these are in Q14 format
- pBiquadState->coefs[3] is Gain, in Q11 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q0 format
- pBiquadState->pDelays[5] is y(n-1)R in Q0 format
- pBiquadState->pDelays[6] is y(n-2)L in Q0 format
- pBiquadState->pDelays[7] is y(n-2)R in Q0 format
-***************************************************************************/
-void PK_2I_D32F32C14G11_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL, ynR, ynLO, ynRO, templ;
- LVM_INT16 ii;
- PFilter_State_Float pBiquadState = (PFilter_State_Float)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- /* ynL= (A0 * (x(n)L - x(n-2)L ) )*/
- templ = (*pDataIn) - pBiquadState->pDelays[2];
- ynL = templ * pBiquadState->coefs[0];
-
- /* ynL+= ((-B2 * y(n-2)L )) */
- templ = pBiquadState->pDelays[6] * pBiquadState->coefs[1];
- ynL += templ;
-
- /* ynL+= ((-B1 * y(n-1)L ) ) */
- templ = pBiquadState->pDelays[4] * pBiquadState->coefs[2];
- ynL += templ;
-
- /* ynLO= ((Gain * ynL )) */
- ynLO = ynL * pBiquadState->coefs[3];
-
- /* ynLO=( ynLO + x(n)L )*/
- ynLO += (*pDataIn);
-
- /**************************************************************************
- PROCESSING OF THE RIGHT CHANNEL
- ***************************************************************************/
- /* ynR= (A0 * (x(n)R - x(n-2)R ) ) */
- templ = (*(pDataIn + 1)) - pBiquadState->pDelays[3];
- ynR = templ * pBiquadState->coefs[0];
-
- /* ynR+= ((-B2 * y(n-2)R ) ) */
- templ = pBiquadState->pDelays[7] * pBiquadState->coefs[1];
- ynR += templ;
-
- /* ynR+= ((-B1 * y(n-1)R ) ) */
- templ = pBiquadState->pDelays[5] * pBiquadState->coefs[2];
- ynR += templ;
-
- /* ynRO= ((Gain * ynR )) */
- ynRO = ynR * pBiquadState->coefs[3];
-
- /* ynRO=( ynRO + x(n)R )*/
- ynRO += (*(pDataIn + 1));
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
- pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
- pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
- pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
- pBiquadState->pDelays[5] = ynR; /* Update y(n-1)R */
- pBiquadState->pDelays[4] = ynL; /* Update y(n-1)L */
- pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L */
- pDataIn++;
- pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R */
- pDataIn++;
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut = ynLO; /* Write Left output*/
- pDataOut++;
- *pDataOut = ynRO; /* Write Right output*/
- pDataOut++;
- }
-}
-
-/**************************************************************************
DELAYS-
pBiquadState->pDelays[0] to
pBiquadState->pDelays[NrChannels - 1] is x(n-1) for all NrChannels
@@ -173,3 +83,4 @@
}
}
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h
index 3f5d332..7fcd33c 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#ifndef _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_
#define _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_
@@ -28,3 +29,4 @@
typedef Filter_State* PFilter_State;
#endif /* _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp
index 178d766..d782631 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#include "BIQUAD.h"
#include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
void PK_2I_D32F32CssGss_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
@@ -31,3 +32,4 @@
pBiquadState->coefs[3] = pCoef->G;
}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
index 57a1c16..4c9f069 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#ifndef BIQUAD_OPT
#ifndef _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_
#define _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_
@@ -35,3 +36,4 @@
typedef Filter_State* PFilter_State;
#endif /* _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/mult3s_16x16.cpp b/media/libeffects/lvm/lib/Common/src/mult3s_16x16.cpp
deleted file mode 100644
index 66f9132..0000000
--- a/media/libeffects/lvm/lib/Common/src/mult3s_16x16.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION MULT3S_16X16
-***********************************************************************************/
-
-void Mult3s_16x16(const LVM_INT16* src, const LVM_INT16 val, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- LVM_INT32 temp;
-
- for (ii = n; ii != 0; ii--) {
- temp = (LVM_INT32)(*src) * (LVM_INT32)val;
- src++;
-
- *dst = (LVM_INT16)(temp >> 15);
- dst++;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
index bccbe86..f4e625f 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
@@ -21,6 +21,9 @@
/* */
/****************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
#include "LVEQNB.h"
#include "LVEQNB_Private.h"
#include "VectorArithmetic.h"
@@ -179,6 +182,9 @@
LVM_UINT16 i; /* Filter band index */
LVEQNB_BiquadType_en BiquadType; /* Filter biquad type */
+#ifdef BIQUAD_OPT
+ pInstance->gain.resize(pInstance->Params.NBands);
+#endif
/*
* Set the coefficients for each band by the init function
*/
@@ -198,8 +204,19 @@
/*
* Set the coefficients
*/
+#ifdef BIQUAD_OPT
+ pInstance->gain[i] = Coefficients.G;
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coefficients.A0, 0.0, -(Coefficients.A0), -(Coefficients.B1),
+ -(Coefficients.B2)};
+ pInstance->eqBiquad[i]
+ .setCoefficients<
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(
+ coefs);
+#else
PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState_Float[i],
&pInstance->pEQNB_Taps_Float[i], &Coefficients);
+#endif
break;
}
default:
@@ -220,6 +237,11 @@
/* */
/************************************************************************************/
void LVEQNB_ClearFilterHistory(LVEQNB_Instance_t* pInstance) {
+#ifdef BIQUAD_OPT
+ for (size_t i = 0; i < pInstance->eqBiquad.size(); i++) {
+ pInstance->eqBiquad[i].clear();
+ }
+#else
LVM_FLOAT* pTapAddress;
LVM_INT16 NumTaps;
@@ -233,6 +255,7 @@
pTapAddress, /* Destination */
NumTaps); /* Number of words */
}
+#endif
}
/****************************************************************************************/
/* */
@@ -310,6 +333,16 @@
(OperatingModeSave == LVEQNB_ON && pInstance->bInOperatingModeTransition &&
LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0);
+#ifdef BIQUAD_OPT
+ /*
+ * Create biquad instance
+ */
+ pInstance->eqBiquad.resize(
+ pParams->NBands, android::audio_utils::BiquadFilter<LVM_FLOAT>(
+ (FCC_1 == pParams->NrChannels) ? FCC_2 : pParams->NrChannels));
+ LVEQNB_ClearFilterHistory(pInstance);
+#endif
+
if (bChange || modeChange) {
/*
* If the sample rate has changed clear the history
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
index 1d2a5f5..57df4db 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
@@ -62,6 +62,9 @@
pInstance->pScratch = pScratch;
/* Equaliser Biquad Instance */
+#ifdef BIQUAD_OPT
+ LVM_UINT32 MemSize = pCapabilities->MaxBands * sizeof(*(pInstance->pBandDefinitions));
+#else
LVM_UINT32 MemSize = pCapabilities->MaxBands * sizeof(*(pInstance->pEQNB_FilterState_Float));
pInstance->pEQNB_FilterState_Float = (Biquad_FLOAT_Instance_t*)calloc(1, MemSize);
if (pInstance->pEQNB_FilterState_Float == LVM_NULL) {
@@ -75,6 +78,7 @@
}
MemSize = (pCapabilities->MaxBands * sizeof(*(pInstance->pBandDefinitions)));
+#endif
pInstance->pBandDefinitions = (LVEQNB_BandDef_t*)calloc(1, MemSize);
if (pInstance->pBandDefinitions == LVM_NULL) {
return LVEQNB_NULLADDRESS;
@@ -105,10 +109,11 @@
*/
LVEQNB_SetFilters(pInstance, /* Set the filter types */
&pInstance->Params);
-
+#ifndef BIQUAD_OPT
LVEQNB_SetCoefficients(pInstance); /* Set the filter coefficients */
LVEQNB_ClearFilterHistory(pInstance); /* Clear the filter history */
+#endif
/*
* Initialise the bypass variables
@@ -154,6 +159,7 @@
}
pInstance = (LVEQNB_Instance_t*)*phInstance;
+#ifndef BIQUAD_OPT
/* Equaliser Biquad Instance */
if (pInstance->pEQNB_FilterState_Float != LVM_NULL) {
free(pInstance->pEQNB_FilterState_Float);
@@ -163,6 +169,7 @@
free(pInstance->pEQNB_Taps_Float);
pInstance->pEQNB_Taps_Float = LVM_NULL;
}
+#endif
if (pInstance->pBandDefinitions != LVM_NULL) {
free(pInstance->pBandDefinitions);
pInstance->pBandDefinitions = LVM_NULL;
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
index 83a3449..32bad29 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
@@ -24,6 +24,9 @@
/* */
/****************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
#include "LVEQNB.h" /* Calling or Application layer definitions */
#include "BIQUAD.h"
#include "LVC_Mixer.h"
@@ -69,8 +72,14 @@
/* Aligned memory pointers */
LVM_FLOAT* pFastTemporary; /* Fast temporary data base address */
+#ifdef BIQUAD_OPT
+ std::vector<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ eqBiquad; /* Biquad filter instances */
+ std::vector<LVM_FLOAT> gain; /* Gain values for all bands*/
+#else
Biquad_2I_Order2_FLOAT_Taps_t* pEQNB_Taps_Float; /* Equaliser Taps */
Biquad_FLOAT_Instance_t* pEQNB_FilterState_Float; /* State for each filter band */
+#endif
/* Filter definitions and call back */
LVM_UINT16 NBands; /* Number of bands */
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
index d2a26db..3f0be7c 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
@@ -104,19 +104,30 @@
* Check if band is non-zero dB gain
*/
if (pInstance->pBandDefinitions[i].Gain != 0) {
+#ifndef BIQUAD_OPT
/*
* Get the address of the biquad instance
*/
Biquad_FLOAT_Instance_t* pBiquad = &pInstance->pEQNB_FilterState_Float[i];
+#endif
/*
* Select single or double precision as required
*/
switch (pInstance->pBiquadType[i]) {
case LVEQNB_SinglePrecision_Float: {
+#ifdef BIQUAD_OPT
+ LVM_FLOAT* pTemp = pScratch + NrSamples;
+ pInstance->eqBiquad[i].process(pTemp, pScratch, NrFrames);
+ const auto gain = pInstance->gain[i];
+ for (unsigned j = 0; j < NrSamples; ++j) {
+ pScratch[j] += pTemp[j] * gain;
+ }
+#else
PK_Mc_D32F32C14G11_TRC_WRA_01(pBiquad, pScratch, pScratch,
(LVM_INT16)NrFrames,
(LVM_INT16)NrChannels);
+#endif
break;
}
default:
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
index 737ef01..a744339 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
@@ -20,6 +20,10 @@
/* Includes */
/* */
/****************************************************************************************/
+
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
#include "LVREV_Private.h"
#include "Filter.h"
@@ -71,10 +75,17 @@
Omega = LVM_GetOmega(pPrivate->NewParams.HPF, pPrivate->NewParams.SampleRate);
LVM_FO_HPF(Omega, &Coeffs);
+#ifdef BIQUAD_OPT
+ const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coeffs.A0, Coeffs.A1, 0.0, -(Coeffs.B1), 0.0};
+ pPrivate->pRevHPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->HPCoefs, &pPrivate->pFastData->HPTaps,
&Coeffs);
LoadConst_Float(0, (LVM_FLOAT*)&pPrivate->pFastData->HPTaps,
sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
+#endif
}
/*
@@ -99,10 +110,17 @@
LVM_FO_LPF(Omega, &Coeffs);
}
}
+#ifdef BIQUAD_OPT
+ const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coeffs.A0, Coeffs.A1, 0.0, -(Coeffs.B1), 0.0};
+ pPrivate->pRevLPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->LPCoefs, &pPrivate->pFastData->LPTaps,
&Coeffs);
LoadConst_Float(0, (LVM_FLOAT*)&pPrivate->pFastData->LPTaps,
sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
+#endif
}
/*
@@ -130,10 +148,6 @@
LVM_INT16 i;
LVM_FLOAT ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4,
LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
- LVM_INT16 MaxT_Delay[] = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, LVREV_MAX_T2_DELAY,
- LVREV_MAX_T3_DELAY};
- LVM_INT16 MaxAP_Delay[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY, LVREV_MAX_AP2_DELAY,
- LVREV_MAX_AP3_DELAY};
/*
* For each delay line
@@ -153,7 +167,7 @@
* Set the fixed delay
*/
- Temp = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 192000;
+ Temp = (LVREV_MAX_T_DELAY[i] - LVREV_MAX_AP_DELAY[i]) * Fs / 192000;
pPrivate->Delay_AP[i] = pPrivate->T[i] - Temp;
/*
@@ -231,8 +245,15 @@
Coeffs.A1 = 0;
Coeffs.B1 = 0;
}
+#ifdef BIQUAD_OPT
+ const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coeffs.A0, Coeffs.A1, 0.0, -(Coeffs.B1), 0.0};
+ pPrivate->revLPFBiquad[i].reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->RevLPCoefs[i],
&pPrivate->pFastData->RevLPTaps[i], &Coeffs);
+#endif
}
}
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
index 5c83ce5..61b3732 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
@@ -56,31 +56,20 @@
* Clear all filter tap data, delay-lines and other signal related data
*/
+#ifdef BIQUAD_OPT
+ pLVREV_Private->pRevHPFBiquad->clear();
+ pLVREV_Private->pRevLPFBiquad->clear();
+#else
LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->HPTaps, 2);
LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->LPTaps, 2);
- if ((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays == LVREV_DELAYLINES_4) {
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[3], 2);
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[2], 2);
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-
- LoadConst_Float(0, pLVREV_Private->pDelay_T[3], LVREV_MAX_T3_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[2], LVREV_MAX_T2_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
- }
-
- if ((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_2) {
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-
- LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
- }
-
- if ((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_1) {
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
+#endif
+ for (size_t i = 0; i < pLVREV_Private->InstanceParams.NumDelays; i++) {
+#ifdef BIQUAD_OPT
+ pLVREV_Private->revLPFBiquad[i]->clear();
+#else
+ LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[i], 2);
+#endif
+ LoadConst_Float(0, pLVREV_Private->pDelay_T[i], LVREV_MAX_T_DELAY[i]);
}
return LVREV_SUCCESS;
}
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
index b5db23b..fa96e52 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
@@ -120,11 +120,11 @@
pLVREV_Private->MemoryTable = *pMemoryTable;
if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
- MaxBlockSize = LVREV_MAX_AP3_DELAY;
+ MaxBlockSize = LVREV_MAX_AP_DELAY[3];
} else if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
- MaxBlockSize = LVREV_MAX_AP1_DELAY;
+ MaxBlockSize = LVREV_MAX_AP_DELAY[1];
} else {
- MaxBlockSize = LVREV_MAX_AP0_DELAY;
+ MaxBlockSize = LVREV_MAX_AP_DELAY[0];
}
if (MaxBlockSize > pInstanceParams->MaxBlockSize) {
@@ -134,69 +134,30 @@
/*
* Set the data, coefficient and temporary memory pointers
*/
+#ifndef BIQUAD_OPT
/* Fast data memory base address */
pLVREV_Private->pFastData =
(LVREV_FastData_st*)InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
- pLVREV_Private->pDelay_T[3] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_FLOAT));
- pLVREV_Private->pDelay_T[2] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_FLOAT));
- pLVREV_Private->pDelay_T[1] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
- pLVREV_Private->pDelay_T[0] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-
- for (i = 0; i < 4; i++) {
- /* Scratch for each delay line output */
- pLVREV_Private->pScratchDelayLine[i] =
- (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
- }
-
- LoadConst_Float(0, pLVREV_Private->pDelay_T[3], LVREV_MAX_T3_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[2], LVREV_MAX_T2_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
- }
-
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
- pLVREV_Private->pDelay_T[1] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
- pLVREV_Private->pDelay_T[0] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-
- for (i = 0; i < 2; i++) {
- /* Scratch for each delay line output */
- pLVREV_Private->pScratchDelayLine[i] =
- (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
- }
-
- LoadConst_Float(0, pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
- }
-
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_1) {
- pLVREV_Private->pDelay_T[0] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-
- for (i = 0; i < 1; i++) {
- /* Scratch for each delay line output */
- pLVREV_Private->pScratchDelayLine[i] =
- (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
- }
-
- LoadConst_Float(0, pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+#endif
+ for (size_t i = 0; i < pInstanceParams->NumDelays; i++) {
+ pLVREV_Private->pDelay_T[i] = (LVM_FLOAT*)InstAlloc_AddMember(
+ &FastData, LVREV_MAX_T_DELAY[i] * sizeof(LVM_FLOAT));
+ /* Scratch for each delay line output */
+ pLVREV_Private->pScratchDelayLine[i] =
+ (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
+ LoadConst_Float(0, pLVREV_Private->pDelay_T[i], LVREV_MAX_T_DELAY[i]);
}
/* All-pass delay buffer addresses and sizes */
- pLVREV_Private->T[0] = LVREV_MAX_T0_DELAY;
- pLVREV_Private->T[1] = LVREV_MAX_T1_DELAY;
- pLVREV_Private->T[2] = LVREV_MAX_T2_DELAY;
- pLVREV_Private->T[3] = LVREV_MAX_T3_DELAY;
+ for (size_t i = 0; i < LVREV_DELAYLINES_4; i++) {
+ pLVREV_Private->T[i] = LVREV_MAX_T_DELAY[i];
+ }
pLVREV_Private->AB_Selection = 1; /* Select smoothing A to B */
+#ifndef BIQUAD_OPT
/* Fast coefficient memory base address */
pLVREV_Private->pFastCoef =
(LVREV_FastCoef_st*)InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));
+#endif
/* General purpose scratch */
pLVREV_Private->pScratch =
(LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
@@ -299,14 +260,21 @@
pLVREV_Private->FeedbackMixer[i].Target = 0;
}
/* Delay tap index */
- pLVREV_Private->A_DelaySize[0] = LVREV_MAX_AP0_DELAY;
- pLVREV_Private->B_DelaySize[0] = LVREV_MAX_AP0_DELAY;
- pLVREV_Private->A_DelaySize[1] = LVREV_MAX_AP1_DELAY;
- pLVREV_Private->B_DelaySize[1] = LVREV_MAX_AP1_DELAY;
- pLVREV_Private->A_DelaySize[2] = LVREV_MAX_AP2_DELAY;
- pLVREV_Private->B_DelaySize[2] = LVREV_MAX_AP2_DELAY;
- pLVREV_Private->A_DelaySize[3] = LVREV_MAX_AP3_DELAY;
- pLVREV_Private->B_DelaySize[3] = LVREV_MAX_AP3_DELAY;
+ for (size_t i = 0; i < LVREV_DELAYLINES_4; i++) {
+ pLVREV_Private->A_DelaySize[i] = LVREV_MAX_AP_DELAY[i];
+ pLVREV_Private->B_DelaySize[i] = LVREV_MAX_AP_DELAY[i];
+ }
+
+#ifdef BIQUAD_OPT
+ pLVREV_Private->pRevHPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+ pLVREV_Private->pRevLPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+ for (int i = 0; i < LVREV_DELAYLINES_4; i++) {
+ pLVREV_Private->revLPFBiquad[i].reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+ }
+#endif
LVREV_ClearAudioBuffers(*phInstance);
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
index 2c1e04d..b344b20 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
@@ -63,7 +63,6 @@
INST_ALLOC FastData;
INST_ALLOC FastCoef;
INST_ALLOC Temporary;
- LVM_INT16 i;
LVM_UINT16 MaxBlockSize;
/*
@@ -117,11 +116,11 @@
* Select the maximum internal block size
*/
if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
- MaxBlockSize = LVREV_MAX_AP3_DELAY;
+ MaxBlockSize = LVREV_MAX_AP_DELAY[3];
} else if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
- MaxBlockSize = LVREV_MAX_AP1_DELAY;
+ MaxBlockSize = LVREV_MAX_AP_DELAY[1];
} else {
- MaxBlockSize = LVREV_MAX_AP0_DELAY;
+ MaxBlockSize = LVREV_MAX_AP_DELAY[0];
}
if (MaxBlockSize > pInstanceParams->MaxBlockSize) {
@@ -139,21 +138,11 @@
/*
* Persistent fast data memory
*/
+#ifndef BIQUAD_OPT
InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
- InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_FLOAT));
- InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_FLOAT));
- InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
- InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
- }
-
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
- InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
- InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
- }
-
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_1) {
- InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
+#endif
+ for (size_t i = 0; i < pInstanceParams->NumDelays; i++) {
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T_DELAY[i] * sizeof(LVM_FLOAT));
}
pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size = InstAlloc_GetTotal(&FastData);
@@ -163,7 +152,9 @@
/*
* Persistent fast coefficient memory
*/
+#ifndef BIQUAD_OPT
InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));
+#endif
pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size = InstAlloc_GetTotal(&FastCoef);
pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Type = LVM_PERSISTENT_FAST_COEF;
pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
@@ -175,25 +166,9 @@
InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
/* Mono->stereo input saved for end mix */
InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_FLOAT) * MaxBlockSize);
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
- for (i = 0; i < 4; i++) {
- /* A Scratch buffer for each delay line */
- InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
- }
- }
-
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
- for (i = 0; i < 2; i++) {
- /* A Scratch buffer for each delay line */
- InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
- }
- }
-
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_1) {
- for (i = 0; i < 1; i++) {
- /* A Scratch buffer for each delay line */
- InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
- }
+ for (size_t i = 0; i < pInstanceParams->NumDelays; i++) {
+ /* A Scratch buffer for each delay line */
+ InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
}
pMemoryTable->Region[LVM_TEMPORARY_FAST].Size = InstAlloc_GetTotal(&Temporary);
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
index b6edb03..c62ad1e 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
@@ -23,6 +23,10 @@
/* Includes */
/* */
/****************************************************************************************/
+
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
#include "LVREV.h"
#include "LVREV_Tables.h"
#include "BIQUAD.h"
@@ -101,21 +105,23 @@
/* */
/****************************************************************************************/
+#ifndef BIQUAD_OPT
/* Fast data structure */
typedef struct {
Biquad_1I_Order1_FLOAT_Taps_t HPTaps; /* High pass filter taps */
Biquad_1I_Order1_FLOAT_Taps_t LPTaps; /* Low pass filter taps */
- Biquad_1I_Order1_FLOAT_Taps_t RevLPTaps[4]; /* Reverb low pass filters taps */
-
+ Biquad_1I_Order1_FLOAT_Taps_t RevLPTaps[LVREV_DELAYLINES_4]; /* Reverb low pass filters taps */
} LVREV_FastData_st;
/* Fast coefficient structure */
typedef struct {
Biquad_FLOAT_Instance_t HPCoefs; /* High pass filter coefficients */
Biquad_FLOAT_Instance_t LPCoefs; /* Low pass filter coefficients */
- Biquad_FLOAT_Instance_t RevLPCoefs[4]; /* Reverb low pass filters coefficients */
-
+ Biquad_FLOAT_Instance_t
+ RevLPCoefs[LVREV_DELAYLINES_4]; /* Reverb low pass filters coefficients */
} LVREV_FastCoef_st;
+#endif
+
typedef struct {
/* General */
LVREV_InstanceParams_st InstanceParams; /* Initialisation time instance parameters */
@@ -134,30 +140,39 @@
processing */
/* Aligned memory pointers */
- LVREV_FastData_st* pFastData; /* Fast data memory base address */
- LVREV_FastCoef_st* pFastCoef; /* Fast coefficient memory base address */
- LVM_FLOAT* pScratchDelayLine[4]; /* Delay line scratch memory */
+#ifdef BIQUAD_OPT
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pRevHPFBiquad; /* Biquad filter instance for HPF */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pRevLPFBiquad; /* Biquad filter instance for LPF */
+ std::array<std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>, LVREV_DELAYLINES_4>
+ revLPFBiquad; /* Biquad filter instance for Reverb LPF */
+#else
+ LVREV_FastData_st* pFastData; /* Fast data memory base address */
+ LVREV_FastCoef_st* pFastCoef; /* Fast coefficient memory base address */
+#endif
+ LVM_FLOAT* pScratchDelayLine[LVREV_DELAYLINES_4]; /* Delay line scratch memory */
LVM_FLOAT* pScratch; /* Multi ussge scratch */
LVM_FLOAT* pInputSave; /* Reverb block input save for dry/wet
mixing*/
/* Feedback matrix */
- Mix_1St_Cll_FLOAT_t FeedbackMixer[4]; /* Mixer for Pop and Click Suppression \
+ Mix_1St_Cll_FLOAT_t FeedbackMixer[LVREV_DELAYLINES_4]; /* Mixer for Pop and Click Suppression \
caused by feedback Gain */
/* All-Pass Filter */
- LVM_INT32 T[4]; /* Maximum delay size of buffer */
- LVM_FLOAT* pDelay_T[4]; /* Pointer to delay buffers */
- LVM_INT32 Delay_AP[4]; /* Offset to AP delay buffer start */
+ LVM_INT32 T[LVREV_DELAYLINES_4]; /* Maximum delay size of buffer */
+ LVM_FLOAT* pDelay_T[LVREV_DELAYLINES_4]; /* Pointer to delay buffers */
+ LVM_INT32 Delay_AP[LVREV_DELAYLINES_4]; /* Offset to AP delay buffer start */
LVM_INT16 AB_Selection; /* Smooth from tap A to B when 1 \
otherwise B to A */
- LVM_INT32 A_DelaySize[4]; /* A delay length in samples */
- LVM_INT32 B_DelaySize[4]; /* B delay length in samples */
- LVM_FLOAT* pOffsetA[4]; /* Offset for the A delay tap */
- LVM_FLOAT* pOffsetB[4]; /* Offset for the B delay tap */
- Mix_2St_Cll_FLOAT_t Mixer_APTaps[4]; /* Smoothed AP delay mixer */
- Mix_1St_Cll_FLOAT_t Mixer_SGFeedback[4]; /* Smoothed SAfeedback gain */
- Mix_1St_Cll_FLOAT_t Mixer_SGFeedforward[4]; /* Smoothed AP feedforward gain */
+ LVM_INT32 A_DelaySize[LVREV_DELAYLINES_4]; /* A delay length in samples */
+ LVM_INT32 B_DelaySize[LVREV_DELAYLINES_4]; /* B delay length in samples */
+ LVM_FLOAT* pOffsetA[LVREV_DELAYLINES_4]; /* Offset for the A delay tap */
+ LVM_FLOAT* pOffsetB[LVREV_DELAYLINES_4]; /* Offset for the B delay tap */
+ Mix_2St_Cll_FLOAT_t Mixer_APTaps[LVREV_DELAYLINES_4]; /* Smoothed AP delay mixer */
+ Mix_1St_Cll_FLOAT_t Mixer_SGFeedback[LVREV_DELAYLINES_4]; /* Smoothed SAfeedback gain */
+ Mix_1St_Cll_FLOAT_t Mixer_SGFeedforward[LVREV_DELAYLINES_4]; /* Smoothed AP feedforward gain */
/* Output gain */
Mix_2St_Cll_FLOAT_t BypassMixer; /* Dry/wet mixer */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
index ed3b89c..e4f939f 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
@@ -204,11 +204,20 @@
/*
* High pass filter
*/
+#ifdef BIQUAD_OPT
+ pPrivate->pRevHPFBiquad->process(pTemp, pTemp, NumSamples);
+#else
FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->HPCoefs, pTemp, pTemp, (LVM_INT16)NumSamples);
+#endif
+
/*
* Low pass filter
*/
+#ifdef BIQUAD_OPT
+ pPrivate->pRevLPFBiquad->process(pTemp, pTemp, NumSamples);
+#else
FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->LPCoefs, pTemp, pTemp, (LVM_INT16)NumSamples);
+#endif
/*
* Process all delay lines
@@ -253,8 +262,12 @@
/*
* Low pass filter
*/
+#ifdef BIQUAD_OPT
+ pPrivate->revLPFBiquad[j]->process(pDelayLine, pDelayLine, NumSamples);
+#else
FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->RevLPCoefs[j], pDelayLine, pDelayLine,
(LVM_INT16)NumSamples);
+#endif
}
/*
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp
index 35a6522..bb6cf12 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp
@@ -29,6 +29,11 @@
/* */
/****************************************************************************************/
+const LVM_INT16 LVREV_MAX_T_DELAY[] = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, LVREV_MAX_T2_DELAY,
+ LVREV_MAX_T3_DELAY};
+const LVM_INT16 LVREV_MAX_AP_DELAY[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY,
+ LVREV_MAX_AP2_DELAY, LVREV_MAX_AP3_DELAY};
+
/* Table with supported sampling rates. The table can be indexed using LVM_Fs_en */
const LVM_UINT32 LVM_FsTable[] = {8000, 11025, 12000, 16000, 22050, 24000, 32000,
44100, 48000, 88200, 96000, 176400, 192000};
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
index 4b0dcca..723d1ff 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
@@ -35,6 +35,8 @@
extern LVM_UINT32 LVM_GetFsFromTable(LVM_Fs_en FsIndex);
extern const LVM_FLOAT LVREV_GainPolyTable[24][5];
+extern const LVM_INT16 LVREV_MAX_T_DELAY[];
+extern const LVM_INT16 LVREV_MAX_AP_DELAY[];
#endif /** _LVREV_TABLES_H_ **/
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp
index 4e90a42..436e7cb 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp
@@ -15,6 +15,9 @@
* limitations under the License.
*/
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
#include "LVPSA.h"
#include "LVPSA_Private.h"
#include "VectorArithmetic.h"
@@ -182,6 +185,13 @@
break;
}
}
+#ifdef BIQUAD_OPT
+ /*
+ * Create biquad instance
+ */
+ pInst->specBiquad.resize(pInst->nRelevantFilters,
+ android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1));
+#endif
LVPSA_SetBPFiltersType(pInst, &Params);
LVPSA_SetBPFCoefficients(pInst, &Params);
LVPSA_SetQPFCoefficients(pInst, &Params);
@@ -302,8 +312,18 @@
/*
* Set the coefficients
*/
+#ifdef BIQUAD_OPT
+ const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coefficients.A0, 0.0, -(Coefficients.A0), -(Coefficients.B1),
+ -(Coefficients.B2)};
+ pInst->specBiquad[ii]
+ .setCoefficients<
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(
+ coefs);
+#else
BP_1I_D16F32Cll_TRC_WRA_01_Init(&pInst->pBP_Instances[ii], &pInst->pBP_Taps[ii],
&Coefficients);
+#endif
break;
}
@@ -319,8 +339,18 @@
/*
* Set the coefficients
*/
+#ifdef BIQUAD_OPT
+ const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coefficients.A0, 0.0, -(Coefficients.A0), -(Coefficients.B1),
+ -(Coefficients.B2)};
+ pInst->specBiquad[ii]
+ .setCoefficients<
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(
+ coefs);
+#else
BP_1I_D16F16Css_TRC_WRA_01_Init(&pInst->pBP_Instances[ii], &pInst->pBP_Taps[ii],
&Coefficients);
+#endif
break;
}
}
@@ -604,6 +634,11 @@
/* */
/************************************************************************************/
LVPSA_RETURN LVPSA_ClearFilterHistory(LVPSA_InstancePr_t* pInst) {
+#ifdef BIQUAD_OPT
+ for (size_t i = 0; i < pInst->specBiquad.size(); i++) {
+ pInst->specBiquad[i].clear();
+ }
+#else
LVM_INT8* pTapAddress;
LVM_UINT32 i;
@@ -617,6 +652,7 @@
for (i = 0; i < pInst->nBands * sizeof(QPD_Taps_t); i++) {
pTapAddress[i] = 0;
}
+#endif
return (LVPSA_OK);
}
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp
index 9a2b29f..f77460b 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp
@@ -108,21 +108,25 @@
if (pLVPSA_Inst->pBPFiltersPrecision == LVM_NULL) {
return LVPSA_ERROR_NULLADDRESS;
}
+#ifndef BIQUAD_OPT
pLVPSA_Inst->pBP_Instances = (Biquad_FLOAT_Instance_t*)calloc(
pInitParams->nBands, sizeof(*(pLVPSA_Inst->pBP_Instances)));
if (pLVPSA_Inst->pBP_Instances == LVM_NULL) {
return LVPSA_ERROR_NULLADDRESS;
}
+#endif
pLVPSA_Inst->pQPD_States =
(QPD_FLOAT_State_t*)calloc(pInitParams->nBands, sizeof(*(pLVPSA_Inst->pQPD_States)));
if (pLVPSA_Inst->pQPD_States == LVM_NULL) {
return LVPSA_ERROR_NULLADDRESS;
}
+#ifndef BIQUAD_OPT
pLVPSA_Inst->pBP_Taps = (Biquad_1I_Order2_FLOAT_Taps_t*)calloc(
pInitParams->nBands, sizeof(*(pLVPSA_Inst->pBP_Taps)));
if (pLVPSA_Inst->pBP_Taps == LVM_NULL) {
return LVPSA_ERROR_NULLADDRESS;
}
+#endif
pLVPSA_Inst->pQPD_Taps =
(QPD_FLOAT_Taps_t*)calloc(pInitParams->nBands, sizeof(*(pLVPSA_Inst->pQPD_Taps)));
if (pLVPSA_Inst->pQPD_Taps == LVM_NULL) {
@@ -193,18 +197,22 @@
free(pLVPSA_Inst->pBPFiltersPrecision);
pLVPSA_Inst->pBPFiltersPrecision = LVM_NULL;
}
+#ifndef BIQUAD_OPT
if (pLVPSA_Inst->pBP_Instances != LVM_NULL) {
free(pLVPSA_Inst->pBP_Instances);
pLVPSA_Inst->pBP_Instances = LVM_NULL;
}
+#endif
if (pLVPSA_Inst->pQPD_States != LVM_NULL) {
free(pLVPSA_Inst->pQPD_States);
pLVPSA_Inst->pQPD_States = LVM_NULL;
}
+#ifndef BIQUAD_OPT
if (pLVPSA_Inst->pBP_Taps != LVM_NULL) {
free(pLVPSA_Inst->pBP_Taps);
pLVPSA_Inst->pBP_Taps = LVM_NULL;
}
+#endif
if (pLVPSA_Inst->pQPD_Taps != LVM_NULL) {
free(pLVPSA_Inst->pQPD_Taps);
pLVPSA_Inst->pQPD_Taps = LVM_NULL;
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
index e00c11c..553156f 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
@@ -18,6 +18,9 @@
#ifndef _LVPSA_PRIVATE_H_
#define _LVPSA_PRIVATE_H_
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
#include "LVPSA.h"
#include "BIQUAD.h"
#include "LVPSA_QPD.h"
@@ -82,9 +85,14 @@
LVPSA_BPFilterPrecision_en* pBPFiltersPrecision; /* Points a nBands elements array that contains
the filter precision for each band */
+#ifdef BIQUAD_OPT
+ std::vector<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ specBiquad; /* Biquad filter instances */
+#else
Biquad_FLOAT_Instance_t* pBP_Instances;
/* Points a nBands elements array that contains the band pass filter taps for each band */
Biquad_1I_Order2_FLOAT_Taps_t* pBP_Taps;
+#endif
/* Points a nBands elements array that contains the QPD filter instance for each band */
QPD_FLOAT_State_t* pQPD_States;
/* Points a nBands elements array that contains the QPD filter taps for each band */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp
index 299dfd2..148b21f 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp
@@ -96,13 +96,23 @@
for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++) {
switch (pLVPSA_Inst->pBPFiltersPrecision[ii]) {
case LVPSA_SimplePrecisionFilter:
+#ifdef BIQUAD_OPT
+ pLVPSA_Inst->specBiquad[ii].process(pScratch + InputBlockSize, pScratch,
+ (LVM_INT16)InputBlockSize);
+#else
BP_1I_D16F16C14_TRC_WRA_01(&pLVPSA_Inst->pBP_Instances[ii], pScratch,
pScratch + InputBlockSize, (LVM_INT16)InputBlockSize);
+#endif
break;
case LVPSA_DoublePrecisionFilter:
+#ifdef BIQUAD_OPT
+ pLVPSA_Inst->specBiquad[ii].process(pScratch + InputBlockSize, pScratch,
+ (LVM_INT16)InputBlockSize);
+#else
BP_1I_D16F32C30_TRC_WRA_01(&pLVPSA_Inst->pBP_Instances[ii], pScratch,
pScratch + InputBlockSize, (LVM_INT16)InputBlockSize);
+#endif
break;
default:
break;
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
index bad9aef..a5952fb 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
@@ -21,6 +21,9 @@
/* */
/************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
#include "LVCS.h"
#include "LVCS_Private.h"
#include "LVCS_Equaliser.h"
@@ -56,14 +59,18 @@
LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t hInstance, LVCS_Params_t* pParams) {
LVM_UINT16 Offset;
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
+#ifndef BIQUAD_OPT
LVCS_Equaliser_t* pConfig = (LVCS_Equaliser_t*)&pInstance->Equaliser;
LVCS_Data_t* pData;
LVCS_Coefficient_t* pCoefficients;
BQ_FLOAT_Coefs_t Coeffs;
+#endif
const BiquadA012B12CoefsSP_t* pEqualiserCoefTable;
+#ifndef BIQUAD_OPT
pData = (LVCS_Data_t*)pInstance->pData;
pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
/*
* If the sample rate changes re-initialise the filters
*/
@@ -75,6 +82,13 @@
Offset = (LVM_UINT16)(pParams->SampleRate + (pParams->SpeakerType * (1 + LVM_FS_48000)));
pEqualiserCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_EqualiserCoefTable[0];
+#ifdef BIQUAD_OPT
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ pEqualiserCoefTable[Offset].A0, pEqualiserCoefTable[Offset].A1,
+ pEqualiserCoefTable[Offset].A2, -(pEqualiserCoefTable[Offset].B1),
+ -(pEqualiserCoefTable[Offset].B2)};
+ pInstance->pEqBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_2, coefs));
+#else
/* Left and right filters */
/* Convert incoming coefficients to the required format/ordering */
Coeffs.A0 = (LVM_FLOAT)pEqualiserCoefTable[Offset].A0;
@@ -103,6 +117,7 @@
pConfig->pBiquadCallBack = BQ_2I_D16F32C15_TRC_WRA_01;
break;
}
+#endif
}
return (LVCS_SUCCESS);
@@ -129,19 +144,25 @@
LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t hInstance, LVM_FLOAT* pInputOutput,
LVM_UINT16 NumSamples) {
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
+#ifndef BIQUAD_OPT
LVCS_Equaliser_t* pConfig = (LVCS_Equaliser_t*)&pInstance->Equaliser;
LVCS_Coefficient_t* pCoefficients;
pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
/*
* Check if the equaliser is required
*/
if ((pInstance->Params.OperatingMode & LVCS_EQUALISERSWITCH) != 0) {
/* Apply filter to the left and right channels */
+#ifdef BIQUAD_OPT
+ pInstance->pEqBiquad->process(pInputOutput, pInputOutput, NumSamples);
+#else
(pConfig->pBiquadCallBack)(
(Biquad_FLOAT_Instance_t*)&pCoefficients->EqualiserBiquadInstance,
(LVM_FLOAT*)pInputOutput, (LVM_FLOAT*)pInputOutput, (LVM_INT16)NumSamples);
+#endif
}
return (LVCS_SUCCESS);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
index c0d0950..18b350d 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
@@ -23,12 +23,12 @@
/* Structures */
/* */
/************************************************************************************/
-
+#ifndef BIQUAD_OPT
/* Equaliser structure */
typedef struct {
void (*pBiquadCallBack)(Biquad_FLOAT_Instance_t*, LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
} LVCS_Equaliser_t;
-
+#endif
/************************************************************************************/
/* */
/* Function prototypes */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
index 5c8f1ae..f23261f 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
@@ -123,6 +123,7 @@
if (pInstance == LVM_NULL) {
return;
}
+#ifndef BIQUAD_OPT
if (pInstance->pCoeff != LVM_NULL) {
free(pInstance->pCoeff);
pInstance->pCoeff = LVM_NULL;
@@ -131,6 +132,7 @@
free(pInstance->pData);
pInstance->pData = LVM_NULL;
}
+#endif
free(pInstance);
*phInstance = LVM_NULL;
return;
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
index f9c23b3..605a204 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
@@ -33,6 +33,9 @@
/* */
/************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
#include "LVCS.h" /* Calling or Application layer definitions */
#include "LVCS_StereoEnhancer.h" /* Stereo enhancer module definitions */
#include "LVCS_ReverbGenerator.h" /* Reverberation module definitions */
@@ -110,7 +113,9 @@
/* Sub-block configurations */
LVCS_StereoEnhancer_t StereoEnhancer; /* Stereo enhancer configuration */
LVCS_ReverbGenerator_t Reverberation; /* Reverberation configuration */
+#ifndef BIQUAD_OPT
LVCS_Equaliser_t Equaliser; /* Equaliser configuration */
+#endif
LVCS_BypassMix_t BypassMix; /* Bypass mixer configuration */
/* Bypass variable */
@@ -120,12 +125,24 @@
LVM_INT16 bTimerDone; /* Timer completion flag */
LVM_Timer_Params_t TimerParams; /* Timer parameters */
LVM_Timer_Instance_t TimerInstance; /* Timer instance */
+#ifdef BIQUAD_OPT
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pEqBiquad; /* Biquad filter instance for Equaliser */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pRevBiquad; /* Biquad filter instance for Reverberation */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pSEMidBiquad; /* Biquad filter instance for Stereo enhancement mid */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pSESideBiquad; /* Biquad filter instance for Stereo enhancement side */
+#else
void* pCoeff; /* pointer to buffer for equaliser filter coeffs */
void* pData; /* pointer to buffer for equaliser filter states */
+#endif
void* pScratch; /* Pointer to bundle scratch buffer */
} LVCS_Instance_t;
+#ifndef BIQUAD_OPT
/* Coefficient Structure */
typedef struct {
Biquad_FLOAT_Instance_t EqualiserBiquadInstance;
@@ -141,6 +158,7 @@
Biquad_1I_Order1_FLOAT_Taps_t SEBiquadTapsMid;
Biquad_1I_Order2_FLOAT_Taps_t SEBiquadTapsSide;
} LVCS_Data_t;
+#endif
void LVCS_TimerCallBack(void* hInstance, void* pCallBackParams, LVM_INT32 CallbackParam);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
index f6d2453..82a3a43 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
@@ -20,6 +20,9 @@
/* Includes */
/* */
/************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
#include <stdlib.h>
#include "LVCS.h"
#include "LVCS_Private.h"
@@ -62,11 +65,14 @@
LVM_UINT16 Offset;
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
LVCS_ReverbGenerator_t* pConfig = (LVCS_ReverbGenerator_t*)&pInstance->Reverberation;
+#ifndef BIQUAD_OPT
LVCS_Data_t* pData;
LVCS_Coefficient_t* pCoefficients;
BQ_FLOAT_Coefs_t Coeffs;
+#endif
const BiquadA012B12CoefsSP_t* pReverbCoefTable;
+#ifndef BIQUAD_OPT
if (pInstance->pData == LVM_NULL) {
pInstance->pData = pData = (LVCS_Data_t*)calloc(1, sizeof(*pData));
if (pData == LVM_NULL) {
@@ -83,6 +89,7 @@
} else {
pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
}
+#endif
/*
* Initialise the delay and filters if:
@@ -109,6 +116,14 @@
Offset = (LVM_UINT16)pParams->SampleRate;
pReverbCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_ReverbCoefTable[0];
+#ifdef BIQUAD_OPT
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ pReverbCoefTable[Offset].A0, pReverbCoefTable[Offset].A1,
+ pReverbCoefTable[Offset].A2, -(pReverbCoefTable[Offset].B1),
+ -(pReverbCoefTable[Offset].B2)};
+ pInstance->pRevBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_2, coefs));
+#else
/* Convert incoming coefficients to the required format/ordering */
Coeffs.A0 = (LVM_FLOAT)pReverbCoefTable[Offset].A0;
Coeffs.A1 = (LVM_FLOAT)pReverbCoefTable[Offset].A1;
@@ -133,6 +148,7 @@
pConfig->pBiquadCallBack = BQ_2I_D16F16C15_TRC_WRA_01;
break;
}
+#endif
/*
* Setup the mixer
@@ -190,10 +206,14 @@
LVM_FLOAT* pOutData, LVM_UINT16 NumSamples) {
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
LVCS_ReverbGenerator_t* pConfig = (LVCS_ReverbGenerator_t*)&pInstance->Reverberation;
+#ifndef BIQUAD_OPT
LVCS_Coefficient_t* pCoefficients;
+#endif
LVM_FLOAT* pScratch;
+#ifndef BIQUAD_OPT
pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
pScratch = (LVM_FLOAT*)pInstance->pScratch;
/*
@@ -233,9 +253,13 @@
/*
* Filter the data
*/
+#ifdef BIQUAD_OPT
+ pInstance->pRevBiquad->process(pScratch, pScratch, NumSamples);
+#else
(pConfig->pBiquadCallBack)((Biquad_FLOAT_Instance_t*)&pCoefficients->ReverbBiquadInstance,
(LVM_FLOAT*)pScratch, (LVM_FLOAT*)pScratch,
(LVM_INT16)NumSamples);
+#endif
Mult3s_Float((LVM_FLOAT*)pScratch, pConfig->ReverbLevel, (LVM_FLOAT*)pScratch,
(LVM_INT16)(2 * NumSamples));
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
index b666da3..a200267 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
@@ -51,8 +51,10 @@
LVM_FLOAT StereoSamples[2 * LVCS_STEREODELAY_CS_MAX_VAL];
/* Reverb Level */
LVM_FLOAT ReverbLevel;
+#ifndef BIQUAD_OPT
/* Filter */
void (*pBiquadCallBack)(Biquad_FLOAT_Instance_t*, LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
+#endif
} LVCS_ReverbGenerator_t;
/************************************************************************************/
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
index ffa9c9b..0e488f5 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
@@ -21,6 +21,9 @@
/* */
/************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
#include "LVCS.h"
#include "LVCS_Private.h"
#include "LVCS_StereoEnhancer.h"
@@ -52,15 +55,19 @@
LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t hInstance, LVCS_Params_t* pParams) {
LVM_UINT16 Offset;
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
+#ifndef BIQUAD_OPT
LVCS_StereoEnhancer_t* pConfig = (LVCS_StereoEnhancer_t*)&pInstance->StereoEnhancer;
LVCS_Data_t* pData;
LVCS_Coefficient_t* pCoefficient;
FO_FLOAT_Coefs_t CoeffsMid;
BQ_FLOAT_Coefs_t CoeffsSide;
+#endif
const BiquadA012B12CoefsSP_t* pSESideCoefs;
+#ifndef BIQUAD_OPT
pData = (LVCS_Data_t*)pInstance->pData;
pCoefficient = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
/*
* If the sample rate or speaker type has changed update the filters
@@ -73,6 +80,13 @@
/* Mid filter */
Offset = (LVM_UINT16)pParams->SampleRate;
+#ifdef BIQUAD_OPT
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ LVCS_SEMidCoefTable[Offset].A0, LVCS_SEMidCoefTable[Offset].A1, 0.0,
+ -(LVCS_SEMidCoefTable[Offset].B1), 0.0};
+ pInstance->pSEMidBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
/* Convert incoming coefficients to the required format/ordering */
CoeffsMid.A0 = (LVM_FLOAT)LVCS_SEMidCoefTable[Offset].A0;
CoeffsMid.A1 = (LVM_FLOAT)LVCS_SEMidCoefTable[Offset].A1;
@@ -91,11 +105,18 @@
if (LVCS_SEMidCoefTable[Offset].Scale == 15) {
pConfig->pBiquadCallBack_Mid = FO_1I_D16F16C15_TRC_WRA_01;
}
+#endif
Offset = (LVM_UINT16)(pParams->SampleRate);
pSESideCoefs = (BiquadA012B12CoefsSP_t*)&LVCS_SESideCoefTable[0];
/* Side filter */
+#ifdef BIQUAD_OPT
+ coefs = {pSESideCoefs[Offset].A0, pSESideCoefs[Offset].A1, pSESideCoefs[Offset].A2,
+ -(pSESideCoefs[Offset].B1), -(pSESideCoefs[Offset].B2)};
+ pInstance->pSESideBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
/* Convert incoming coefficients to the required format/ordering */
CoeffsSide.A0 = (LVM_FLOAT)pSESideCoefs[Offset].A0;
CoeffsSide.A1 = (LVM_FLOAT)pSESideCoefs[Offset].A1;
@@ -123,6 +144,7 @@
pConfig->pBiquadCallBack_Side = BQ_1I_D16F16C15_TRC_WRA_01;
break;
}
+#endif
}
return (LVCS_SUCCESS);
@@ -169,9 +191,13 @@
LVM_FLOAT* pOutData, LVM_UINT16 NumSamples) {
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
LVCS_StereoEnhancer_t* pConfig = (LVCS_StereoEnhancer_t*)&pInstance->StereoEnhancer;
+#ifndef BIQUAD_OPT
LVCS_Coefficient_t* pCoefficient;
+#endif
LVM_FLOAT* pScratch;
+#ifndef BIQUAD_OPT
pCoefficient = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
pScratch = (LVM_FLOAT*)pInstance->pScratch;
/*
* Check if the Stereo Enhancer is enabled
@@ -186,9 +212,13 @@
* Apply filter to the middle signal
*/
if (pInstance->OutputDevice == LVCS_HEADPHONE) {
+#ifdef BIQUAD_OPT
+ pInstance->pSEMidBiquad->process(pScratch, pScratch, NumSamples);
+#else
(pConfig->pBiquadCallBack_Mid)(
(Biquad_FLOAT_Instance_t*)&pCoefficient->SEBiquadInstanceMid,
(LVM_FLOAT*)pScratch, (LVM_FLOAT*)pScratch, (LVM_INT16)NumSamples);
+#endif
} else {
Mult3s_Float(pScratch, /* Source */
(LVM_FLOAT)pConfig->MidGain, /* Gain */
@@ -201,10 +231,15 @@
* and in all modes for mobile speakers
*/
if (pInstance->Params.SourceFormat == LVCS_STEREO) {
+#ifdef BIQUAD_OPT
+ pInstance->pSESideBiquad->process(pScratch + NumSamples, pScratch + NumSamples,
+ NumSamples);
+#else
(pConfig->pBiquadCallBack_Side)(
(Biquad_FLOAT_Instance_t*)&pCoefficient->SEBiquadInstanceSide,
(LVM_FLOAT*)(pScratch + NumSamples), (LVM_FLOAT*)(pScratch + NumSamples),
(LVM_INT16)NumSamples);
+#endif
}
/*
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
index c92f8a5..a083c47 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
@@ -36,6 +36,7 @@
/* Stereo enhancer structure */
typedef struct {
+#ifndef BIQUAD_OPT
/*
* Middle filter
*/
@@ -45,6 +46,7 @@
* Side filter
*/
void (*pBiquadCallBack_Side)(Biquad_FLOAT_Instance_t*, LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
+#endif
LVM_FLOAT MidGain; /* Middle gain in mobile speaker mode */
} LVCS_StereoEnhancer_t;
diff --git a/media/libeffects/lvm/tests/Android.bp b/media/libeffects/lvm/tests/Android.bp
index d026ab6..abacc94 100644
--- a/media/libeffects/lvm/tests/Android.bp
+++ b/media/libeffects/lvm/tests/Android.bp
@@ -59,9 +59,12 @@
shared_libs: [
"libaudioutils",
"liblog",
- "libreverbwrapper",
],
+ static_libs: [
+ "libreverb",
+ "libreverbwrapper",
+ ],
srcs: [
"reverb_test.cpp",
],
diff --git a/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh b/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
index a97acc9..7b0ff5e 100755
--- a/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
+++ b/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
@@ -23,7 +23,7 @@
echo "========================================"
echo "testing lvm"
adb shell mkdir -p $testdir
-adb push $ANDROID_BUILD_TOP/cts/tests/tests/media/res/raw/sinesweepraw.raw $testdir
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/libeffects/res/raw/sinesweepraw.raw $testdir
adb push $OUT/testcases/snr/arm64/snr $testdir
E_VAL=1
@@ -91,7 +91,7 @@
do
for fs in ${fs_arr[*]}
do
- for chMask in {0..22}
+ for chMask in {0..38}
do
adb shell $testdir/lvmtest -i:$testdir/sinesweepraw.raw \
-o:$testdir/sinesweep_$((chMask))_$((fs)).raw -chMask:$chMask -fs:$fs $flags
diff --git a/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh b/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh
index 0c3b0b5..72b370e 100755
--- a/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh
+++ b/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh
@@ -23,7 +23,7 @@
echo "========================================"
echo "testing reverb"
adb shell mkdir -p $testdir
-adb push $ANDROID_BUILD_TOP/cts/tests/tests/media/res/raw/sinesweepraw.raw $testdir
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/libeffects/res/raw/sinesweepraw.raw $testdir
E_VAL=1
cmds="adb push $OUT/testcases/reverb_test/arm/reverb_test $testdir"
@@ -59,9 +59,9 @@
do
for fs in ${fs_arr[*]}
do
- for chMask in {0..22}
+ for chMask in {0..38}
do
- adb shell LD_LIBRARY_PATH=/system/vendor/lib/soundfx $testdir/reverb_test \
+ adb shell $testdir/reverb_test \
--input $testdir/sinesweepraw.raw \
--output $testdir/sinesweep_$((chMask))_$((fs)).raw \
--chMask $chMask $flags --fs $fs --preset $preset_val
diff --git a/media/libeffects/lvm/tests/lvmtest.cpp b/media/libeffects/lvm/tests/lvmtest.cpp
index 5c5f646..f107b18 100644
--- a/media/libeffects/lvm/tests/lvmtest.cpp
+++ b/media/libeffects/lvm/tests/lvmtest.cpp
@@ -109,6 +109,22 @@
AUDIO_CHANNEL_OUT_5POINT1POINT2,
AUDIO_CHANNEL_OUT_7POINT1,
AUDIO_CHANNEL_INDEX_MASK_8,
+ AUDIO_CHANNEL_INDEX_MASK_9,
+ AUDIO_CHANNEL_INDEX_MASK_10,
+ AUDIO_CHANNEL_INDEX_MASK_11,
+ AUDIO_CHANNEL_INDEX_MASK_12,
+ AUDIO_CHANNEL_INDEX_MASK_13,
+ AUDIO_CHANNEL_INDEX_MASK_14,
+ AUDIO_CHANNEL_INDEX_MASK_15,
+ AUDIO_CHANNEL_INDEX_MASK_16,
+ AUDIO_CHANNEL_INDEX_MASK_17,
+ AUDIO_CHANNEL_INDEX_MASK_18,
+ AUDIO_CHANNEL_INDEX_MASK_19,
+ AUDIO_CHANNEL_INDEX_MASK_20,
+ AUDIO_CHANNEL_INDEX_MASK_21,
+ AUDIO_CHANNEL_INDEX_MASK_22,
+ AUDIO_CHANNEL_INDEX_MASK_23,
+ AUDIO_CHANNEL_INDEX_MASK_24,
};
void printUsage() {
@@ -394,7 +410,7 @@
params->SourceFormat = LVM_MONO;
} else if (params->NrChannels == 2) {
params->SourceFormat = LVM_STEREO;
- } else if (params->NrChannels > 2 && params->NrChannels <= 8) { // FCC_2 FCC_8
+ } else if (params->NrChannels > FCC_2 && params->NrChannels <= FCC_24) {
params->SourceFormat = LVM_MULTICHANNEL;
} else {
return -EINVAL;
diff --git a/media/libeffects/lvm/tests/reverb_test.cpp b/media/libeffects/lvm/tests/reverb_test.cpp
index 7cbca9b..cecc975 100644
--- a/media/libeffects/lvm/tests/reverb_test.cpp
+++ b/media/libeffects/lvm/tests/reverb_test.cpp
@@ -94,6 +94,22 @@
AUDIO_CHANNEL_OUT_5POINT1POINT2,
AUDIO_CHANNEL_OUT_7POINT1,
AUDIO_CHANNEL_INDEX_MASK_8,
+ AUDIO_CHANNEL_INDEX_MASK_9,
+ AUDIO_CHANNEL_INDEX_MASK_10,
+ AUDIO_CHANNEL_INDEX_MASK_11,
+ AUDIO_CHANNEL_INDEX_MASK_12,
+ AUDIO_CHANNEL_INDEX_MASK_13,
+ AUDIO_CHANNEL_INDEX_MASK_14,
+ AUDIO_CHANNEL_INDEX_MASK_15,
+ AUDIO_CHANNEL_INDEX_MASK_16,
+ AUDIO_CHANNEL_INDEX_MASK_17,
+ AUDIO_CHANNEL_INDEX_MASK_18,
+ AUDIO_CHANNEL_INDEX_MASK_19,
+ AUDIO_CHANNEL_INDEX_MASK_20,
+ AUDIO_CHANNEL_INDEX_MASK_21,
+ AUDIO_CHANNEL_INDEX_MASK_22,
+ AUDIO_CHANNEL_INDEX_MASK_23,
+ AUDIO_CHANNEL_INDEX_MASK_24,
};
constexpr int kReverbConfigChMaskCount = std::size(kReverbConfigChMask);
@@ -340,7 +356,7 @@
const int outChannelCount = (channelCount == 1 ? 2 : channelCount);
std::vector<short> in(frameLength * maxChannelCount);
- std::vector<short> out(frameLength * maxChannelCount);
+ std::vector<short> out(frameLength * outChannelCount);
std::vector<float> floatIn(frameLength * channelCount);
std::vector<float> floatOut(frameLength * outChannelCount);
diff --git a/media/libeffects/lvm/wrapper/Android.bp b/media/libeffects/lvm/wrapper/Android.bp
index be60aae..f96928b 100644
--- a/media/libeffects/lvm/wrapper/Android.bp
+++ b/media/libeffects/lvm/wrapper/Android.bp
@@ -38,7 +38,7 @@
}
// reverb wrapper
-cc_library_shared {
+cc_library {
name: "libreverbwrapper",
arch: {
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 670b415..865baad 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -1021,6 +1021,16 @@
ActiveParams.NrChannels = NrChannels;
ActiveParams.ChMask = pConfig->inputCfg.channels;
+ if (NrChannels == 1) {
+ ActiveParams.SourceFormat = LVM_MONO;
+ } else if (NrChannels == 2) {
+ ActiveParams.SourceFormat = LVM_STEREO;
+ } else if (NrChannels > 2 && NrChannels <= LVM_MAX_CHANNELS) {
+ ActiveParams.SourceFormat = LVM_MULTICHANNEL;
+ } else {
+ return -EINVAL;
+ }
+
LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "Effect_setConfig")
diff --git a/media/libeffects/preprocessing/Android.bp b/media/libeffects/preprocessing/Android.bp
index 5217cf9..681e247 100644
--- a/media/libeffects/preprocessing/Android.bp
+++ b/media/libeffects/preprocessing/Android.bp
@@ -1,35 +1,5 @@
// audio preprocessing wrapper
cc_library_shared {
- name: "libaudiopreprocessing_legacy",
-
- vendor: true,
-
- relative_install_path: "soundfx",
-
- srcs: ["PreProcessing.cpp"],
-
- shared_libs: [
- "libwebrtc_audio_preprocessing",
- "libspeexresampler",
- "libutils",
- "liblog",
- ],
-
- cflags: [
- "-DWEBRTC_POSIX",
- "-DWEBRTC_LEGACY",
- "-fvisibility=hidden",
- "-Wall",
- "-Werror",
- ],
-
- header_libs: [
- "libaudioeffects",
- "libhardware_headers",
- ],
-}
-
-cc_library_shared {
name: "libaudiopreprocessing",
vendor: true,
relative_install_path: "soundfx",
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 1a5547b..03ccc34 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -23,15 +23,10 @@
#include <hardware/audio_effect.h>
#include <utils/Log.h>
#include <utils/Timers.h>
-#ifndef WEBRTC_LEGACY
#include <audio_effects/effect_agc2.h>
-#endif
#include <audio_effects/effect_ns.h>
#include <audio_processing.h>
#include <module_common_types.h>
-#ifdef WEBRTC_LEGACY
-#include "speex/speex_resampler.h"
-#endif
// undefine to perform multi channels API functional tests
//#define DUAL_MIC_TEST
@@ -46,9 +41,7 @@
// types of pre processing modules
enum preproc_id {
PREPROC_AGC, // Automatic Gain Control
-#ifndef WEBRTC_LEGACY
PREPROC_AGC2, // Automatic Gain Control 2
-#endif
PREPROC_AEC, // Acoustic Echo Canceler
PREPROC_NS, // Noise Suppressor
PREPROC_NUM_EFFECTS
@@ -110,10 +103,8 @@
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)
-#ifndef WEBRTC_LEGACY
// Audio Processing module builder
webrtc::AudioProcessingBuilder ap_builder;
-#endif
size_t apmFrameCount; // buffer size for webRTC process (10 ms)
uint32_t apmSamplingRate; // webRTC APM sampling rate (8/16 or 32 kHz)
size_t frameCount; // buffer size before input resampler ( <=> apmFrameCount)
@@ -124,42 +115,25 @@
uint32_t enabledMsk; // bit field containing IDs of enabled pre processors
uint32_t processedMsk; // bit field containing IDs of pre processors already
// processed in current round
-#ifdef WEBRTC_LEGACY
- webrtc::AudioFrame* procFrame; // audio frame passed to webRTC AMP ProcessStream()
-#else
// audio config strucutre
webrtc::AudioProcessing::Config config;
webrtc::StreamConfig inputConfig; // input stream configuration
webrtc::StreamConfig outputConfig; // output stream configuration
-#endif
int16_t* inBuf; // input buffer used when resampling
size_t inBufSize; // input buffer size in frames
size_t framesIn; // number of frames in input buffer
-#ifdef WEBRTC_LEGACY
- SpeexResamplerState* inResampler; // handle on input speex resampler
-#endif
int16_t* outBuf; // output buffer used when resampling
size_t outBufSize; // output buffer size in frames
size_t framesOut; // number of frames in output buffer
-#ifdef WEBRTC_LEGACY
- SpeexResamplerState* outResampler; // handle on output speex resampler
-#endif
uint32_t revChannelCount; // number of channels on reverse stream
uint32_t revEnabledMsk; // bit field containing IDs of enabled pre processors
// with reverse channel
uint32_t revProcessedMsk; // bit field containing IDs of pre processors with reverse
// channel already processed in current round
-#ifdef WEBRTC_LEGACY
- webrtc::AudioFrame* revFrame; // audio frame passed to webRTC AMP AnalyzeReverseStream()
-#else
webrtc::StreamConfig revConfig; // reverse stream configuration.
-#endif
int16_t* revBuf; // reverse channel input buffer
size_t revBufSize; // reverse channel input buffer size
size_t framesRev; // number of frames in reverse channel input buffer
-#ifdef WEBRTC_LEGACY
- SpeexResamplerState* revResampler; // handle on reverse channel input speex resampler
-#endif
};
#ifdef DUAL_MIC_TEST
@@ -213,7 +187,6 @@
"Automatic Gain Control",
"The Android Open Source Project"};
-#ifndef WEBRTC_LEGACY
// Automatic Gain Control 2
static const effect_descriptor_t sAgc2Descriptor = {
{0xae3c653b, 0xbe18, 0x4ab8, 0x8938, {0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac}}, // type
@@ -224,7 +197,6 @@
0, // FIXME indicate memory usage
"Automatic Gain Control 2",
"The Android Open Source Project"};
-#endif
// Acoustic Echo Cancellation
static const effect_descriptor_t sAecDescriptor = {
@@ -249,9 +221,7 @@
"The Android Open Source Project"};
static const effect_descriptor_t* sDescriptors[PREPROC_NUM_EFFECTS] = {&sAgcDescriptor,
-#ifndef WEBRTC_LEGACY
&sAgc2Descriptor,
-#endif
&sAecDescriptor,
&sNsDescriptor};
@@ -260,9 +230,7 @@
//------------------------------------------------------------------------------
const effect_uuid_t* const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {FX_IID_AGC,
-#ifndef WEBRTC_LEGACY
FX_IID_AGC2,
-#endif
FX_IID_AEC, FX_IID_NS};
const effect_uuid_t* ProcIdToUuid(int procId) {
@@ -297,7 +265,6 @@
static const int kAgcDefaultCompGain = 9;
static const bool kAgcDefaultLimiter = true;
-#ifndef WEBRTC_LEGACY
int Agc2Init(preproc_effect_t* effect) {
ALOGV("Agc2Init");
effect->session->config = effect->session->apm->GetConfig();
@@ -308,48 +275,27 @@
effect->session->apm->ApplyConfig(effect->session->config);
return 0;
}
-#endif
int AgcInit(preproc_effect_t* effect) {
ALOGV("AgcInit");
-#ifdef WEBRTC_LEGACY
- webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
- agc->set_mode(webrtc::GainControl::kFixedDigital);
- agc->set_target_level_dbfs(kAgcDefaultTargetLevel);
- agc->set_compression_gain_db(kAgcDefaultCompGain);
- agc->enable_limiter(kAgcDefaultLimiter);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
effect->session->config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
effect->session->config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
return 0;
}
-#ifndef WEBRTC_LEGACY
int Agc2Create(preproc_effect_t* effect) {
Agc2Init(effect);
return 0;
}
-#endif
int AgcCreate(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- webrtc::GainControl* agc = effect->session->apm->gain_control();
- ALOGV("AgcCreate got agc %p", agc);
- if (agc == NULL) {
- ALOGW("AgcCreate Error");
- return -ENOMEM;
- }
- effect->engine = static_cast<preproc_fx_handle_t>(agc);
-#endif
AgcInit(effect);
return 0;
}
-#ifndef WEBRTC_LEGACY
int Agc2GetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
int status = 0;
uint32_t param = *(uint32_t*)pParam;
@@ -422,15 +368,11 @@
return status;
}
-#endif
int AgcGetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
int status = 0;
uint32_t param = *(uint32_t*)pParam;
t_agc_settings* pProperties = (t_agc_settings*)pValue;
-#ifdef WEBRTC_LEGACY
- webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
-#endif
switch (param) {
case AGC_PARAM_TARGET_LEVEL:
@@ -459,32 +401,6 @@
break;
}
-#ifdef WEBRTC_LEGACY
- switch (param) {
- case AGC_PARAM_TARGET_LEVEL:
- *(int16_t*)pValue = (int16_t)(agc->target_level_dbfs() * -100);
- ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t*)pValue);
- break;
- case AGC_PARAM_COMP_GAIN:
- *(int16_t*)pValue = (int16_t)(agc->compression_gain_db() * 100);
- ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t*)pValue);
- break;
- case AGC_PARAM_LIMITER_ENA:
- *(bool*)pValue = (bool)agc->is_limiter_enabled();
- ALOGV("AgcGetParameter() limiter enabled %s",
- (*(int16_t*)pValue != 0) ? "true" : "false");
- break;
- case AGC_PARAM_PROPERTIES:
- pProperties->targetLevel = (int16_t)(agc->target_level_dbfs() * -100);
- pProperties->compGain = (int16_t)(agc->compression_gain_db() * 100);
- pProperties->limiterEnabled = (bool)agc->is_limiter_enabled();
- break;
- default:
- ALOGW("AgcGetParameter() unknown param %d", param);
- status = -EINVAL;
- break;
- }
-#else
effect->session->config = effect->session->apm->GetConfig();
switch (param) {
case AGC_PARAM_TARGET_LEVEL:
@@ -515,11 +431,9 @@
status = -EINVAL;
break;
}
-#endif
return status;
}
-#ifndef WEBRTC_LEGACY
int Agc2SetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
int status = 0;
uint32_t param = *(uint32_t*)pParam;
@@ -567,43 +481,9 @@
return status;
}
-#endif
int AgcSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
int status = 0;
-#ifdef WEBRTC_LEGACY
- uint32_t param = *(uint32_t*)pParam;
- t_agc_settings* pProperties = (t_agc_settings*)pValue;
- webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
-
- switch (param) {
- case AGC_PARAM_TARGET_LEVEL:
- ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t*)pValue);
- status = agc->set_target_level_dbfs(-(*(int16_t*)pValue / 100));
- break;
- case AGC_PARAM_COMP_GAIN:
- ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t*)pValue);
- status = agc->set_compression_gain_db(*(int16_t*)pValue / 100);
- break;
- case AGC_PARAM_LIMITER_ENA:
- ALOGV("AgcSetParameter() limiter enabled %s", *(bool*)pValue ? "true" : "false");
- status = agc->enable_limiter(*(bool*)pValue);
- break;
- case AGC_PARAM_PROPERTIES:
- ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
- pProperties->targetLevel, pProperties->compGain, pProperties->limiterEnabled);
- status = agc->set_target_level_dbfs(-(pProperties->targetLevel / 100));
- if (status != 0) break;
- status = agc->set_compression_gain_db(pProperties->compGain / 100);
- if (status != 0) break;
- status = agc->enable_limiter(pProperties->limiterEnabled);
- break;
- default:
- ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
- status = -EINVAL;
- break;
- }
-#else
uint32_t param = *(uint32_t*)pParam;
t_agc_settings* pProperties = (t_agc_settings*)pValue;
effect->session->config = effect->session->apm->GetConfig();
@@ -637,96 +517,57 @@
break;
}
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
ALOGV("AgcSetParameter() done status %d", status);
return status;
}
-#ifndef WEBRTC_LEGACY
void Agc2Enable(preproc_effect_t* effect) {
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller2.enabled = true;
effect->session->apm->ApplyConfig(effect->session->config);
}
-#endif
void AgcEnable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
- ALOGV("AgcEnable agc %p", agc);
- agc->Enable(true);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller1.enabled = true;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
-#ifndef WEBRTC_LEGACY
void Agc2Disable(preproc_effect_t* effect) {
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller2.enabled = false;
effect->session->apm->ApplyConfig(effect->session->config);
}
-#endif
void AgcDisable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- ALOGV("AgcDisable");
- webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
- agc->Enable(false);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller1.enabled = false;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
static const preproc_ops_t sAgcOps = {AgcCreate, AgcInit, NULL, AgcEnable, AgcDisable,
AgcSetParameter, AgcGetParameter, NULL};
-#ifndef WEBRTC_LEGACY
static const preproc_ops_t sAgc2Ops = {Agc2Create, Agc2Init, NULL,
Agc2Enable, Agc2Disable, Agc2SetParameter,
Agc2GetParameter, NULL};
-#endif
//------------------------------------------------------------------------------
// Acoustic Echo Canceler (AEC)
//------------------------------------------------------------------------------
-#ifdef WEBRTC_LEGACY
-static const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode =
- webrtc::EchoControlMobile::kEarpiece;
-static const bool kAecDefaultComfortNoise = true;
-#endif
int AecInit(preproc_effect_t* effect) {
ALOGV("AecInit");
-#ifdef WEBRTC_LEGACY
- webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
- aec->set_routing_mode(kAecDefaultMode);
- aec->enable_comfort_noise(kAecDefaultComfortNoise);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.echo_canceller.mobile_mode = true;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
return 0;
}
int AecCreate(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- webrtc::EchoControlMobile* aec = effect->session->apm->echo_control_mobile();
- ALOGV("AecCreate got aec %p", aec);
- if (aec == NULL) {
- ALOGW("AgcCreate Error");
- return -ENOMEM;
- }
- effect->engine = static_cast<preproc_fx_handle_t>(aec);
-#endif
AecInit(effect);
return 0;
}
@@ -744,13 +585,11 @@
*(uint32_t*)pValue = 1000 * effect->session->apm->stream_delay_ms();
ALOGV("AecGetParameter() echo delay %d us", *(uint32_t*)pValue);
break;
-#ifndef WEBRTC_LEGACY
case AEC_PARAM_MOBILE_MODE:
effect->session->config = effect->session->apm->GetConfig();
*(uint32_t*)pValue = effect->session->config.echo_canceller.mobile_mode;
ALOGV("AecGetParameter() mobile mode %d us", *(uint32_t*)pValue);
break;
-#endif
default:
ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
status = -EINVAL;
@@ -770,14 +609,12 @@
status = effect->session->apm->set_stream_delay_ms(value / 1000);
ALOGV("AecSetParameter() echo delay %d us, status %d", value, status);
break;
-#ifndef WEBRTC_LEGACY
case AEC_PARAM_MOBILE_MODE:
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.echo_canceller.mobile_mode = value;
ALOGV("AecSetParameter() mobile mode %d us", value);
effect->session->apm->ApplyConfig(effect->session->config);
break;
-#endif
default:
ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
status = -EINVAL;
@@ -787,57 +624,24 @@
}
void AecEnable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
- ALOGV("AecEnable aec %p", aec);
- aec->Enable(true);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.echo_canceller.enabled = true;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
void AecDisable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- ALOGV("AecDisable");
- webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
- aec->Enable(false);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.echo_canceller.enabled = false;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
int AecSetDevice(preproc_effect_t* effect, uint32_t device) {
ALOGV("AecSetDevice %08x", device);
-#ifdef WEBRTC_LEGACY
- webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
- webrtc::EchoControlMobile::RoutingMode mode =
- webrtc::EchoControlMobile::kQuietEarpieceOrHeadset;
-#endif
if (audio_is_input_device(device)) {
return 0;
}
-#ifdef WEBRTC_LEGACY
- switch (device) {
- case AUDIO_DEVICE_OUT_EARPIECE:
- mode = webrtc::EchoControlMobile::kEarpiece;
- break;
- case AUDIO_DEVICE_OUT_SPEAKER:
- mode = webrtc::EchoControlMobile::kSpeakerphone;
- break;
- case AUDIO_DEVICE_OUT_WIRED_HEADSET:
- case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
- case AUDIO_DEVICE_OUT_USB_HEADSET:
- default:
- break;
- }
- aec->set_routing_mode(mode);
-#endif
return 0;
}
@@ -849,49 +653,19 @@
// Noise Suppression (NS)
//------------------------------------------------------------------------------
-#ifdef WEBRTC_LEGACY
-static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate;
-#else
static const webrtc::AudioProcessing::Config::NoiseSuppression::Level kNsDefaultLevel =
webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
-#endif
int NsInit(preproc_effect_t* effect) {
ALOGV("NsInit");
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
- ns->set_level(kNsDefaultLevel);
- webrtc::Config config;
- std::vector<webrtc::Point> geometry;
- // TODO(aluebs): Make the geometry settable.
- geometry.push_back(webrtc::Point(-0.03f, 0.f, 0.f));
- geometry.push_back(webrtc::Point(-0.01f, 0.f, 0.f));
- geometry.push_back(webrtc::Point(0.01f, 0.f, 0.f));
- geometry.push_back(webrtc::Point(0.03f, 0.f, 0.f));
- // The geometry needs to be set with Beamforming enabled.
- config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
- effect->session->apm->SetExtraOptions(config);
- config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry));
- effect->session->apm->SetExtraOptions(config);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.noise_suppression.level = kNsDefaultLevel;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
effect->type = NS_TYPE_SINGLE_CHANNEL;
return 0;
}
int NsCreate(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression* ns = effect->session->apm->noise_suppression();
- ALOGV("NsCreate got ns %p", ns);
- if (ns == NULL) {
- ALOGW("AgcCreate Error");
- return -ENOMEM;
- }
- effect->engine = static_cast<preproc_fx_handle_t>(ns);
-#endif
NsInit(effect);
return 0;
}
@@ -904,31 +678,6 @@
int NsSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
int status = 0;
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
- uint32_t param = *(uint32_t*)pParam;
- uint32_t value = *(uint32_t*)pValue;
- switch (param) {
- case NS_PARAM_LEVEL:
- ns->set_level((webrtc::NoiseSuppression::Level)value);
- ALOGV("NsSetParameter() level %d", value);
- break;
- case NS_PARAM_TYPE: {
- webrtc::Config config;
- std::vector<webrtc::Point> geometry;
- bool is_beamforming_enabled = value == NS_TYPE_MULTI_CHANNEL && ns->is_enabled();
- config.Set<webrtc::Beamforming>(
- new webrtc::Beamforming(is_beamforming_enabled, geometry));
- effect->session->apm->SetExtraOptions(config);
- effect->type = value;
- ALOGV("NsSetParameter() type %d", value);
- break;
- }
- default:
- ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
- status = -EINVAL;
- }
-#else
uint32_t param = *(uint32_t*)pParam;
uint32_t value = *(uint32_t*)pValue;
effect->session->config = effect->session->apm->GetConfig();
@@ -943,52 +692,28 @@
status = -EINVAL;
}
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
return status;
}
void NsEnable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
- ALOGV("NsEnable ns %p", ns);
- ns->Enable(true);
- if (effect->type == NS_TYPE_MULTI_CHANNEL) {
- webrtc::Config config;
- std::vector<webrtc::Point> geometry;
- config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
- effect->session->apm->SetExtraOptions(config);
- }
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.noise_suppression.enabled = true;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
void NsDisable(preproc_effect_t* effect) {
ALOGV("NsDisable");
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
- ns->Enable(false);
- webrtc::Config config;
- std::vector<webrtc::Point> geometry;
- config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry));
- effect->session->apm->SetExtraOptions(config);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.noise_suppression.enabled = false;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
static const preproc_ops_t sNsOps = {NsCreate, NsInit, NULL, NsEnable,
NsDisable, NsSetParameter, NsGetParameter, NULL};
static const preproc_ops_t* sPreProcOps[PREPROC_NUM_EFFECTS] = {&sAgcOps,
-#ifndef WEBRTC_LEGACY
&sAgc2Ops,
-#endif
&sAecOps, &sNsOps};
//------------------------------------------------------------------------------
@@ -1119,9 +844,6 @@
session->id = 0;
session->io = 0;
session->createdMsk = 0;
-#ifdef WEBRTC_LEGACY
- session->apm = NULL;
-#endif
for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
status = Effect_Init(&session->effects[i], i);
}
@@ -1135,75 +857,32 @@
ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
if (session->createdMsk == 0) {
-#ifdef WEBRTC_LEGACY
- session->apm = webrtc::AudioProcessing::Create();
- if (session->apm == NULL) {
- ALOGW("Session_CreateEffect could not get apm engine");
- goto error;
- }
- const webrtc::ProcessingConfig processing_config = {
- {{kPreprocDefaultSr, kPreProcDefaultCnl},
- {kPreprocDefaultSr, kPreProcDefaultCnl},
- {kPreprocDefaultSr, kPreProcDefaultCnl},
- {kPreprocDefaultSr, kPreProcDefaultCnl}}};
- session->apm->Initialize(processing_config);
- session->procFrame = new webrtc::AudioFrame();
- if (session->procFrame == NULL) {
- ALOGW("Session_CreateEffect could not allocate audio frame");
- goto error;
- }
- session->revFrame = new webrtc::AudioFrame();
- if (session->revFrame == NULL) {
- ALOGW("Session_CreateEffect could not allocate reverse audio frame");
- goto error;
- }
-#else
session->apm = session->ap_builder.Create();
if (session->apm == NULL) {
ALOGW("Session_CreateEffect could not get apm engine");
goto error;
}
-#endif
session->apmSamplingRate = kPreprocDefaultSr;
session->apmFrameCount = (kPreprocDefaultSr) / 100;
session->frameCount = session->apmFrameCount;
session->samplingRate = kPreprocDefaultSr;
session->inChannelCount = kPreProcDefaultCnl;
session->outChannelCount = kPreProcDefaultCnl;
-#ifdef WEBRTC_LEGACY
- session->procFrame->sample_rate_hz_ = kPreprocDefaultSr;
- session->procFrame->num_channels_ = kPreProcDefaultCnl;
-#else
session->inputConfig.set_sample_rate_hz(kPreprocDefaultSr);
session->inputConfig.set_num_channels(kPreProcDefaultCnl);
session->outputConfig.set_sample_rate_hz(kPreprocDefaultSr);
session->outputConfig.set_num_channels(kPreProcDefaultCnl);
-#endif
session->revChannelCount = kPreProcDefaultCnl;
-#ifdef WEBRTC_LEGACY
- session->revFrame->sample_rate_hz_ = kPreprocDefaultSr;
- session->revFrame->num_channels_ = kPreProcDefaultCnl;
-#else
session->revConfig.set_sample_rate_hz(kPreprocDefaultSr);
session->revConfig.set_num_channels(kPreProcDefaultCnl);
-#endif
session->enabledMsk = 0;
session->processedMsk = 0;
session->revEnabledMsk = 0;
session->revProcessedMsk = 0;
-#ifdef WEBRTC_LEGACY
- session->inResampler = NULL;
-#endif
session->inBuf = NULL;
session->inBufSize = 0;
-#ifdef WEBRTC_LEGACY
- session->outResampler = NULL;
-#endif
session->outBuf = NULL;
session->outBufSize = 0;
-#ifdef WEBRTC_LEGACY
- session->revResampler = NULL;
-#endif
session->revBuf = NULL;
session->revBufSize = 0;
}
@@ -1217,17 +896,8 @@
error:
if (session->createdMsk == 0) {
-#ifdef WEBRTC_LEGACY
- delete session->revFrame;
- session->revFrame = NULL;
- delete session->procFrame;
- session->procFrame = NULL;
- delete session->apm;
- session->apm = NULL; // NOLINT(clang-analyzer-cplusplus.NewDelete)
-#else
delete session->apm;
session->apm = NULL;
-#endif
}
return status;
}
@@ -1236,29 +906,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) {
-#ifdef WEBRTC_LEGACY
delete session->apm;
session->apm = NULL;
- delete session->procFrame;
- session->procFrame = NULL;
- delete session->revFrame;
- session->revFrame = NULL;
- if (session->inResampler != NULL) {
- speex_resampler_destroy(session->inResampler);
- session->inResampler = NULL;
- }
- if (session->outResampler != NULL) {
- speex_resampler_destroy(session->outResampler);
- session->outResampler = NULL;
- }
- if (session->revResampler != NULL) {
- speex_resampler_destroy(session->revResampler);
- session->revResampler = NULL;
- }
-#else
- delete session->apm;
- session->apm = NULL;
-#endif
delete session->inBuf;
session->inBuf = NULL;
delete session->outBuf;
@@ -1284,9 +933,6 @@
ALOGV("Session_SetConfig sr %d cnl %08x", config->inputCfg.samplingRate,
config->inputCfg.channels);
-#ifdef WEBRTC_LEGACY
- int status;
-#endif
// AEC implementation is limited to 16kHz
if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
@@ -1297,51 +943,25 @@
session->apmSamplingRate = 8000;
}
-#ifdef WEBRTC_LEGACY
- const webrtc::ProcessingConfig processing_config = {
- {{static_cast<int>(session->apmSamplingRate), inCnl},
- {static_cast<int>(session->apmSamplingRate), outCnl},
- {static_cast<int>(session->apmSamplingRate), inCnl},
- {static_cast<int>(session->apmSamplingRate), inCnl}}};
- status = session->apm->Initialize(processing_config);
- if (status < 0) {
- return -EINVAL;
- }
-#endif
session->samplingRate = config->inputCfg.samplingRate;
session->apmFrameCount = session->apmSamplingRate / 100;
if (session->samplingRate == session->apmSamplingRate) {
session->frameCount = session->apmFrameCount;
} else {
-#ifdef WEBRTC_LEGACY
- session->frameCount =
- (session->apmFrameCount * session->samplingRate) / session->apmSamplingRate + 1;
-#else
session->frameCount =
(session->apmFrameCount * session->samplingRate) / session->apmSamplingRate;
-#endif
}
session->inChannelCount = inCnl;
session->outChannelCount = outCnl;
-#ifdef WEBRTC_LEGACY
- session->procFrame->num_channels_ = inCnl;
- session->procFrame->sample_rate_hz_ = session->apmSamplingRate;
-#else
session->inputConfig.set_sample_rate_hz(session->samplingRate);
session->inputConfig.set_num_channels(inCnl);
session->outputConfig.set_sample_rate_hz(session->samplingRate);
session->outputConfig.set_num_channels(inCnl);
-#endif
session->revChannelCount = inCnl;
-#ifdef WEBRTC_LEGACY
- session->revFrame->num_channels_ = inCnl;
- session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
-#else
session->revConfig.set_sample_rate_hz(session->samplingRate);
session->revConfig.set_num_channels(inCnl);
-#endif
// force process buffer reallocation
session->inBufSize = 0;
@@ -1349,53 +969,6 @@
session->framesIn = 0;
session->framesOut = 0;
-#ifdef WEBRTC_LEGACY
- if (session->inResampler != NULL) {
- speex_resampler_destroy(session->inResampler);
- session->inResampler = NULL;
- }
- if (session->outResampler != NULL) {
- speex_resampler_destroy(session->outResampler);
- session->outResampler = NULL;
- }
- if (session->revResampler != NULL) {
- speex_resampler_destroy(session->revResampler);
- session->revResampler = NULL;
- }
- if (session->samplingRate != session->apmSamplingRate) {
- int error;
- session->inResampler =
- speex_resampler_init(session->inChannelCount, session->samplingRate,
- session->apmSamplingRate, RESAMPLER_QUALITY, &error);
- if (session->inResampler == NULL) {
- ALOGW("Session_SetConfig Cannot create speex resampler: %s",
- speex_resampler_strerror(error));
- return -EINVAL;
- }
- session->outResampler =
- speex_resampler_init(session->outChannelCount, session->apmSamplingRate,
- session->samplingRate, RESAMPLER_QUALITY, &error);
- if (session->outResampler == NULL) {
- ALOGW("Session_SetConfig Cannot create speex resampler: %s",
- speex_resampler_strerror(error));
- speex_resampler_destroy(session->inResampler);
- session->inResampler = NULL;
- return -EINVAL;
- }
- session->revResampler =
- speex_resampler_init(session->inChannelCount, session->samplingRate,
- session->apmSamplingRate, RESAMPLER_QUALITY, &error);
- if (session->revResampler == NULL) {
- ALOGW("Session_SetConfig Cannot create speex resampler: %s",
- speex_resampler_strerror(error));
- speex_resampler_destroy(session->inResampler);
- session->inResampler = NULL;
- speex_resampler_destroy(session->outResampler);
- session->outResampler = NULL;
- return -EINVAL;
- }
- }
-#endif
session->state = PREPROC_SESSION_STATE_CONFIG;
return 0;
@@ -1430,22 +1003,7 @@
return -EINVAL;
}
uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels);
-#ifdef WEBRTC_LEGACY
- const webrtc::ProcessingConfig processing_config = {
- {{static_cast<int>(session->apmSamplingRate), session->inChannelCount},
- {static_cast<int>(session->apmSamplingRate), session->outChannelCount},
- {static_cast<int>(session->apmSamplingRate), inCnl},
- {static_cast<int>(session->apmSamplingRate), inCnl}}};
- int status = session->apm->Initialize(processing_config);
- if (status < 0) {
- return -EINVAL;
- }
-#endif
session->revChannelCount = inCnl;
-#ifdef WEBRTC_LEGACY
- session->revFrame->num_channels_ = inCnl;
- session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
-#endif
// force process buffer reallocation
session->revBufSize = 0;
session->framesRev = 0;
@@ -1467,24 +1025,10 @@
if (enabled) {
if (session->enabledMsk == 0) {
session->framesIn = 0;
-#ifdef WEBRTC_LEGACY
- if (session->inResampler != NULL) {
- speex_resampler_reset_mem(session->inResampler);
- }
- session->framesOut = 0;
- if (session->outResampler != NULL) {
- speex_resampler_reset_mem(session->outResampler);
- }
-#endif
}
session->enabledMsk |= (1 << procId);
if (HasReverseStream(procId)) {
session->framesRev = 0;
-#ifdef WEBRTC_LEGACY
- if (session->revResampler != NULL) {
- speex_resampler_reset_mem(session->revResampler);
- }
-#endif
session->revEnabledMsk |= (1 << procId);
}
} else {
@@ -1600,82 +1144,6 @@
return 0;
}
-#ifdef WEBRTC_LEGACY
- if (session->inResampler != NULL) {
- size_t fr = session->frameCount - session->framesIn;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- if (session->inBufSize < session->framesIn + fr) {
- int16_t* buf;
- session->inBufSize = session->framesIn + fr;
- buf = (int16_t*)realloc(
- session->inBuf,
- session->inBufSize * session->inChannelCount * sizeof(int16_t));
- if (buf == NULL) {
- session->framesIn = 0;
- free(session->inBuf);
- session->inBuf = NULL;
- return -ENOMEM;
- }
- session->inBuf = buf;
- }
- memcpy(session->inBuf + session->framesIn * session->inChannelCount, inBuffer->s16,
- fr * session->inChannelCount * sizeof(int16_t));
-#ifdef DUAL_MIC_TEST
- pthread_mutex_lock(&gPcmDumpLock);
- if (gPcmDumpFh != NULL) {
- fwrite(inBuffer->raw, fr * session->inChannelCount * sizeof(int16_t), 1,
- gPcmDumpFh);
- }
- pthread_mutex_unlock(&gPcmDumpLock);
-#endif
-
- session->framesIn += fr;
- inBuffer->frameCount = fr;
- if (session->framesIn < session->frameCount) {
- return 0;
- }
- spx_uint32_t frIn = session->framesIn;
- spx_uint32_t frOut = session->apmFrameCount;
- if (session->inChannelCount == 1) {
- speex_resampler_process_int(session->inResampler, 0, session->inBuf, &frIn,
- session->procFrame->data_, &frOut);
- } else {
- speex_resampler_process_interleaved_int(session->inResampler, session->inBuf, &frIn,
- session->procFrame->data_, &frOut);
- }
- memmove(session->inBuf, session->inBuf + frIn * session->inChannelCount,
- (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t));
- session->framesIn -= frIn;
- } else {
- size_t fr = session->frameCount - session->framesIn;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- memcpy(session->procFrame->data_ + session->framesIn * session->inChannelCount,
- inBuffer->s16, fr * session->inChannelCount * sizeof(int16_t));
-
-#ifdef DUAL_MIC_TEST
- pthread_mutex_lock(&gPcmDumpLock);
- if (gPcmDumpFh != NULL) {
- fwrite(inBuffer->raw, fr * session->inChannelCount * sizeof(int16_t), 1,
- gPcmDumpFh);
- }
- pthread_mutex_unlock(&gPcmDumpLock);
-#endif
-
- session->framesIn += fr;
- inBuffer->frameCount = fr;
- if (session->framesIn < session->frameCount) {
- return 0;
- }
- session->framesIn = 0;
- }
- session->procFrame->samples_per_channel_ = session->apmFrameCount;
-
- effect->session->apm->ProcessStream(session->procFrame);
-#else
size_t fr = session->frameCount - session->framesIn;
if (inBuffer->frameCount < fr) {
fr = inBuffer->frameCount;
@@ -1696,7 +1164,6 @@
return status;
}
outBuffer->frameCount = inBuffer->frameCount;
-#endif
if (session->outBufSize < session->framesOut + session->frameCount) {
int16_t* buf;
@@ -1713,30 +1180,7 @@
session->outBuf = buf;
}
-#ifdef WEBRTC_LEGACY
- if (session->outResampler != NULL) {
- spx_uint32_t frIn = session->apmFrameCount;
- spx_uint32_t frOut = session->frameCount;
- if (session->inChannelCount == 1) {
- speex_resampler_process_int(
- session->outResampler, 0, session->procFrame->data_, &frIn,
- session->outBuf + session->framesOut * session->outChannelCount, &frOut);
- } else {
- speex_resampler_process_interleaved_int(
- session->outResampler, session->procFrame->data_, &frIn,
- session->outBuf + session->framesOut * session->outChannelCount, &frOut);
- }
- session->framesOut += frOut;
- } else {
- memcpy(session->outBuf + session->framesOut * session->outChannelCount,
- session->procFrame->data_,
- session->frameCount * session->outChannelCount * sizeof(int16_t));
- session->framesOut += session->frameCount;
- }
- size_t fr = session->framesOut;
-#else
fr = session->framesOut;
-#endif
if (framesRq - framesWr < fr) {
fr = framesRq - framesWr;
}
@@ -2129,63 +1573,6 @@
if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
effect->session->revProcessedMsk = 0;
-#ifdef WEBRTC_LEGACY
- if (session->revResampler != NULL) {
- size_t fr = session->frameCount - session->framesRev;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- if (session->revBufSize < session->framesRev + fr) {
- int16_t* buf;
- session->revBufSize = session->framesRev + fr;
- buf = (int16_t*)realloc(
- session->revBuf,
- session->revBufSize * session->inChannelCount * sizeof(int16_t));
- if (buf == NULL) {
- session->framesRev = 0;
- free(session->revBuf);
- session->revBuf = NULL;
- return -ENOMEM;
- }
- session->revBuf = buf;
- }
- memcpy(session->revBuf + session->framesRev * session->inChannelCount, inBuffer->s16,
- fr * session->inChannelCount * sizeof(int16_t));
-
- session->framesRev += fr;
- inBuffer->frameCount = fr;
- if (session->framesRev < session->frameCount) {
- return 0;
- }
- spx_uint32_t frIn = session->framesRev;
- spx_uint32_t frOut = session->apmFrameCount;
- if (session->inChannelCount == 1) {
- speex_resampler_process_int(session->revResampler, 0, session->revBuf, &frIn,
- session->revFrame->data_, &frOut);
- } else {
- speex_resampler_process_interleaved_int(session->revResampler, session->revBuf,
- &frIn, session->revFrame->data_, &frOut);
- }
- memmove(session->revBuf, session->revBuf + frIn * session->inChannelCount,
- (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t));
- session->framesRev -= frIn;
- } else {
- size_t fr = session->frameCount - session->framesRev;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- memcpy(session->revFrame->data_ + session->framesRev * session->inChannelCount,
- inBuffer->s16, fr * session->inChannelCount * sizeof(int16_t));
- session->framesRev += fr;
- inBuffer->frameCount = fr;
- if (session->framesRev < session->frameCount) {
- return 0;
- }
- session->framesRev = 0;
- }
- session->revFrame->samples_per_channel_ = session->apmFrameCount;
- effect->session->apm->AnalyzeReverseStream(session->revFrame);
-#else
size_t fr = session->frameCount - session->framesRev;
if (inBuffer->frameCount < fr) {
fr = inBuffer->frameCount;
@@ -2205,7 +1592,6 @@
ALOGE("Process Reverse Stream failed with error %d\n", status);
return status;
}
-#endif
return 0;
} else {
return -ENODATA;
diff --git a/media/libeffects/preprocessing/benchmarks/Android.bp b/media/libeffects/preprocessing/benchmarks/Android.bp
index 2808293..262fd19 100644
--- a/media/libeffects/preprocessing/benchmarks/Android.bp
+++ b/media/libeffects/preprocessing/benchmarks/Android.bp
@@ -1,31 +1,4 @@
cc_benchmark {
- name: "preprocessing_legacy_benchmark",
- vendor: true,
- relative_install_path: "soundfx",
- srcs: ["preprocessing_benchmark.cpp"],
- shared_libs: [
- "libaudiopreprocessing_legacy",
- "libaudioutils",
- "liblog",
- "libutils",
- "libwebrtc_audio_preprocessing",
- ],
- cflags: [
- "-DWEBRTC_POSIX",
- "-DWEBRTC_LEGACY",
- "-fvisibility=default",
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
- header_libs: [
- "libaudioeffects",
- "libhardware_headers",
- "libwebrtc_absl_headers",
- ],
-}
-
-cc_benchmark {
name: "preprocessing_benchmark",
vendor: true,
relative_install_path: "soundfx",
diff --git a/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp b/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp
index 3a0ad6d..694a6c4 100644
--- a/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp
+++ b/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp
@@ -54,9 +54,7 @@
#include <cstdlib>
#include <random>
#include <vector>
-#ifndef WEBRTC_LEGACY
#include <audio_effects/effect_agc2.h>
-#endif
#include <audio_effects/effect_ns.h>
#include <benchmark/benchmark.h>
#include <hardware/audio_effect.h>
@@ -76,10 +74,8 @@
{0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
// ns uuid
{0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
-#ifndef WEBRTC_LEGACY
// agc2 uuid
{0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}},
-#endif
};
constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
constexpr audio_channel_mask_t kChMasks[] = {
@@ -93,9 +89,7 @@
PREPROC_AGC, // Automatic Gain Control
PREPROC_AEC, // Acoustic Echo Canceler
PREPROC_NS, // Noise Suppressor
-#ifndef WEBRTC_LEGACY
PREPROC_AGC2, // Automatic Gain Control 2
-#endif
PREPROC_NUM_EFFECTS
};
diff --git a/media/libeffects/preprocessing/tests/Android.bp b/media/libeffects/preprocessing/tests/Android.bp
index 045b0d3..b439880 100644
--- a/media/libeffects/preprocessing/tests/Android.bp
+++ b/media/libeffects/preprocessing/tests/Android.bp
@@ -1,37 +1,5 @@
// audio preprocessing unit test
cc_test {
- name: "AudioPreProcessingLegacyTest",
-
- vendor: true,
-
- relative_install_path: "soundfx",
-
- srcs: ["PreProcessingTest.cpp"],
-
- shared_libs: [
- "libaudiopreprocessing_legacy",
- "libaudioutils",
- "liblog",
- "libutils",
- "libwebrtc_audio_preprocessing",
- ],
-
- cflags: [
- "-DWEBRTC_POSIX",
- "-DWEBRTC_LEGACY",
- "-fvisibility=default",
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
-
- header_libs: [
- "libaudioeffects",
- "libhardware_headers",
- ],
-}
-
-cc_test {
name: "AudioPreProcessingTest",
vendor: true,
diff --git a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
index 65b9469..5f223c9 100644
--- a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
+++ b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
@@ -22,9 +22,7 @@
#include <audio_effects/effect_aec.h>
#include <audio_effects/effect_agc.h>
-#ifndef WEBRTC_LEGACY
#include <audio_effects/effect_agc2.h>
-#endif
#include <audio_effects/effect_ns.h>
#include <log/log.h>
@@ -38,9 +36,7 @@
// types of pre processing modules
enum PreProcId {
PREPROC_AGC, // Automatic Gain Control
-#ifndef WEBRTC_LEGACY
PREPROC_AGC2, // Automatic Gain Control 2
-#endif
PREPROC_AEC, // Acoustic Echo Canceler
PREPROC_NS, // Noise Suppressor
PREPROC_NUM_EFFECTS
@@ -57,11 +53,9 @@
ARG_AGC_COMP_LVL,
ARG_AEC_DELAY,
ARG_NS_LVL,
-#ifndef WEBRTC_LEGACY
ARG_AGC2_GAIN,
ARG_AGC2_LVL,
ARG_AGC2_SAT_MGN
-#endif
};
struct preProcConfigParams_t {
@@ -70,19 +64,15 @@
int nsLevel = 0; // a value between 0-3
int agcTargetLevel = 3; // in dB
int agcCompLevel = 9; // in dB
-#ifndef WEBRTC_LEGACY
float agc2Gain = 0.f; // in dB
float agc2SaturationMargin = 2.f; // in dB
int agc2Level = 0; // either kRms(0) or kPeak(1)
-#endif
int aecDelay = 0; // in ms
};
const effect_uuid_t kPreProcUuids[PREPROC_NUM_EFFECTS] = {
{0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // agc uuid
-#ifndef WEBRTC_LEGACY
{0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}}, // agc2 uuid
-#endif
{0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // aec uuid
{0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // ns uuid
};
@@ -138,24 +128,20 @@
printf("\n Enable Noise Suppression, default disabled");
printf("\n --agc");
printf("\n Enable Gain Control, default disabled");
-#ifndef WEBRTC_LEGACY
printf("\n --agc2");
printf("\n Enable Gain Controller 2, default disabled");
-#endif
printf("\n --ns_lvl <ns_level>");
printf("\n Noise Suppression level in dB, default value 0dB");
printf("\n --agc_tgt_lvl <target_level>");
printf("\n AGC Target Level in dB, default value 3dB");
printf("\n --agc_comp_lvl <comp_level>");
printf("\n AGC Comp Level in dB, default value 9dB");
-#ifndef WEBRTC_LEGACY
printf("\n --agc2_gain <fixed_digital_gain>");
printf("\n AGC Fixed Digital Gain in dB, default value 0dB");
printf("\n --agc2_lvl <level_estimator>");
printf("\n AGC Adaptive Digital Level Estimator, default value kRms");
printf("\n --agc2_sat_mgn <saturation_margin>");
printf("\n AGC Adaptive Digital Saturation Margin in dB, default value 2dB");
-#endif
printf("\n --aec_delay <delay>");
printf("\n AEC delay value in ms, default value 0ms");
printf("\n");
@@ -217,18 +203,14 @@
{"ch_mask", required_argument, nullptr, ARG_CH_MASK},
{"agc_tgt_lvl", required_argument, nullptr, ARG_AGC_TGT_LVL},
{"agc_comp_lvl", required_argument, nullptr, ARG_AGC_COMP_LVL},
-#ifndef WEBRTC_LEGACY
{"agc2_gain", required_argument, nullptr, ARG_AGC2_GAIN},
{"agc2_lvl", required_argument, nullptr, ARG_AGC2_LVL},
{"agc2_sat_mgn", required_argument, nullptr, ARG_AGC2_SAT_MGN},
-#endif
{"aec_delay", required_argument, nullptr, ARG_AEC_DELAY},
{"ns_lvl", required_argument, nullptr, ARG_NS_LVL},
{"aec", no_argument, &effectEn[PREPROC_AEC], 1},
{"agc", no_argument, &effectEn[PREPROC_AGC], 1},
-#ifndef WEBRTC_LEGACY
{"agc2", no_argument, &effectEn[PREPROC_AGC2], 1},
-#endif
{"ns", no_argument, &effectEn[PREPROC_NS], 1},
{nullptr, 0, nullptr, 0},
};
@@ -277,7 +259,6 @@
preProcCfgParams.agcCompLevel = atoi(optarg);
break;
}
-#ifndef WEBRTC_LEGACY
case ARG_AGC2_GAIN: {
preProcCfgParams.agc2Gain = atof(optarg);
break;
@@ -290,7 +271,6 @@
preProcCfgParams.agc2SaturationMargin = atof(optarg);
break;
}
-#endif
case ARG_AEC_DELAY: {
preProcCfgParams.aecDelay = atoi(optarg);
break;
@@ -387,7 +367,6 @@
return EXIT_FAILURE;
}
}
-#ifndef WEBRTC_LEGACY
if (effectEn[PREPROC_AGC2]) {
if (int status = preProcSetConfigParam(AGC2_PARAM_FIXED_DIGITAL_GAIN,
(float)preProcCfgParams.agc2Gain,
@@ -411,7 +390,6 @@
return EXIT_FAILURE;
}
}
-#endif
if (effectEn[PREPROC_NS]) {
if (int status = preProcSetConfigParam(NS_PARAM_LEVEL, (uint32_t)preProcCfgParams.nsLevel,
effectHandle[PREPROC_NS]);
diff --git a/media/libeffects/res/raw/sinesweepraw.raw b/media/libeffects/res/raw/sinesweepraw.raw
new file mode 100644
index 0000000..c0d48ce
--- /dev/null
+++ b/media/libeffects/res/raw/sinesweepraw.raw
Binary files differ
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index 39caf53..7ed76d8 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -38,7 +38,8 @@
FLAGS,
SETMEDIACAS,
NAME,
- GETMETRICS
+ GETMETRICS,
+ SETENTRYPOINT
};
class BpMediaExtractor : public BpInterface<IMediaExtractor> {
@@ -142,6 +143,13 @@
}
return nm;
}
+
+ virtual status_t setEntryPoint(EntryPoint entryPoint) {
+ Parcel data, reply;
+ data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+ data.writeInt32(static_cast<int32_t>(entryPoint));
+ return remote()->transact(SETENTRYPOINT, data, &reply);
+ }
};
IMPLEMENT_META_INTERFACE(MediaExtractor, "android.media.IMediaExtractor");
@@ -232,6 +240,16 @@
reply->writeString8(nm);
return NO_ERROR;
}
+ case SETENTRYPOINT: {
+ ALOGV("setEntryPoint");
+ CHECK_INTERFACE(IMediaExtractor, data, reply);
+ int32_t entryPoint;
+ status_t err = data.readInt32(&entryPoint);
+ if (err == OK) {
+ setEntryPoint(EntryPoint(entryPoint));
+ }
+ return err;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index da272e3..f682b6e 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -21,6 +21,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <algorithm>
#include <media/MidiIoWrapper.h>
#include <media/MediaExtractorPluginApi.h>
@@ -33,6 +34,8 @@
}
namespace android {
+int MidiIoWrapper::sCacheBufferSize = 0;
+Mutex MidiIoWrapper::mCacheLock;
MidiIoWrapper::MidiIoWrapper(const char *path) {
ALOGV("MidiIoWrapper(%s)", path);
@@ -40,6 +43,8 @@
mBase = 0;
mLength = lseek(mFd, 0, SEEK_END);
mDataSource = nullptr;
+ mCacheBuffer = NULL;
+ mCacheBufRangeLength = 0;
}
MidiIoWrapper::MidiIoWrapper(int fd, off64_t offset, int64_t size) {
@@ -48,6 +53,8 @@
mBase = offset;
mLength = size;
mDataSource = nullptr;
+ mCacheBuffer = NULL;
+ mCacheBufRangeLength = 0;
}
class MidiIoWrapper::DataSourceUnwrapper {
@@ -97,6 +104,8 @@
} else {
mLength = 0;
}
+ mCacheBuffer = NULL;
+ mCacheBufRangeLength = 0;
}
MidiIoWrapper::~MidiIoWrapper() {
@@ -105,11 +114,80 @@
close(mFd);
}
delete mDataSource;
+
+ if (NULL != mCacheBuffer) {
+ delete [] mCacheBuffer;
+ mCacheBuffer = NULL;
+ {
+ Mutex::Autolock _l(mCacheLock);
+ sCacheBufferSize -= mLength;
+ }
+ }
}
int MidiIoWrapper::readAt(void *buffer, int offset, int size) {
ALOGV("readAt(%p, %d, %d)", buffer, offset, size);
+ if (offset < 0) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (offset + size > mLength) {
+ size = mLength - offset;
+ }
+
+ if (mCacheBuffer == NULL) {
+ Mutex::Autolock _l(mCacheLock);
+ if (sCacheBufferSize + mLength <= kTotalCacheSize) {
+ mCacheBuffer = new (std::nothrow) unsigned char[mLength];
+ if (NULL != mCacheBuffer) {
+ sCacheBufferSize += mLength;
+ ALOGV("sCacheBufferSize : %d", sCacheBufferSize);
+ } else {
+ ALOGE("failed to allocate memory for mCacheBuffer");
+ }
+ } else {
+ ALOGV("not allocate memory for mCacheBuffer");
+ }
+ }
+
+ if (mCacheBuffer != NULL) {
+ if (mCacheBufRangeLength > 0 && mCacheBufRangeLength >= (offset + size)) {
+ /* Use buffered data */
+ memcpy(buffer, (void*)(mCacheBuffer + offset), size);
+ return size;
+ } else {
+ /* Buffer new data */
+ int64_t beyondCacheBufRangeLength = (offset + size) - mCacheBufRangeLength;
+ int64_t numRequiredBytesToCache =
+ std::max((int64_t)kSingleCacheSize, beyondCacheBufRangeLength);
+ int64_t availableReadLength = mLength - mCacheBufRangeLength;
+ int64_t readSize = std::min(availableReadLength, numRequiredBytesToCache);
+ int actualNumBytesRead =
+ unbufferedReadAt(mCacheBuffer + mCacheBufRangeLength,
+ mCacheBufRangeLength, readSize);
+ if(actualNumBytesRead > 0) {
+ mCacheBufRangeLength += actualNumBytesRead;
+ if (offset >= mCacheBufRangeLength) {
+ return 0;
+ } else if (offset + size >= mCacheBufRangeLength) {
+ memcpy(buffer, (void*)(mCacheBuffer + offset), mCacheBufRangeLength - offset);
+ return mCacheBufRangeLength - offset;
+ } else {
+ memcpy(buffer, (void*)(mCacheBuffer + offset), size);
+ return size;
+ }
+ } else {
+ return actualNumBytesRead;
+ }
+ }
+ } else {
+ return unbufferedReadAt(buffer, offset, size);
+ }
+}
+
+int MidiIoWrapper::unbufferedReadAt(void *buffer, int offset, int size) {
+ ALOGV("unbufferedReadAt(%p, %d, %d)", buffer, offset, size);
if (mDataSource != NULL) {
return mDataSource->readAt(offset, buffer, size);
}
diff --git a/media/libmedia/include/android/IMediaExtractor.h b/media/libmedia/include/android/IMediaExtractor.h
index 3e035ad..f9cafde 100644
--- a/media/libmedia/include/android/IMediaExtractor.h
+++ b/media/libmedia/include/android/IMediaExtractor.h
@@ -63,6 +63,15 @@
virtual status_t setMediaCas(const HInterfaceToken &casToken) = 0;
virtual String8 name() = 0;
+
+ enum class EntryPoint {
+ SDK = 1,
+ NDK_WITH_JVM = 2,
+ NDK_NO_JVM = 3,
+ OTHER = 4,
+ };
+
+ virtual status_t setEntryPoint(EntryPoint entryPoint) = 0;
};
diff --git a/media/libmedia/include/media/MidiIoWrapper.h b/media/libmedia/include/media/MidiIoWrapper.h
index 0cdd4ad..5fa745c 100644
--- a/media/libmedia/include/media/MidiIoWrapper.h
+++ b/media/libmedia/include/media/MidiIoWrapper.h
@@ -18,6 +18,7 @@
#define MIDI_IO_WRAPPER_H_
#include <libsonivox/eas_types.h>
+#include <utils/Mutex.h>
namespace android {
@@ -32,17 +33,27 @@
~MidiIoWrapper();
int readAt(void *buffer, int offset, int size);
+ int unbufferedReadAt(void *buffer, int offset, int size);
int size();
EAS_FILE_LOCATOR getLocator();
private:
+ enum {
+ kTotalCacheSize = 1024 * 1024 + 512 * 1024,
+ kSingleCacheSize = 65536,
+ };
+
int mFd;
off64_t mBase;
int64_t mLength;
class DataSourceUnwrapper;
DataSourceUnwrapper *mDataSource;
EAS_FILE mEasFile;
+ unsigned char *mCacheBuffer;
+ int64_t mCacheBufRangeLength;
+ static int sCacheBufferSize;
+ static Mutex mCacheLock;
};
diff --git a/media/libmedia/include/media/mediametadataretriever.h b/media/libmedia/include/media/mediametadataretriever.h
index 1fe6ffc..fba1a30 100644
--- a/media/libmedia/include/media/mediametadataretriever.h
+++ b/media/libmedia/include/media/mediametadataretriever.h
@@ -74,6 +74,8 @@
METADATA_KEY_SAMPLERATE = 38,
METADATA_KEY_BITS_PER_SAMPLE = 39,
METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40,
+ METADATA_KEY_XMP_OFFSET = 41,
+ METADATA_KEY_XMP_LENGTH = 42,
// Add more here...
};
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 1cc255d..89c7032 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -127,7 +127,8 @@
pid_t pid = IPCThreadState::self()->getCallingPid();
uid_t uid = IPCThreadState::self()->getCallingUid();
- if ((as == AUDIO_SOURCE_FM_TUNER && !captureAudioOutputAllowed(pid, uid))
+ if ((as == AUDIO_SOURCE_FM_TUNER
+ && !(captureAudioOutputAllowed(pid, uid) || captureTunerAudioInputAllowed(pid, uid)))
|| !recordingAllowed(String16(""), pid, uid)) {
return PERMISSION_DENIED;
}
diff --git a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
index 02fb6bb..6dc3e3f 100644
--- a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -529,6 +529,15 @@
mMetaData.add(METADATA_KEY_EXIF_LENGTH, String8(tmp));
}
+ int64_t xmpOffset, xmpSize;
+ if (meta->findInt64(kKeyXmpOffset, &xmpOffset)
+ && meta->findInt64(kKeyXmpSize, &xmpSize)) {
+ sprintf(tmp, "%lld", (long long)xmpOffset);
+ mMetaData.add(METADATA_KEY_XMP_OFFSET, String8(tmp));
+ sprintf(tmp, "%lld", (long long)xmpSize);
+ mMetaData.add(METADATA_KEY_XMP_LENGTH, String8(tmp));
+ }
+
bool hasAudio = false;
bool hasVideo = false;
int32_t videoWidth = -1;
@@ -629,7 +638,8 @@
}
// The duration value is a string representing the duration in ms.
- sprintf(tmp, "%" PRId64, (maxDurationUs + 500) / 1000);
+ sprintf(tmp, "%" PRId64,
+ (maxDurationUs > (INT64_MAX - 500) ? INT64_MAX : (maxDurationUs + 500)) / 1000);
mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
if (hasAudio) {
diff --git a/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp b/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
index 5a52ea5..d08c66d 100644
--- a/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
+++ b/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
@@ -41,7 +41,7 @@
"libmediandk",
],
- compile_multilib: "32",
+ compile_multilib: "prefer32",
cflags: [
"-Werror",
diff --git a/media/libmediatranscoding/Android.bp b/media/libmediatranscoding/Android.bp
index ec806d1..094d7c3 100644
--- a/media/libmediatranscoding/Android.bp
+++ b/media/libmediatranscoding/Android.bp
@@ -44,13 +44,32 @@
{
java: {
enabled: true,
+ apex_available: [
+ "com.android.media",
+ "test_com.android.media",
+ ],
+ min_sdk_version: "29",
+ },
+ ndk: {
+ enabled: true,
+ apex_available: [
+ "com.android.media",
+ "test_com.android.media",
+ ],
+ min_sdk_version: "29",
},
},
}
-cc_library_shared {
+cc_library {
name: "libmediatranscoding",
+ min_sdk_version: "29",
+ apex_available: [
+ "com.android.media",
+ "test_com.android.media",
+ ],
+
srcs: [
"TranscodingClientManager.cpp",
"TranscodingSessionController.cpp",
@@ -60,13 +79,12 @@
],
shared_libs: [
- "libandroid",
+ "libandroid#31",
"libbinder_ndk",
"libcutils",
"liblog",
"libutils",
"libmediatranscoder",
- "libbinder",
"libmediandk",
],
export_shared_lib_headers: [
diff --git a/media/libmediatranscoding/TranscodingResourcePolicy.cpp b/media/libmediatranscoding/TranscodingResourcePolicy.cpp
index f2e973a..af53f64 100644
--- a/media/libmediatranscoding/TranscodingResourcePolicy.cpp
+++ b/media/libmediatranscoding/TranscodingResourcePolicy.cpp
@@ -21,7 +21,6 @@
#include <aidl/android/media/IResourceObserverService.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
-#include <binder/IServiceManager.h>
#include <media/TranscodingResourcePolicy.h>
#include <utils/Log.h>
diff --git a/media/libmediatranscoding/TranscodingSessionController.cpp b/media/libmediatranscoding/TranscodingSessionController.cpp
index 49a7083..b77a3a4 100644
--- a/media/libmediatranscoding/TranscodingSessionController.cpp
+++ b/media/libmediatranscoding/TranscodingSessionController.cpp
@@ -31,6 +31,7 @@
static_assert((SessionIdType)-1 < 0, "SessionIdType should be signed");
constexpr static uid_t OFFLINE_UID = -1;
+constexpr static size_t kSessionHistoryMax = 100;
//static
String8 TranscodingSessionController::sessionToString(const SessionKeyType& sessionKey) {
@@ -47,6 +48,12 @@
return "RUNNING";
case Session::State::PAUSED:
return "PAUSED";
+ case Session::State::FINISHED:
+ return "FINISHED";
+ case Session::State::CANCELED:
+ return "CANCELED";
+ case Session::State::ERROR:
+ return "ERROR";
default:
break;
}
@@ -71,6 +78,30 @@
TranscodingSessionController::~TranscodingSessionController() {}
+void TranscodingSessionController::dumpSession_l(const Session& session, String8& result,
+ bool closedSession) {
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ const TranscodingRequestParcel& request = session.request;
+ snprintf(buffer, SIZE, " Session: %s, %s, %d%%\n", sessionToString(session.key).c_str(),
+ sessionStateToString(session.getState()), session.lastProgress);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " pkg: %s\n", request.clientPackageName.c_str());
+ result.append(buffer);
+ snprintf(buffer, SIZE, " src: %s\n", request.sourceFilePath.c_str());
+ result.append(buffer);
+ snprintf(buffer, SIZE, " dst: %s\n", request.destinationFilePath.c_str());
+ result.append(buffer);
+
+ if (closedSession) {
+ snprintf(buffer, SIZE,
+ " waiting: %.1fs, running: %.1fs, paused: %.1fs, paused count: %d\n",
+ session.waitingTime.count() / 1000000.0f, session.runningTime.count() / 1000000.0f,
+ session.pausedTime.count() / 1000000.0f, session.pauseCount);
+ result.append(buffer);
+ }
+}
+
void TranscodingSessionController::dumpAllSessions(int fd, const Vector<String16>& args __unused) {
String8 result;
@@ -78,7 +109,7 @@
char buffer[SIZE];
std::scoped_lock lock{mLock};
- snprintf(buffer, SIZE, "\n========== Dumping all sessions queues =========\n");
+ snprintf(buffer, SIZE, "\n========== Dumping live sessions queues =========\n");
result.append(buffer);
snprintf(buffer, SIZE, " Total num of Sessions: %zu\n", mSessionMap.size());
result.append(buffer);
@@ -91,7 +122,7 @@
if (mSessionQueues[uid].empty()) {
continue;
}
- snprintf(buffer, SIZE, " Uid: %d, pkg: %s\n", uid,
+ snprintf(buffer, SIZE, " uid: %d, pkg: %s\n", uid,
mUidPackageNames.count(uid) > 0 ? mUidPackageNames[uid].c_str() : "(unknown)");
result.append(buffer);
snprintf(buffer, SIZE, " Num of sessions: %zu\n", mSessionQueues[uid].size());
@@ -104,25 +135,16 @@
result.append(buffer);
continue;
}
- Session& session = sessionIt->second;
- TranscodingRequestParcel& request = session.request;
- snprintf(buffer, SIZE, " Session: %s, %s, %d%%\n",
- sessionToString(sessionKey).c_str(), sessionStateToString(session.state),
- session.lastProgress);
- result.append(buffer);
- snprintf(buffer, SIZE, " Src: %s\n", request.sourceFilePath.c_str());
- result.append(buffer);
- snprintf(buffer, SIZE, " Dst: %s\n", request.destinationFilePath.c_str());
- result.append(buffer);
- // For the offline queue, print out the original client.
- if (uid == OFFLINE_UID) {
- snprintf(buffer, SIZE, " Original Client: %s\n",
- request.clientPackageName.c_str());
- result.append(buffer);
- }
+ dumpSession_l(sessionIt->second, result);
}
}
+ snprintf(buffer, SIZE, "\n========== Dumping past sessions =========\n");
+ result.append(buffer);
+ for (auto &session : mSessionHistory) {
+ dumpSession_l(session, result, true /*closedSession*/);
+ }
+
write(fd, result.string(), result.size());
}
@@ -135,6 +157,34 @@
return &mSessionMap[topSessionKey];
}
+void TranscodingSessionController::Session::setState(Session::State newState) {
+ if (state == newState) {
+ return;
+ }
+ auto nowTime = std::chrono::system_clock::now();
+ if (state != INVALID) {
+ std::chrono::microseconds elapsedTime = (nowTime - stateEnterTime);
+ switch (state) {
+ case PAUSED:
+ pausedTime = pausedTime + elapsedTime;
+ break;
+ case RUNNING:
+ runningTime = runningTime + elapsedTime;
+ break;
+ case NOT_STARTED:
+ waitingTime = waitingTime + elapsedTime;
+ break;
+ default:
+ break;
+ }
+ }
+ if (newState == PAUSED) {
+ pauseCount++;
+ }
+ stateEnterTime = nowTime;
+ state = newState;
+}
+
void TranscodingSessionController::updateCurrentSession_l() {
Session* topSession = getTopSession_l();
Session* curSession = mCurrentSession;
@@ -145,29 +195,30 @@
// If we found a topSession that should be run, and it's not already running,
// take some actions to ensure it's running.
if (topSession != nullptr &&
- (topSession != curSession || topSession->state != Session::RUNNING)) {
+ (topSession != curSession || topSession->getState() != Session::RUNNING)) {
// If another session is currently running, pause it first.
- if (curSession != nullptr && curSession->state == Session::RUNNING) {
+ if (curSession != nullptr && curSession->getState() == Session::RUNNING) {
mTranscoder->pause(curSession->key.first, curSession->key.second);
- curSession->state = Session::PAUSED;
+ curSession->setState(Session::PAUSED);
}
// If we are not experiencing resource loss, we can start or resume
// the topSession now.
if (!mResourceLost) {
- if (topSession->state == Session::NOT_STARTED) {
+ if (topSession->getState() == Session::NOT_STARTED) {
mTranscoder->start(topSession->key.first, topSession->key.second,
topSession->request, topSession->callback.lock());
- } else if (topSession->state == Session::PAUSED) {
+ } else if (topSession->getState() == Session::PAUSED) {
mTranscoder->resume(topSession->key.first, topSession->key.second,
topSession->request, topSession->callback.lock());
}
- topSession->state = Session::RUNNING;
+ topSession->setState(Session::RUNNING);
}
}
mCurrentSession = topSession;
}
-void TranscodingSessionController::removeSession_l(const SessionKeyType& sessionKey) {
+void TranscodingSessionController::removeSession_l(const SessionKeyType& sessionKey,
+ Session::State finalState) {
ALOGV("%s: session %s", __FUNCTION__, sessionToString(sessionKey).c_str());
if (mSessionMap.count(sessionKey) == 0) {
@@ -201,6 +252,12 @@
mCurrentSession = nullptr;
}
+ mSessionMap[sessionKey].setState(finalState);
+ mSessionHistory.push_back(mSessionMap[sessionKey]);
+ if (mSessionHistory.size() > kSessionHistoryMax) {
+ mSessionHistory.erase(mSessionHistory.begin());
+ }
+
// Remove session from session map.
mSessionMap.erase(sessionKey);
}
@@ -288,10 +345,11 @@
// Add session to session map.
mSessionMap[sessionKey].key = sessionKey;
mSessionMap[sessionKey].uid = uid;
- mSessionMap[sessionKey].state = Session::NOT_STARTED;
mSessionMap[sessionKey].lastProgress = 0;
+ mSessionMap[sessionKey].pauseCount = 0;
mSessionMap[sessionKey].request = request;
mSessionMap[sessionKey].callback = callback;
+ mSessionMap[sessionKey].setState(Session::NOT_STARTED);
// If it's an offline session, the queue was already added in constructor.
// If it's a real-time sessions, check if a queue is already present for the uid,
@@ -350,12 +408,12 @@
// Note that stop() is needed even if the session is currently paused. This instructs
// the transcoder to discard any states for the session, otherwise the states may
// never be discarded.
- if (mSessionMap[*it].state != Session::NOT_STARTED) {
+ if (mSessionMap[*it].getState() != Session::NOT_STARTED) {
mTranscoder->stop(it->first, it->second);
}
// Remove the session.
- removeSession_l(*it);
+ removeSession_l(*it, Session::CANCELED);
}
// Start next session.
@@ -396,7 +454,7 @@
// Only ignore if session was never started. In particular, propagate the status
// to client if the session is paused. Transcoder could have posted finish when
// we're pausing it, and the finish arrived after we changed current session.
- if (mSessionMap[sessionKey].state == Session::NOT_STARTED) {
+ if (mSessionMap[sessionKey].getState() == Session::NOT_STARTED) {
ALOGW("%s: ignoring %s for session %s that was never started", __FUNCTION__, reason,
sessionToString(sessionKey).c_str());
return;
@@ -445,7 +503,7 @@
}
// Remove the session.
- removeSession_l(sessionKey);
+ removeSession_l(sessionKey, Session::FINISHED);
// Start next session.
updateCurrentSession_l();
@@ -465,7 +523,7 @@
}
// Remove the session.
- removeSession_l(sessionKey);
+ removeSession_l(sessionKey, Session::ERROR);
// Start next session.
updateCurrentSession_l();
@@ -494,15 +552,15 @@
}
Session* resourceLostSession = &mSessionMap[sessionKey];
- if (resourceLostSession->state != Session::RUNNING) {
+ if (resourceLostSession->getState() != Session::RUNNING) {
ALOGW("session %s lost resource but is no longer running",
- sessionToString(sessionKey).c_str());
+ sessionToString(sessionKey).c_str());
return;
}
// If we receive a resource loss event, the transcoder already paused the transcoding,
// so we don't need to call onPaused() to pause it. However, we still need to notify
// the client and update the session state here.
- resourceLostSession->state = Session::PAUSED;
+ resourceLostSession->setState(Session::PAUSED);
// Notify the client as a paused event.
auto clientCallback = resourceLostSession->callback.lock();
if (clientCallback != nullptr) {
diff --git a/media/libmediatranscoding/TranscodingUidPolicy.cpp b/media/libmediatranscoding/TranscodingUidPolicy.cpp
index 8a74d5d..a725387 100644
--- a/media/libmediatranscoding/TranscodingUidPolicy.cpp
+++ b/media/libmediatranscoding/TranscodingUidPolicy.cpp
@@ -17,11 +17,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "TranscodingUidPolicy"
+#include <android/activity_manager.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
-#include <binder/ActivityManager.h>
-#include <cutils/misc.h> // FIRST_APPLICATION_UID
-#include <cutils/multiuser.h>
#include <inttypes.h>
#include <media/TranscodingUidPolicy.h>
#include <utils/Log.h>
@@ -31,51 +29,12 @@
namespace android {
constexpr static uid_t OFFLINE_UID = -1;
-constexpr static const char* kTranscodingTag = "transcoding";
-
-struct TranscodingUidPolicy::UidObserver : public BnUidObserver,
- public virtual IBinder::DeathRecipient {
- explicit UidObserver(TranscodingUidPolicy* owner) : mOwner(owner) {}
-
- // IUidObserver
- void onUidGone(uid_t uid, bool disabled) override;
- void onUidActive(uid_t uid) override;
- void onUidIdle(uid_t uid, bool disabled) override;
- void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
- int32_t capability) override;
-
- // IBinder::DeathRecipient implementation
- void binderDied(const wp<IBinder>& who) override;
-
- TranscodingUidPolicy* mOwner;
-};
-
-void TranscodingUidPolicy::UidObserver::onUidGone(uid_t uid __unused, bool disabled __unused) {}
-
-void TranscodingUidPolicy::UidObserver::onUidActive(uid_t uid __unused) {}
-
-void TranscodingUidPolicy::UidObserver::onUidIdle(uid_t uid __unused, bool disabled __unused) {}
-
-void TranscodingUidPolicy::UidObserver::onUidStateChanged(uid_t uid, int32_t procState,
- int64_t procStateSeq __unused,
- int32_t capability __unused) {
- mOwner->onUidStateChanged(uid, procState);
-}
-
-void TranscodingUidPolicy::UidObserver::binderDied(const wp<IBinder>& /*who*/) {
- ALOGW("TranscodingUidPolicy: ActivityManager has died");
- // TODO(chz): this is a rare event (since if the AMS is dead, the system is
- // probably dead as well). But we should try to reconnect.
- mOwner->setUidObserverRegistered(false);
-}
-
-////////////////////////////////////////////////////////////////////////////
+constexpr static int32_t IMPORTANCE_UNKNOWN = INT32_MAX;
TranscodingUidPolicy::TranscodingUidPolicy()
- : mAm(std::make_shared<ActivityManager>()),
- mUidObserver(new UidObserver(this)),
+ : mUidObserver(nullptr),
mRegistered(false),
- mTopUidState(ActivityManager::PROCESS_STATE_UNKNOWN) {
+ mTopUidState(IMPORTANCE_UNKNOWN) {
registerSelf();
}
@@ -83,39 +42,32 @@
unregisterSelf();
}
+void TranscodingUidPolicy::OnUidImportance(uid_t uid, int32_t uidImportance, void* cookie) {
+ TranscodingUidPolicy* owner = reinterpret_cast<TranscodingUidPolicy*>(cookie);
+ owner->onUidStateChanged(uid, uidImportance);
+}
+
void TranscodingUidPolicy::registerSelf() {
- status_t res = mAm->linkToDeath(mUidObserver.get());
- mAm->registerUidObserver(
- mUidObserver.get(),
- ActivityManager::UID_OBSERVER_GONE | ActivityManager::UID_OBSERVER_IDLE |
- ActivityManager::UID_OBSERVER_ACTIVE | ActivityManager::UID_OBSERVER_PROCSTATE,
- ActivityManager::PROCESS_STATE_UNKNOWN, String16(kTranscodingTag));
+ mUidObserver = AActivityManager_addUidImportanceListener(
+ &OnUidImportance, -1, (void*)this);
- if (res == OK) {
- Mutex::Autolock _l(mUidLock);
-
- mRegistered = true;
- ALOGI("TranscodingUidPolicy: Registered with ActivityManager");
- } else {
- mAm->unregisterUidObserver(mUidObserver.get());
+ if (mUidObserver == nullptr) {
+ ALOGE("Failed to register uid observer");
+ return;
}
+
+ Mutex::Autolock _l(mUidLock);
+ mRegistered = true;
+ ALOGI("Registered uid observer");
}
void TranscodingUidPolicy::unregisterSelf() {
- mAm->unregisterUidObserver(mUidObserver.get());
- mAm->unlinkToDeath(mUidObserver.get());
+ AActivityManager_removeUidImportanceListener(mUidObserver);
+ mUidObserver = nullptr;
Mutex::Autolock _l(mUidLock);
-
mRegistered = false;
-
- ALOGI("TranscodingUidPolicy: Unregistered with ActivityManager");
-}
-
-void TranscodingUidPolicy::setUidObserverRegistered(bool registered) {
- Mutex::Autolock _l(mUidLock);
-
- mRegistered = registered;
+ ALOGI("Unregistered uid observer");
}
void TranscodingUidPolicy::setCallback(const std::shared_ptr<UidPolicyCallbackInterface>& cb) {
@@ -133,9 +85,9 @@
return;
}
- int32_t state = ActivityManager::PROCESS_STATE_UNKNOWN;
- if (mRegistered && mAm->isUidActive(uid, String16(kTranscodingTag))) {
- state = mAm->getUidProcessState(uid, String16(kTranscodingTag));
+ int32_t state = IMPORTANCE_UNKNOWN;
+ if (mRegistered && AActivityManager_isUidActive(uid)) {
+ state = AActivityManager_getUidImportance(uid);
}
ALOGV("%s: inserting new uid: %u, procState %d", __FUNCTION__, uid, state);
@@ -170,14 +122,14 @@
bool TranscodingUidPolicy::isUidOnTop(uid_t uid) {
Mutex::Autolock _l(mUidLock);
- return mTopUidState != ActivityManager::PROCESS_STATE_UNKNOWN &&
+ return mTopUidState != IMPORTANCE_UNKNOWN &&
mTopUidState == getProcState_l(uid);
}
std::unordered_set<uid_t> TranscodingUidPolicy::getTopUids() const {
Mutex::Autolock _l(mUidLock);
- if (mTopUidState == ActivityManager::PROCESS_STATE_UNKNOWN) {
+ if (mTopUidState == IMPORTANCE_UNKNOWN) {
return std::unordered_set<uid_t>();
}
@@ -195,11 +147,13 @@
if (it != mUidStateMap.end() && it->second != procState) {
// Top set changed if 1) the uid is in the current top uid set, or 2) the
// new procState is at least the same priority as the current top uid state.
- bool isUidCurrentTop = mTopUidState != ActivityManager::PROCESS_STATE_UNKNOWN &&
- mStateUidMap[mTopUidState].count(uid) > 0;
- bool isNewStateHigherThanTop = procState != ActivityManager::PROCESS_STATE_UNKNOWN &&
- (procState <= mTopUidState ||
- mTopUidState == ActivityManager::PROCESS_STATE_UNKNOWN);
+ bool isUidCurrentTop =
+ mTopUidState != IMPORTANCE_UNKNOWN &&
+ mStateUidMap[mTopUidState].count(uid) > 0;
+ bool isNewStateHigherThanTop =
+ procState != IMPORTANCE_UNKNOWN &&
+ (procState <= mTopUidState ||
+ mTopUidState == IMPORTANCE_UNKNOWN);
topUidSetChanged = (isUidCurrentTop || isNewStateHigherThanTop);
// Move uid to the new procState.
@@ -227,11 +181,12 @@
}
void TranscodingUidPolicy::updateTopUid_l() {
- mTopUidState = ActivityManager::PROCESS_STATE_UNKNOWN;
+ mTopUidState = IMPORTANCE_UNKNOWN;
// Find the lowest uid state (ignoring PROCESS_STATE_UNKNOWN) with some monitored uids.
for (auto stateIt = mStateUidMap.begin(); stateIt != mStateUidMap.end(); stateIt++) {
- if (stateIt->first != ActivityManager::PROCESS_STATE_UNKNOWN && !stateIt->second.empty()) {
+ if (stateIt->first != IMPORTANCE_UNKNOWN &&
+ !stateIt->second.empty()) {
mTopUidState = stateIt->first;
break;
}
@@ -245,7 +200,7 @@
if (it != mUidStateMap.end()) {
return it->second;
}
- return ActivityManager::PROCESS_STATE_UNKNOWN;
+ return IMPORTANCE_UNKNOWN;
}
} // namespace android
diff --git a/media/libmediatranscoding/include/media/TranscoderWrapper.h b/media/libmediatranscoding/include/media/TranscoderWrapper.h
index 9ec32d7..02beede 100644
--- a/media/libmediatranscoding/include/media/TranscoderWrapper.h
+++ b/media/libmediatranscoding/include/media/TranscoderWrapper.h
@@ -17,7 +17,6 @@
#ifndef ANDROID_TRANSCODER_WRAPPER_H
#define ANDROID_TRANSCODER_WRAPPER_H
-#include <android-base/thread_annotations.h>
#include <media/NdkMediaError.h>
#include <media/TranscoderInterface.h>
diff --git a/media/libmediatranscoding/include/media/TranscodingSessionController.h b/media/libmediatranscoding/include/media/TranscodingSessionController.h
index 4215e06..a443265 100644
--- a/media/libmediatranscoding/include/media/TranscodingSessionController.h
+++ b/media/libmediatranscoding/include/media/TranscodingSessionController.h
@@ -26,6 +26,7 @@
#include <utils/String8.h>
#include <utils/Vector.h>
+#include <chrono>
#include <list>
#include <map>
#include <mutex>
@@ -82,16 +83,33 @@
using SessionQueueType = std::list<SessionKeyType>;
struct Session {
- SessionKeyType key;
- uid_t uid;
enum State {
- NOT_STARTED,
+ INVALID = -1,
+ NOT_STARTED = 0,
RUNNING,
PAUSED,
- } state;
+ FINISHED,
+ CANCELED,
+ ERROR,
+ };
+ SessionKeyType key;
+ uid_t uid;
int32_t lastProgress;
+ int32_t pauseCount;
+ std::chrono::time_point<std::chrono::system_clock> stateEnterTime;
+ std::chrono::microseconds waitingTime;
+ std::chrono::microseconds runningTime;
+ std::chrono::microseconds pausedTime;
+
TranscodingRequest request;
std::weak_ptr<ITranscodingClientCallback> callback;
+
+ // Must use setState to change state.
+ void setState(Session::State state);
+ State getState() const { return state; }
+
+ private:
+ State state = INVALID;
};
// TODO(chz): call transcoder without global lock.
@@ -115,15 +133,17 @@
Session* mCurrentSession;
bool mResourceLost;
+ std::list<Session> mSessionHistory;
// Only allow MediaTranscodingService and unit tests to instantiate.
TranscodingSessionController(const std::shared_ptr<TranscoderInterface>& transcoder,
const std::shared_ptr<UidPolicyInterface>& uidPolicy,
const std::shared_ptr<ResourcePolicyInterface>& resourcePolicy);
+ void dumpSession_l(const Session& session, String8& result, bool closedSession = false);
Session* getTopSession_l();
void updateCurrentSession_l();
- void removeSession_l(const SessionKeyType& sessionKey);
+ void removeSession_l(const SessionKeyType& sessionKey, Session::State finalState);
void moveUidsToTop_l(const std::unordered_set<uid_t>& uids, bool preserveTopUid);
void notifyClient(ClientIdType clientId, SessionIdType sessionId, const char* reason,
std::function<void(const SessionKeyType&)> func);
diff --git a/media/libmediatranscoding/include/media/TranscodingUidPolicy.h b/media/libmediatranscoding/include/media/TranscodingUidPolicy.h
index acd3cff..4dde5a6 100644
--- a/media/libmediatranscoding/include/media/TranscodingUidPolicy.h
+++ b/media/libmediatranscoding/include/media/TranscodingUidPolicy.h
@@ -22,18 +22,16 @@
#include <media/UidPolicyInterface.h>
#include <sys/types.h>
#include <utils/Condition.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
#include <map>
#include <mutex>
#include <unordered_map>
#include <unordered_set>
+struct AActivityManager_UidImportanceListener;
+
namespace android {
-class ActivityManager;
// Observer for UID lifecycle and provide information about the uid's app
// priority used by the session controller.
class TranscodingUidPolicy : public UidPolicyInterface {
@@ -51,17 +49,17 @@
private:
void onUidStateChanged(uid_t uid, int32_t procState);
- void setUidObserverRegistered(bool registerd);
void registerSelf();
void unregisterSelf();
int32_t getProcState_l(uid_t uid) NO_THREAD_SAFETY_ANALYSIS;
void updateTopUid_l() NO_THREAD_SAFETY_ANALYSIS;
- struct UidObserver;
+ static void OnUidImportance(uid_t uid, int32_t uidImportance, void* cookie);
+
struct ResourceManagerClient;
mutable Mutex mUidLock;
- std::shared_ptr<ActivityManager> mAm;
- sp<UidObserver> mUidObserver;
+ AActivityManager_UidImportanceListener* mUidObserver;
+
bool mRegistered GUARDED_BY(mUidLock);
int32_t mTopUidState GUARDED_BY(mUidLock);
std::unordered_map<uid_t, int32_t> mUidStateMap GUARDED_BY(mUidLock);
diff --git a/media/libmediatranscoding/tests/Android.bp b/media/libmediatranscoding/tests/Android.bp
index e49df35..8bff10a 100644
--- a/media/libmediatranscoding/tests/Android.bp
+++ b/media/libmediatranscoding/tests/Android.bp
@@ -14,15 +14,16 @@
],
shared_libs: [
+ "libandroid",
"libbinder_ndk",
"libcutils",
"liblog",
"libutils",
- "libmediatranscoding"
],
static_libs: [
"mediatranscoding_aidl_interface-ndk_platform",
+ "libmediatranscoding",
],
cflags: [
diff --git a/media/libmediatranscoding/transcoder/Android.bp b/media/libmediatranscoding/transcoder/Android.bp
index aa7cdde..bebe6b1 100644
--- a/media/libmediatranscoding/transcoder/Android.bp
+++ b/media/libmediatranscoding/transcoder/Android.bp
@@ -28,6 +28,14 @@
"VideoTrackTranscoder.cpp",
],
+ min_sdk_version: "29",
+ apex_available: [
+ "com.android.media",
+ "test_com.android.media",
+ ],
+
+ //header_libs: [ "libarect_headers", "libarect_headers_for_ndk" ],
+ static_libs: [ "libarect" ],
shared_libs: [
"libbase",
"libcutils",
diff --git a/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp b/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
index 92ba818..1a6e7ed 100644
--- a/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
+++ b/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
@@ -235,6 +235,33 @@
return AMEDIA_OK;
}
+media_status_t MediaSampleReaderNDK::unselectTrack(int trackIndex) {
+ std::scoped_lock lock(mExtractorMutex);
+
+ if (trackIndex < 0 || trackIndex >= mTrackCount) {
+ LOG(ERROR) << "Invalid trackIndex " << trackIndex << " for trackCount " << mTrackCount;
+ return AMEDIA_ERROR_INVALID_PARAMETER;
+ } else if (mExtractorTrackIndex >= 0) {
+ LOG(ERROR) << "unselectTrack must be called before sample reading begins.";
+ return AMEDIA_ERROR_UNSUPPORTED;
+ }
+
+ auto it = mTrackSignals.find(trackIndex);
+ if (it == mTrackSignals.end()) {
+ LOG(ERROR) << "TrackIndex " << trackIndex << " is not selected";
+ return AMEDIA_ERROR_INVALID_PARAMETER;
+ }
+ mTrackSignals.erase(it);
+
+ media_status_t status = AMediaExtractor_unselectTrack(mExtractor, trackIndex);
+ if (status != AMEDIA_OK) {
+ LOG(ERROR) << "AMediaExtractor_selectTrack returned error: " << status;
+ return status;
+ }
+
+ return AMEDIA_OK;
+}
+
media_status_t MediaSampleReaderNDK::setEnforceSequentialAccess(bool enforce) {
LOG(DEBUG) << "setEnforceSequentialAccess( " << enforce << " )";
diff --git a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
index 94a9a33..3d4ff15 100644
--- a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
@@ -275,12 +275,6 @@
return AMEDIA_ERROR_INVALID_PARAMETER;
}
- media_status_t status = mSampleReader->selectTrack(trackIndex);
- if (status != AMEDIA_OK) {
- LOG(ERROR) << "Unable to select track " << trackIndex;
- return status;
- }
-
std::shared_ptr<MediaTrackTranscoder> transcoder;
std::shared_ptr<AMediaFormat> format;
@@ -322,10 +316,17 @@
format = std::shared_ptr<AMediaFormat>(mergedFormat, &AMediaFormat_delete);
}
+ media_status_t status = mSampleReader->selectTrack(trackIndex);
+ if (status != AMEDIA_OK) {
+ LOG(ERROR) << "Unable to select track " << trackIndex;
+ return status;
+ }
+
status = transcoder->configure(mSampleReader, trackIndex, format);
if (status != AMEDIA_OK) {
LOG(ERROR) << "Configure track transcoder for track #" << trackIndex << " returned error "
<< status;
+ mSampleReader->unselectTrack(trackIndex);
return status;
}
diff --git a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
index 5ec5e08..21d60ea 100644
--- a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "VideoTrackTranscoder"
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <media/NdkCommon.h>
#include <media/VideoTrackTranscoder.h>
#include <utils/AndroidThreads.h>
@@ -39,11 +40,16 @@
// Default key frame interval in seconds.
static constexpr float kDefaultKeyFrameIntervalSeconds = 1.0f;
// Default codec operating rate.
-static constexpr int32_t kDefaultCodecOperatingRate = 240;
+static int32_t kDefaultCodecOperatingRate720P = base::GetIntProperty(
+ "debug.media.transcoding.codec_max_operating_rate_720P", /*default*/ 480);
+static int32_t kDefaultCodecOperatingRate1080P = base::GetIntProperty(
+ "debug.media.transcoding.codec_max_operating_rate_1080P", /*default*/ 240);
// Default codec priority.
static constexpr int32_t kDefaultCodecPriority = 1;
// Default bitrate, in case source estimation fails.
static constexpr int32_t kDefaultBitrateMbps = 10 * 1000 * 1000;
+// Default frame rate.
+static constexpr int32_t kDefaultFrameRate = 30;
template <typename T>
void VideoTrackTranscoder::BlockingQueue<T>::push(T const& value, bool front) {
@@ -179,6 +185,25 @@
}
}
+// Search the default operating rate based on resolution.
+static int32_t getDefaultOperatingRate(AMediaFormat* encoderFormat) {
+ int32_t width, height;
+ if (AMediaFormat_getInt32(encoderFormat, AMEDIAFORMAT_KEY_WIDTH, &width) && (width > 0) &&
+ AMediaFormat_getInt32(encoderFormat, AMEDIAFORMAT_KEY_HEIGHT, &height) && (height > 0)) {
+ if ((width == 1280 && height == 720) || (width == 720 && height == 1280)) {
+ return kDefaultCodecOperatingRate720P;
+ } else if ((width == 1920 && height == 1080) || (width == 1080 && height == 1920)) {
+ return kDefaultCodecOperatingRate1080P;
+ } else {
+ LOG(WARNING) << "Could not find default operating rate: " << width << " " << height;
+ // Don't set operating rate if the correct dimensions are not found.
+ }
+ } else {
+ LOG(ERROR) << "Failed to get default operating rate due to missing resolution";
+ }
+ return -1;
+}
+
// Creates and configures the codecs.
media_status_t VideoTrackTranscoder::configureDestinationFormat(
const std::shared_ptr<AMediaFormat>& destinationFormat) {
@@ -209,10 +234,15 @@
SetDefaultFormatValueFloat(AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, encoderFormat,
kDefaultKeyFrameIntervalSeconds);
- SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_OPERATING_RATE, encoderFormat,
- kDefaultCodecOperatingRate);
- SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_PRIORITY, encoderFormat, kDefaultCodecPriority);
+ int32_t operatingRate = getDefaultOperatingRate(encoderFormat);
+
+ if (operatingRate != -1) {
+ SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_OPERATING_RATE, encoderFormat, operatingRate);
+ }
+
+ SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_PRIORITY, encoderFormat, kDefaultCodecPriority);
+ SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_FRAME_RATE, encoderFormat, kDefaultFrameRate);
AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT, kColorFormatSurface);
// Always encode without rotation. The rotation degree will be transferred directly to
@@ -230,13 +260,19 @@
return AMEDIA_ERROR_INVALID_PARAMETER;
}
+#if !defined(__ANDROID_APEX__)
+ // TODO(jiyong): replace this #ifdef with a __builtin_available check.
AMediaCodec* encoder = AMediaCodec_createEncoderByTypeForClient(destinationMime, mPid, mUid);
+#else
+ AMediaCodec* encoder = AMediaCodec_createEncoderByType(destinationMime);
+#endif
if (encoder == nullptr) {
LOG(ERROR) << "Unable to create encoder for type " << destinationMime;
return AMEDIA_ERROR_UNSUPPORTED;
}
mEncoder = std::make_shared<CodecWrapper>(encoder, shared_from_this());
+ LOG(DEBUG) << "Configuring encoder with: " << AMediaFormat_toString(mDestinationFormat.get());
status = AMediaCodec_configure(mEncoder->getCodec(), mDestinationFormat.get(),
NULL /* surface */, NULL /* crypto */,
AMEDIACODEC_CONFIGURE_FLAG_ENCODE);
@@ -259,7 +295,12 @@
return AMEDIA_ERROR_INVALID_PARAMETER;
}
+#if !defined(__ANDROID_APEX__)
+ // TODO(jiyong): replace this #ifdef with a __builtin_available check.
mDecoder = AMediaCodec_createDecoderByTypeForClient(sourceMime, mPid, mUid);
+#else
+ mDecoder = AMediaCodec_createDecoderByType(sourceMime);
+#endif
if (mDecoder == nullptr) {
LOG(ERROR) << "Unable to create decoder for type " << sourceMime;
return AMEDIA_ERROR_UNSUPPORTED;
@@ -284,6 +325,7 @@
CopyFormatEntries(mDestinationFormat.get(), decoderFormat.get(), kEncoderEntriesToCopy,
entryCount);
+ LOG(DEBUG) << "Configuring decoder with: " << AMediaFormat_toString(decoderFormat.get());
status = AMediaCodec_configure(mDecoder, decoderFormat.get(), mSurface, NULL /* crypto */,
0 /* flags */);
if (status != AMEDIA_OK) {
diff --git a/media/libmediatranscoding/transcoder/benchmark/Android.bp b/media/libmediatranscoding/transcoder/benchmark/Android.bp
index ce34702..74f65b9 100644
--- a/media/libmediatranscoding/transcoder/benchmark/Android.bp
+++ b/media/libmediatranscoding/transcoder/benchmark/Android.bp
@@ -1,7 +1,16 @@
cc_defaults {
name: "benchmarkdefaults",
- shared_libs: ["libmediatranscoder", "libmediandk", "libbase", "libbinder_ndk"],
- static_libs: ["libgoogle-benchmark"],
+ shared_libs: [
+ "libmediandk",
+ "libbase",
+ "libbinder_ndk",
+ "libbinder",
+ "libutils",
+ "libnativewindow",
+ ],
+ static_libs: ["libmediatranscoder", "libgoogle-benchmark"],
+ test_config_template: "AndroidTestTemplate.xml",
+ test_suites: ["device-tests", "TranscoderBenchmarks"],
}
cc_test {
diff --git a/media/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml b/media/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml
new file mode 100644
index 0000000..64085d8
--- /dev/null
+++ b/media/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Unit test configuration for {MODULE}">
+ <option name="test-suite-tag" value="TranscoderBenchmarks" />
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="false" />
+ <option name="push-file" key="{MODULE}" value="/data/local/tmp/{MODULE}" />
+ <option name="push-file"
+ key="https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.1.zip?unzip=true"
+ value="/data/local/tmp/TranscodingBenchmark/" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GoogleBenchmarkTest" >
+ <option name="native-benchmark-device-path" value="/data/local/tmp" />
+ <option name="benchmark-module-name" value="{MODULE}" />
+ </test>
+</configuration>
+
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp b/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
index 351d80b..d6ed2c6 100644
--- a/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
+++ b/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
@@ -167,6 +167,10 @@
return AMEDIA_OK;
}
+ media_status_t unselectTrack(int trackIndex __unused) override {
+ return AMEDIA_ERROR_UNSUPPORTED;
+ }
+
media_status_t setEnforceSequentialAccess(bool enforce __unused) override { return AMEDIA_OK; }
media_status_t getEstimatedBitrateForTrack(int trackIndex __unused,
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp b/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
index 93a08d1..d47a30c 100644
--- a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
+++ b/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
@@ -30,11 +30,15 @@
*/
#include <benchmark/benchmark.h>
+#include <binder/ProcessState.h>
#include <fcntl.h>
#include <media/MediaTranscoder.h>
+#include <iostream>
using namespace android;
+const std::string PARAM_VIDEO_FRAME_RATE = "VideoFrameRate";
+
class TranscoderCallbacks : public MediaTranscoder::CallbackInterface {
public:
virtual void onFinished(const MediaTranscoder* transcoder __unused) override {
@@ -110,7 +114,6 @@
std::string srcPath = kAssetDirectory + srcFileName;
std::string dstPath = kAssetDirectory + dstFileName;
- auto callbacks = std::make_shared<TranscoderCallbacks>();
media_status_t status = AMEDIA_OK;
if ((srcFd = open(srcPath.c_str(), O_RDONLY)) < 0) {
@@ -123,6 +126,7 @@
}
for (auto _ : state) {
+ auto callbacks = std::make_shared<TranscoderCallbacks>();
auto transcoder = MediaTranscoder::create(callbacks);
status = transcoder->configureSource(srcFd);
@@ -151,8 +155,8 @@
if (strncmp(mime, "video/", 6) == 0) {
int32_t frameCount;
if (AMediaFormat_getInt32(srcFormat, AMEDIAFORMAT_KEY_FRAME_COUNT, &frameCount)) {
- state.counters["VideoFrameRate"] =
- benchmark::Counter(frameCount, benchmark::Counter::kIsRate);
+ state.counters[PARAM_VIDEO_FRAME_RATE] = benchmark::Counter(
+ frameCount, benchmark::Counter::kIsIterationInvariantRate);
}
}
@@ -332,4 +336,70 @@
TRANSCODER_BENCHMARK(BM_TranscodeAudioVideoPassthrough);
TRANSCODER_BENCHMARK(BM_TranscodeVideoPassthrough);
-BENCHMARK_MAIN();
+class CustomCsvReporter : public benchmark::BenchmarkReporter {
+public:
+ CustomCsvReporter() : mPrintedHeader(false) {}
+ virtual bool ReportContext(const Context& context);
+ virtual void ReportRuns(const std::vector<Run>& reports);
+
+private:
+ void PrintRunData(const Run& report);
+
+ bool mPrintedHeader;
+ std::vector<std::string> mHeaders = {"name", "real_time", "cpu_time", PARAM_VIDEO_FRAME_RATE};
+};
+
+bool CustomCsvReporter::ReportContext(const Context& context __unused) {
+ return true;
+}
+
+void CustomCsvReporter::ReportRuns(const std::vector<Run>& reports) {
+ std::ostream& Out = GetOutputStream();
+
+ if (!mPrintedHeader) {
+ // print the header
+ for (auto header = mHeaders.begin(); header != mHeaders.end();) {
+ Out << *header++;
+ if (header != mHeaders.end()) Out << ",";
+ }
+ Out << "\n";
+ mPrintedHeader = true;
+ }
+
+ // print results for each run
+ for (const auto& run : reports) {
+ PrintRunData(run);
+ }
+}
+
+void CustomCsvReporter::PrintRunData(const Run& run) {
+ if (run.error_occurred) {
+ return;
+ }
+ std::ostream& Out = GetOutputStream();
+ Out << run.benchmark_name() << ",";
+ Out << run.GetAdjustedRealTime() << ",";
+ Out << run.GetAdjustedCPUTime() << ",";
+ auto frameRate = run.counters.find(PARAM_VIDEO_FRAME_RATE);
+ if (frameRate == run.counters.end()) {
+ Out << "NA"
+ << ",";
+ } else {
+ Out << frameRate->second << ",";
+ }
+ Out << '\n';
+}
+
+int main(int argc, char** argv) {
+ android::ProcessState::self()->startThreadPool();
+ std::unique_ptr<benchmark::BenchmarkReporter> fileReporter;
+ for (int i = 1; i < argc; ++i) {
+ if (std::string(argv[i]).find("--benchmark_out") != std::string::npos) {
+ fileReporter.reset(new CustomCsvReporter);
+ break;
+ }
+ }
+ ::benchmark::Initialize(&argc, argv);
+ if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
+ ::benchmark::RunSpecifiedBenchmarks(nullptr, fileReporter.get());
+}
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h b/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
index 7b6fbef..5c7eeac 100644
--- a/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
+++ b/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
@@ -69,6 +69,13 @@
virtual media_status_t selectTrack(int trackIndex) = 0;
/**
+ * Undo a track selection.
+ * @param trackIndex The track to un-select.
+ * @return AMEDIA_OK on success.
+ */
+ virtual media_status_t unselectTrack(int trackIndex) = 0;
+
+ /**
* Toggles sequential access enforcement on or off. When the reader enforces sequential access
* calls to read sample information will block unless the underlying extractor points to the
* specified track.
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h b/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
index 2032def..30cc37f 100644
--- a/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
+++ b/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
@@ -48,6 +48,7 @@
size_t getTrackCount() const override;
AMediaFormat* getTrackFormat(int trackIndex) override;
media_status_t selectTrack(int trackIndex) override;
+ media_status_t unselectTrack(int trackIndex) override;
media_status_t setEnforceSequentialAccess(bool enforce) override;
media_status_t getEstimatedBitrateForTrack(int trackIndex, int32_t* bitrate) override;
media_status_t getSampleInfoForTrack(int trackIndex, MediaSampleInfo* info) override;
diff --git a/media/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h b/media/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h
index d2ffb01..e3f3f4f 100644
--- a/media/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h
+++ b/media/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h
@@ -97,8 +97,12 @@
BlockingQueue<std::function<void()>> mCodecMessageQueue;
std::shared_ptr<AMediaFormat> mDestinationFormat;
std::shared_ptr<AMediaFormat> mActualOutputFormat;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-private-field"
+ // These could be unused on older platforms
pid_t mPid;
uid_t mUid;
+#pragma clang diagnostic pop
};
} // namespace android
diff --git a/media/libmediatranscoding/transcoder/setloglevel.sh b/media/libmediatranscoding/transcoder/setloglevel.sh
new file mode 100755
index 0000000..5eb7b67
--- /dev/null
+++ b/media/libmediatranscoding/transcoder/setloglevel.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+if [ $# -ne 1 ]
+then
+ echo Usage: $0 loglevel
+ exit 1
+fi
+
+level=$1
+echo Setting transcoder log level to $level
+
+# List all log tags
+declare -a tags=(
+ MediaTranscoder MediaTrackTranscoder VideoTrackTranscoder PassthroughTrackTranscoder
+ MediaSampleWriter MediaSampleReader MediaSampleQueue MediaTranscoderTests
+ MediaTrackTranscoderTests VideoTrackTranscoderTests PassthroughTrackTranscoderTests
+ MediaSampleWriterTests MediaSampleReaderNDKTests MediaSampleQueueTests)
+
+# Set log level for all tags
+for tag in "${tags[@]}"
+do
+ adb shell setprop log.tag.${tag} $level
+done
+
+# Pick up new settings
+adb shell stop && adb shell start
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
index 5c59992..bfc1f3b 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
@@ -283,20 +283,22 @@
}
EXPECT_NE(videoFormat, nullptr);
+ if (videoFormat != nullptr) {
+ LOG(INFO) << "source video format: " << AMediaFormat_toString(mSourceVideoFormat.get());
+ LOG(INFO) << "transcoded video format: " << AMediaFormat_toString(videoFormat.get());
- LOG(INFO) << "source video format: " << AMediaFormat_toString(mSourceVideoFormat.get());
- LOG(INFO) << "transcoded video format: " << AMediaFormat_toString(videoFormat.get());
+ for (int i = 0; i < (sizeof(kFieldsToPreserve) / sizeof(kFieldsToPreserve[0])); ++i) {
+ EXPECT_TRUE(kFieldsToPreserve[i].equal(kFieldsToPreserve[i].key,
+ mSourceVideoFormat.get(), videoFormat.get()))
+ << "Failed at key " << kFieldsToPreserve[i].key;
+ }
- for (int i = 0; i < (sizeof(kFieldsToPreserve) / sizeof(kFieldsToPreserve[0])); ++i) {
- EXPECT_TRUE(kFieldsToPreserve[i].equal(kFieldsToPreserve[i].key,
- mSourceVideoFormat.get(), videoFormat.get()))
- << "Failed at key " << kFieldsToPreserve[i].key;
- }
-
- if (extraVerifiers != nullptr) {
- for (int i = 0; i < extraVerifiers->size(); ++i) {
- const FormatVerifierEntry& entry = (*extraVerifiers)[i];
- EXPECT_TRUE(entry.equal(entry.key, mSourceVideoFormat.get(), videoFormat.get()));
+ if (extraVerifiers != nullptr) {
+ for (int i = 0; i < extraVerifiers->size(); ++i) {
+ const FormatVerifierEntry& entry = (*extraVerifiers)[i];
+ EXPECT_TRUE(
+ entry.equal(entry.key, mSourceVideoFormat.get(), videoFormat.get()));
+ }
}
}
diff --git a/media/libmediatranscoding/transcoder/tests/fuzzer/Android.bp b/media/libmediatranscoding/transcoder/tests/fuzzer/Android.bp
new file mode 100644
index 0000000..3ae349b
--- /dev/null
+++ b/media/libmediatranscoding/transcoder/tests/fuzzer/Android.bp
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_fuzz {
+ name: "media_transcoder_fuzzer",
+ srcs: [
+ "media_transcoder_fuzzer.cpp",
+ ],
+ static_libs: [
+ "liblog",
+ "libmediatranscoder",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libmediandk",
+ "libnativewindow",
+ "libutils",
+ ],
+ header_libs: [
+ "libcodec2_headers",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
diff --git a/media/libmediatranscoding/transcoder/tests/fuzzer/README.md b/media/libmediatranscoding/transcoder/tests/fuzzer/README.md
new file mode 100644
index 0000000..d376a20
--- /dev/null
+++ b/media/libmediatranscoding/transcoder/tests/fuzzer/README.md
@@ -0,0 +1,59 @@
+# Fuzzer for libmediatranscoder
+
+## Plugin Design Considerations
+The fuzzer plugin for libmediatranscoder is designed based on the understanding of the
+transcoder and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+Transcoder supports the following parameters:
+1. Destination Mime Type (parameter name: `dstMime`)
+2. AVC Profile (parameter name: `profile`)
+3. HEVC Profile (parameter name: `profile`)
+4. AVC Level (parameter name: `level`)
+5. HEVC Level (parameter name: `level`)
+6. Bitrate (parameter name: `bitrate`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `dstMime` | 0. `AMEDIA_MIMETYPE_VIDEO_AVC` 1. `AMEDIA_MIMETYPE_VIDEO_HEVC` | Bit 0 (LSB) of 1st byte of data |
+| `profile` for AVC | 0. `PROFILE_AVC_BASELINE` 1. `PROFILE_AVC_CONSTRAINED_BASELINE` 2. `PROFILE_AVC_MAIN`| All bits of 2nd byte of data modulus 3 |
+| `profile` for HEVC | 0. `PROFILE_HEVC_MAIN` 1. `PROFILE_HEVC_MAIN_STILL` | All bits of 2nd byte of data modulus 2 |
+| `level` for AVC | 0. `LEVEL_AVC_1` 1. `LEVEL_AVC_1B` 2. `LEVEL_AVC_1_1` 3. `LEVEL_AVC_1_2` 4. `LEVEL_AVC_1_3` 5. `LEVEL_AVC_2` 6. `LEVEL_AVC_2_1` 7. `LEVEL_AVC_2_2` 8. `LEVEL_AVC_3` 9. `LEVEL_AVC_3_1` 10. `LEVEL_AVC_3_2` 11. `LEVEL_AVC_4` 12. `LEVEL_AVC_4_1` 13. `LEVEL_AVC_4_2` 14. `LEVEL_AVC_5`| All bits of 3rd byte of data modulus 15 |
+| `level` for HEVC | 0. `LEVEL_HEVC_MAIN_1` 1. `LEVEL_HEVC_MAIN_2` 2. `LEVEL_HEVC_MAIN_2_1` 3. `LEVEL_HEVC_MAIN_3` 4. `LEVEL_HEVC_MAIN_3_1` 5. `LEVEL_HEVC_MAIN_4` 6. `LEVEL_HEVC_MAIN_4_1` 7. `LEVEL_HEVC_MAIN_5` 8. `LEVEL_HEVC_MAIN_5_1` 9. `LEVEL_HEVC_MAIN_5_2` | All bits of 3rd byte of data modulus 10 |
+| `bitrate` | In the range `0` to `500000000` | All bits of 4th and 5th byte of data |
+
+This also ensures that the plugin is always deterministic for any given input.
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the transcoder.
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build media_transcoder_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) media_transcoder_fuzzer
+```
+#### Steps to run
+Create a directory CORPUS_DIR
+```
+ $ adb shell mkdir CORPUS_DIR
+```
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/${TARGET_ARCH}/media_transcoder_fuzzer/media_transcoder_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/media/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp b/media/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp
new file mode 100644
index 0000000..48d3406
--- /dev/null
+++ b/media/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp
@@ -0,0 +1,209 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <C2Config.h>
+#include <android/binder_process.h>
+#include <fcntl.h>
+#include <media/MediaTranscoder.h>
+#include <media/NdkCommon.h>
+#include <stdio.h>
+
+#define UNUSED_PARAM __attribute__((unused))
+#define SRC_FILE "sourceTranscodingFile"
+#define DEST_FILE "destTranscodingFile"
+
+using namespace std;
+using namespace android;
+
+const char* kMimeType[] = {AMEDIA_MIMETYPE_VIDEO_AVC, AMEDIA_MIMETYPE_VIDEO_HEVC};
+const C2Config::profile_t kAvcProfile[] = {C2Config::PROFILE_AVC_BASELINE,
+ C2Config::PROFILE_AVC_CONSTRAINED_BASELINE,
+ C2Config::PROFILE_AVC_MAIN};
+const C2Config::level_t kAvcLevel[] = {
+ C2Config::LEVEL_AVC_1, C2Config::LEVEL_AVC_1B, C2Config::LEVEL_AVC_1_1,
+ C2Config::LEVEL_AVC_1_2, C2Config::LEVEL_AVC_1_3, C2Config::LEVEL_AVC_2,
+ C2Config::LEVEL_AVC_2_1, C2Config::LEVEL_AVC_2_2, C2Config::LEVEL_AVC_3,
+ C2Config::LEVEL_AVC_3_1, C2Config::LEVEL_AVC_3_2, C2Config::LEVEL_AVC_4,
+ C2Config::LEVEL_AVC_4_1, C2Config::LEVEL_AVC_4_2, C2Config::LEVEL_AVC_5,
+};
+const C2Config::profile_t kHevcProfile[] = {C2Config::PROFILE_HEVC_MAIN,
+ C2Config::PROFILE_HEVC_MAIN_STILL};
+const C2Config::level_t kHevcLevel[] = {
+ C2Config::LEVEL_HEVC_MAIN_1, C2Config::LEVEL_HEVC_MAIN_2, C2Config::LEVEL_HEVC_MAIN_2_1,
+ C2Config::LEVEL_HEVC_MAIN_3, C2Config::LEVEL_HEVC_MAIN_3_1, C2Config::LEVEL_HEVC_MAIN_4,
+ C2Config::LEVEL_HEVC_MAIN_4_1, C2Config::LEVEL_HEVC_MAIN_5, C2Config::LEVEL_HEVC_MAIN_5_1,
+ C2Config::LEVEL_HEVC_MAIN_5_2};
+const size_t kNumAvcProfile = size(kAvcProfile);
+const size_t kNumAvcLevel = size(kAvcLevel);
+const size_t kNumHevcProfile = size(kHevcProfile);
+const size_t kNumHevcLevel = size(kHevcLevel);
+const size_t kMaxBitrate = 500000000;
+
+enum {
+ IDX_MIME_TYPE = 0,
+ IDX_PROFILE,
+ IDX_LEVEL,
+ IDX_BITRATE_BYTE_1,
+ IDX_BITRATE_BYTE_2,
+ IDX_LAST
+};
+
+class TestCallbacks : public MediaTranscoder::CallbackInterface {
+public:
+ virtual void onFinished(const MediaTranscoder* transcoder UNUSED_PARAM) override {
+ unique_lock<mutex> lock(mMutex);
+ mFinished = true;
+ mCondition.notify_all();
+ }
+
+ virtual void onError(const MediaTranscoder* transcoder UNUSED_PARAM,
+ media_status_t error UNUSED_PARAM) override {
+ unique_lock<mutex> lock(mMutex);
+ mFinished = true;
+ mCondition.notify_all();
+ }
+
+ virtual void onProgressUpdate(const MediaTranscoder* transcoder UNUSED_PARAM,
+ int32_t progress) override {
+ unique_lock<mutex> lock(mMutex);
+ if (progress > 0 && !mProgressMade) {
+ mProgressMade = true;
+ mCondition.notify_all();
+ }
+ }
+
+ virtual void onCodecResourceLost(const MediaTranscoder* transcoder UNUSED_PARAM,
+ const shared_ptr<ndk::ScopedAParcel>& pausedState
+ UNUSED_PARAM) override {}
+
+ void waitForTranscodingFinished() {
+ unique_lock<mutex> lock(mMutex);
+ while (!mFinished) {
+ mCondition.wait(lock);
+ }
+ }
+
+private:
+ mutex mMutex;
+ condition_variable mCondition;
+ bool mFinished = false;
+ bool mProgressMade = false;
+};
+
+class MediaTranscoderFuzzer {
+public:
+ void init();
+ void invokeTranscoder(const uint8_t* data, size_t size);
+ void deInit();
+
+private:
+ AMediaFormat* getFormat(AMediaFormat* sourceFormat) {
+ AMediaFormat* format = nullptr;
+ const char* mime = nullptr;
+ AMediaFormat_getString(sourceFormat, AMEDIAFORMAT_KEY_MIME, &mime);
+ if (mime != nullptr) {
+ if (strncmp(mime, "video/", 6) == 0 && (mDestMime != nullptr)) {
+ format = AMediaFormat_new();
+ AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, mDestMime);
+ AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_PROFILE, mProfile);
+ AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_LEVEL, mLevel);
+ AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, mBitrate);
+ AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_OPERATING_RATE, INT32_MAX);
+ AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_PRIORITY, 1);
+ }
+ }
+ return format;
+ }
+
+ shared_ptr<TestCallbacks> mCallbacks;
+ int mSrcFd = 0;
+ int mDestFd = 0;
+ const char* mDestMime;
+ C2Config::profile_t mProfile;
+ C2Config::level_t mLevel;
+ uint64_t mBitrate = 0;
+};
+
+void MediaTranscoderFuzzer::init() {
+ mCallbacks = make_shared<TestCallbacks>();
+ ABinderProcess_startThreadPool();
+}
+
+void MediaTranscoderFuzzer::deInit() {
+ mCallbacks.reset();
+ if (mSrcFd) {
+ close(mSrcFd);
+ }
+ if (mDestFd) {
+ close(mDestFd);
+ }
+}
+
+void MediaTranscoderFuzzer::invokeTranscoder(const uint8_t* data, size_t size) {
+ auto transcoder = MediaTranscoder::create(mCallbacks);
+ if (transcoder == nullptr) {
+ return;
+ }
+
+ mDestMime = kMimeType[data[IDX_MIME_TYPE] & 0x01];
+ mBitrate = (((data[IDX_BITRATE_BYTE_1] << 8) | data[IDX_BITRATE_BYTE_2]) * 1000) % kMaxBitrate;
+ if (mDestMime == AMEDIA_MIMETYPE_VIDEO_AVC) {
+ mProfile = kAvcProfile[data[IDX_PROFILE] % kNumAvcProfile];
+ mLevel = kAvcLevel[data[IDX_LEVEL] % kNumAvcLevel];
+ } else {
+ mProfile = kHevcProfile[data[IDX_PROFILE] % kNumHevcProfile];
+ mLevel = kHevcLevel[data[IDX_LEVEL] % kNumHevcLevel];
+ }
+
+ data += IDX_LAST;
+ size -= IDX_LAST;
+
+ mSrcFd = memfd_create(SRC_FILE, MFD_ALLOW_SEALING);
+ write(mSrcFd, data, size);
+
+ transcoder->configureSource(mSrcFd);
+ vector<shared_ptr<AMediaFormat>> trackFormats = transcoder->getTrackFormats();
+ for (int i = 0; i < trackFormats.size(); ++i) {
+ AMediaFormat* format = getFormat(trackFormats[i].get());
+ transcoder->configureTrackFormat(i, format);
+
+ if (format != nullptr) {
+ AMediaFormat_delete(format);
+ }
+ }
+ mDestFd = memfd_create(DEST_FILE, MFD_ALLOW_SEALING);
+ transcoder->configureDestination(mDestFd);
+ if (transcoder->start() == AMEDIA_OK) {
+ mCallbacks->waitForTranscodingFinished();
+ transcoder->cancel();
+ }
+ close(mSrcFd);
+ close(mDestFd);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ if (size < IDX_LAST + 1) {
+ return 0;
+ }
+ MediaTranscoderFuzzer transcoderFuzzer;
+ transcoderFuzzer.init();
+ transcoderFuzzer.invokeTranscoder(data, size);
+ transcoderFuzzer.deInit();
+ return 0;
+}
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 71c1b0b..8f1da0d 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -7078,10 +7078,9 @@
return err;
}
- using hardware::media::omx::V1_0::utils::TWOmxNode;
err = statusFromBinderStatus(
mCodec->mGraphicBufferSource->configure(
- new TWOmxNode(mCodec->mOMXNode),
+ mCodec->mOMXNode->getHalInterface<IOmxNode>(),
static_cast<hardware::graphics::common::V1_0::Dataspace>(dataSpace)));
if (err != OK) {
ALOGE("[%s] Unable to configure for node (err %d)",
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index e783578..d11408d 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -44,7 +44,7 @@
namespace android {
static const int64_t kBufferTimeOutUs = 10000LL; // 10 msec
-static const size_t kRetryCount = 50; // must be >0
+static const size_t kRetryCount = 100; // must be >0
static const int64_t kDefaultSampleDurationUs = 33333LL; // 33ms
sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta,
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 0af97df..447d599 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -1137,11 +1137,24 @@
if (!truncatePreAllocation()) {
if (err == OK) { err = ERROR_IO; }
}
+
+ // TODO(b/174770856) remove this measurement (and perhaps the fsync)
+ nsecs_t sync_started = systemTime(SYSTEM_TIME_REALTIME);
if (fsync(mFd) != 0) {
ALOGW("(ignored)fsync err:%s(%d)", std::strerror(errno), errno);
// Don't bubble up fsync error, b/157291505.
// if (err == OK) { err = ERROR_IO; }
}
+ nsecs_t sync_finished = systemTime(SYSTEM_TIME_REALTIME);
+ nsecs_t sync_elapsed_ns = sync_finished - sync_started;
+ int64_t filesize = -1;
+ struct stat statbuf;
+ if (fstat(mFd, &statbuf) == 0) {
+ filesize = statbuf.st_size;
+ }
+ ALOGD("final fsync() takes %" PRId64 " ms, file size %" PRId64,
+ sync_elapsed_ns / 1000000, (int64_t) filesize);
+
if (close(mFd) != 0) {
ALOGE("close err:%s(%d)", std::strerror(errno), errno);
if (err == OK) { err = ERROR_IO; }
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index da8f024..358c5e3 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -19,6 +19,8 @@
#define LOG_TAG "MediaCodec"
#include <utils/Log.h>
+#include <set>
+
#include <inttypes.h>
#include <stdlib.h>
@@ -202,6 +204,10 @@
// implements DeathRecipient
static void BinderDiedCallback(void* cookie);
void binderDied();
+ static Mutex sLockCookies;
+ static std::set<void*> sCookies;
+ static void addCookie(void* cookie);
+ static void removeCookie(void* cookie);
void addResource(const MediaResourceParcel &resource);
void removeResource(const MediaResourceParcel &resource);
@@ -228,8 +234,15 @@
}
MediaCodec::ResourceManagerServiceProxy::~ResourceManagerServiceProxy() {
+
+ // remove the cookie, so any in-flight death notification will get dropped
+ // by our handler.
+ removeCookie(this);
+
+ Mutex::Autolock _l(mLock);
if (mService != nullptr) {
AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
+ mService = nullptr;
}
}
@@ -241,16 +254,39 @@
return;
}
- AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
-
// Kill clients pending removal.
mService->reclaimResourcesFromClientsPendingRemoval(mPid);
+
+ // so our handler will process the death notifications
+ addCookie(this);
+
+ // after this, require mLock whenever using mService
+ AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
+}
+
+//static
+Mutex MediaCodec::ResourceManagerServiceProxy::sLockCookies;
+std::set<void*> MediaCodec::ResourceManagerServiceProxy::sCookies;
+
+//static
+void MediaCodec::ResourceManagerServiceProxy::addCookie(void* cookie) {
+ Mutex::Autolock _l(sLockCookies);
+ sCookies.insert(cookie);
+}
+
+//static
+void MediaCodec::ResourceManagerServiceProxy::removeCookie(void* cookie) {
+ Mutex::Autolock _l(sLockCookies);
+ sCookies.erase(cookie);
}
//static
void MediaCodec::ResourceManagerServiceProxy::BinderDiedCallback(void* cookie) {
- auto thiz = static_cast<ResourceManagerServiceProxy*>(cookie);
- thiz->binderDied();
+ Mutex::Autolock _l(sLockCookies);
+ if (sCookies.find(cookie) != sCookies.end()) {
+ auto thiz = static_cast<ResourceManagerServiceProxy*>(cookie);
+ thiz->binderDied();
+ }
}
void MediaCodec::ResourceManagerServiceProxy::binderDied() {
@@ -4094,7 +4130,15 @@
}
}
}
- mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
+ status_t err = mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
+
+ if (err == NO_INIT) {
+ ALOGE("rendering to non-initilized(obsolete) surface");
+ return err;
+ }
+ if (err != OK) {
+ ALOGI("rendring output error %d", err);
+ }
} else {
mBufferChannel->discardBuffer(buffer);
}
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index ac54fa1..799ca0d 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -209,9 +209,12 @@
ALOGD("ignored a null builder");
continue;
}
- mInitCheck = builder->buildMediaCodecList(&writer);
- if (mInitCheck != OK) {
- break;
+ auto currentCheck = builder->buildMediaCodecList(&writer);
+ if (currentCheck != OK) {
+ ALOGD("ignored failed builder");
+ continue;
+ } else {
+ mInitCheck = currentCheck;
}
}
writer.writeGlobalSettings(mGlobalSettings);
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 6245014..f2c7dd6 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -50,8 +50,9 @@
mSampleTimeUs(timeUs) {
}
-NuMediaExtractor::NuMediaExtractor()
- : mTotalBitrate(-1LL),
+NuMediaExtractor::NuMediaExtractor(EntryPoint entryPoint)
+ : mEntryPoint(entryPoint),
+ mTotalBitrate(-1LL),
mDurationUs(-1LL) {
}
@@ -93,6 +94,7 @@
if (mImpl == NULL) {
return ERROR_UNSUPPORTED;
}
+ setEntryPointToRemoteMediaExtractor();
status_t err = OK;
if (!mCasToken.empty()) {
@@ -134,6 +136,7 @@
if (mImpl == NULL) {
return ERROR_UNSUPPORTED;
}
+ setEntryPointToRemoteMediaExtractor();
if (!mCasToken.empty()) {
err = mImpl->setMediaCas(mCasToken);
@@ -168,6 +171,7 @@
if (mImpl == NULL) {
return ERROR_UNSUPPORTED;
}
+ setEntryPointToRemoteMediaExtractor();
if (!mCasToken.empty()) {
err = mImpl->setMediaCas(mCasToken);
@@ -489,6 +493,16 @@
}
}
+void NuMediaExtractor::setEntryPointToRemoteMediaExtractor() {
+ if (mImpl == NULL) {
+ return;
+ }
+ status_t err = mImpl->setEntryPoint(mEntryPoint);
+ if (err != OK) {
+ ALOGW("Failed to set entry point with error %d.", err);
+ }
+}
+
ssize_t NuMediaExtractor::fetchAllTrackSamples(
int64_t seekTimeUs, MediaSource::ReadOptions::SeekMode mode) {
TrackInfo *minInfo = NULL;
diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp
index 25e43c2..381eb1a 100644
--- a/media/libstagefright/RemoteMediaExtractor.cpp
+++ b/media/libstagefright/RemoteMediaExtractor.cpp
@@ -39,6 +39,12 @@
static const char *kExtractorFormat = "android.media.mediaextractor.fmt";
static const char *kExtractorMime = "android.media.mediaextractor.mime";
static const char *kExtractorTracks = "android.media.mediaextractor.ntrk";
+static const char *kExtractorEntryPoint = "android.media.mediaextractor.entry";
+
+static const char *kEntryPointSdk = "sdk";
+static const char *kEntryPointWithJvm = "ndk-with-jvm";
+static const char *kEntryPointNoJvm = "ndk-no-jvm";
+static const char *kEntryPointOther = "other";
RemoteMediaExtractor::RemoteMediaExtractor(
MediaExtractor *extractor,
@@ -74,6 +80,9 @@
}
// what else is interesting and not already available?
}
+ // By default, we set the entry point to be "other". Clients of this
+ // class will override this value by calling setEntryPoint.
+ mMetricsItem->setCString(kExtractorEntryPoint, kEntryPointOther);
}
}
@@ -143,6 +152,28 @@
return String8(mExtractor->name());
}
+status_t RemoteMediaExtractor::setEntryPoint(EntryPoint entryPoint) {
+ const char* entryPointString;
+ switch (entryPoint) {
+ case EntryPoint::SDK:
+ entryPointString = kEntryPointSdk;
+ break;
+ case EntryPoint::NDK_WITH_JVM:
+ entryPointString = kEntryPointWithJvm;
+ break;
+ case EntryPoint::NDK_NO_JVM:
+ entryPointString = kEntryPointNoJvm;
+ break;
+ case EntryPoint::OTHER:
+ entryPointString = kEntryPointOther;
+ break;
+ default:
+ return BAD_VALUE;
+ }
+ mMetricsItem->setCString(kExtractorEntryPoint, entryPointString);
+ return OK;
+}
+
////////////////////////////////////////////////////////////////////////////////
// static
diff --git a/media/libstagefright/TEST_MAPPING b/media/libstagefright/TEST_MAPPING
index 76fc74f..dff7b22 100644
--- a/media/libstagefright/TEST_MAPPING
+++ b/media/libstagefright/TEST_MAPPING
@@ -11,7 +11,7 @@
],
- "presubmit": [
+ "presubmit-large": [
{
"name": "CtsMediaTestCases",
"options": [
@@ -29,7 +29,9 @@
"exclude-filter": "android.media.cts.AudioRecordTest"
}
]
- },
+ }
+ ],
+ "presubmit": [
{
"name": "mediacodecTest"
}
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 48b3255..f63740e 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -729,6 +729,8 @@
{
{ "exif-offset", kKeyExifOffset },
{ "exif-size", kKeyExifSize },
+ { "xmp-offset", kKeyXmpOffset },
+ { "xmp-size", kKeyXmpSize },
{ "target-time", kKeyTargetTime },
{ "thumbnail-time", kKeyThumbnailTime },
{ "timeUs", kKeyTime },
@@ -2192,7 +2194,7 @@
#ifdef DISABLE_AUDIO_SYSTEM_OFFLOAD
return false;
#else
- return AudioSystem::isOffloadSupported(info);
+ return AudioSystem::getOffloadSupport(info) != AUDIO_OFFLOAD_NOT_SUPPORTED;
#endif
}
diff --git a/media/libstagefright/bqhelper/Android.bp b/media/libstagefright/bqhelper/Android.bp
index 8698d33..2b0494c 100644
--- a/media/libstagefright/bqhelper/Android.bp
+++ b/media/libstagefright/bqhelper/Android.bp
@@ -101,6 +101,7 @@
"//apex_available:platform",
],
vendor_available: false,
+ min_sdk_version: "29",
static_libs: [
"libgui_bufferqueue_static",
],
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 28a7a1e..92ec94f 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -1247,6 +1247,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
index 6e437cf..90421b9 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
@@ -732,6 +732,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index cdfc03a..01da3f8 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -576,6 +576,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
index 85ab64e..a1f6686 100644
--- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
@@ -421,6 +421,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
index 7fb8a4c..657a5ce 100644
--- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
@@ -476,6 +476,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/avcdec/Android.bp b/media/libstagefright/codecs/avcdec/Android.bp
index 0bb6bb0..61379d2 100644
--- a/media/libstagefright/codecs/avcdec/Android.bp
+++ b/media/libstagefright/codecs/avcdec/Android.bp
@@ -16,6 +16,12 @@
"signed-integer-overflow",
],
cfi: true,
+ diag: {
+ cfi: true,
+ },
+ config: {
+ cfi_assembly_support: true,
+ },
},
ldflags: ["-Wl,-Bsymbolic"],
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index 5a4b2f8..3891f23 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -724,6 +724,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/avcenc/Android.bp b/media/libstagefright/codecs/avcenc/Android.bp
index 980261c..aceaebf 100644
--- a/media/libstagefright/codecs/avcenc/Android.bp
+++ b/media/libstagefright/codecs/avcenc/Android.bp
@@ -10,6 +10,12 @@
"signed-integer-overflow",
],
cfi: true,
+ diag: {
+ cfi: true,
+ },
+ config: {
+ cfi_assembly_support: true,
+ },
},
cflags: [
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
index 9db6465..01174c9 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
@@ -1507,6 +1507,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
index 842a7ce..d6448d3 100644
--- a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
+++ b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
@@ -491,6 +491,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
index 078c8e3..24216a2 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
@@ -592,6 +592,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
index 877cb5a..fe91510 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -382,6 +382,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
index d777229..330cb8a 100644
--- a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
+++ b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
@@ -354,6 +354,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
index f6ae1f4..176da47 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
@@ -713,6 +713,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(const char *name,
const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index 60750d9..a4b3e2f 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -412,6 +412,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index fa7db81..fb6c4e2 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -528,6 +528,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index 15cde20..07bb45a 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -498,6 +498,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
index 9d5f342..9f8001f 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
@@ -864,6 +864,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
index 0f2ff17..bffc23a 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -355,6 +355,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index d0cb071..e9b4341 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -775,6 +775,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
index 5bb1879..dcd8dda 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -666,6 +666,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/raw/SoftRaw.cpp b/media/libstagefright/codecs/raw/SoftRaw.cpp
index 0e31804..82dd171 100644
--- a/media/libstagefright/codecs/raw/SoftRaw.cpp
+++ b/media/libstagefright/codecs/raw/SoftRaw.cpp
@@ -273,6 +273,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 08e20cc..3daed10 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -636,6 +636,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/xaacdec/Android.bp b/media/libstagefright/codecs/xaacdec/Android.bp
index 5385dbc..2d90910 100644
--- a/media/libstagefright/codecs/xaacdec/Android.bp
+++ b/media/libstagefright/codecs/xaacdec/Android.bp
@@ -14,6 +14,12 @@
// integer_overflow: true,
misc_undefined: [ "signed-integer-overflow", "unsigned-integer-overflow", ],
cfi: true,
+ diag: {
+ cfi: true,
+ },
+ config: {
+ cfi_assembly_support: true,
+ },
},
static_libs: ["libxaacdec"],
diff --git a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
index 87e8fd4..a478642 100644
--- a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
+++ b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
@@ -1693,6 +1693,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent* createSoftOMXComponent(const char* name,
const OMX_CALLBACKTYPE* callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE** component) {
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 7752bda..f242b19 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -33,7 +33,7 @@
#include <media/stagefright/foundation/hexdump.h>
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
#include <binder/Parcel.h>
#endif
@@ -646,7 +646,7 @@
return s;
}
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
// static
sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) {
int32_t what = parcel.readInt32();
@@ -813,7 +813,7 @@
}
}
}
-#endif // __ANDROID_VNDK__
+#endif // !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) const {
if (other == NULL) {
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
index 8722e14..b1ed077 100644
--- a/media/libstagefright/foundation/AString.cpp
+++ b/media/libstagefright/foundation/AString.cpp
@@ -27,7 +27,7 @@
#include "ADebug.h"
#include "AString.h"
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
#include <binder/Parcel.h>
#endif
@@ -365,7 +365,7 @@
return !strcasecmp(mData + mSize - suffixLen, suffix);
}
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
// static
AString AString::FromParcel(const Parcel &parcel) {
size_t size = static_cast<size_t>(parcel.readInt32());
@@ -380,7 +380,7 @@
}
return err;
}
-#endif
+#endif // !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
AString AStringPrintf(const char *format, ...) {
va_list ap;
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index ebf1035..39670a2 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -86,6 +86,11 @@
"-DNO_IMEMORY",
],
},
+ apex: {
+ exclude_shared_libs: [
+ "libbinder",
+ ],
+ },
darwin: {
enabled: false,
},
diff --git a/media/libstagefright/foundation/MediaBuffer.cpp b/media/libstagefright/foundation/MediaBuffer.cpp
index 8e245dc..68df21f 100644
--- a/media/libstagefright/foundation/MediaBuffer.cpp
+++ b/media/libstagefright/foundation/MediaBuffer.cpp
@@ -51,12 +51,12 @@
mRangeLength(size),
mOwnsData(true),
mMetaData(new MetaDataBase) {
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
if (size < kSharedMemThreshold
|| std::atomic_load_explicit(&mUseSharedMemory, std::memory_order_seq_cst) == 0) {
#endif
mData = malloc(size);
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
} else {
ALOGV("creating memoryDealer");
size_t newSize = 0;
diff --git a/media/libstagefright/foundation/MediaBufferGroup.cpp b/media/libstagefright/foundation/MediaBufferGroup.cpp
index 3c25047..fc98f28 100644
--- a/media/libstagefright/foundation/MediaBufferGroup.cpp
+++ b/media/libstagefright/foundation/MediaBufferGroup.cpp
@@ -62,7 +62,7 @@
mInternal->mGrowthLimit = buffers;
}
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
if (buffer_size >= kSharedMemoryThreshold) {
ALOGD("creating MemoryDealer");
// Using a single MemoryDealer is efficient for a group of shared memory objects.
diff --git a/media/libstagefright/foundation/MetaData.cpp b/media/libstagefright/foundation/MetaData.cpp
index 8174597..7f48cfd 100644
--- a/media/libstagefright/foundation/MetaData.cpp
+++ b/media/libstagefright/foundation/MetaData.cpp
@@ -28,7 +28,7 @@
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MetaData.h>
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
#include <binder/Parcel.h>
#endif
@@ -48,7 +48,7 @@
MetaData::~MetaData() {
}
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
/* static */
sp<MetaData> MetaData::createFromParcel(const Parcel &parcel) {
diff --git a/media/libstagefright/foundation/MetaDataBase.cpp b/media/libstagefright/foundation/MetaDataBase.cpp
index 4b439c6..3f050ea 100644
--- a/media/libstagefright/foundation/MetaDataBase.cpp
+++ b/media/libstagefright/foundation/MetaDataBase.cpp
@@ -28,7 +28,7 @@
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MetaDataBase.h>
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
#include <binder/Parcel.h>
#endif
@@ -452,7 +452,7 @@
}
}
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
status_t MetaDataBase::writeToParcel(Parcel &parcel) {
status_t ret;
size_t numItems = mInternalData->mItems.size();
@@ -532,7 +532,7 @@
ALOGW("no metadata in parcel");
return UNKNOWN_ERROR;
}
-#endif
+#endif // !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
} // namespace android
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
index b5d6666..31e58ba 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
@@ -63,7 +63,7 @@
AMessage();
AMessage(uint32_t what, const sp<const AHandler> &handler);
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
// Construct an AMessage from a parcel.
// nestingAllowed determines how many levels AMessage can be nested inside
// AMessage. The default value here is arbitrarily set to 255.
@@ -88,7 +88,7 @@
// All items in the AMessage must have types that are recognized by
// FromParcel(); otherwise, TRESPASS error will occur.
void writeToParcel(Parcel *parcel) const;
-#endif
+#endif // !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
void setWhat(uint32_t what);
uint32_t what() const;
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h
index deef0d4..517774b 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h
@@ -89,7 +89,7 @@
void tolower();
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
static AString FromParcel(const Parcel &parcel);
status_t writeToParcel(Parcel *parcel) const;
#endif
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 5509512..e97f6eb 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -813,6 +813,10 @@
baseSize = U32_AT(&mParent.mData[mOffset + 4]);
}
+ if (baseSize == 0) {
+ return;
+ }
+
// Prevent integer overflow when adding
if (SIZE_MAX - 10 <= baseSize) {
return;
diff --git a/media/libstagefright/id3/TEST_MAPPING b/media/libstagefright/id3/TEST_MAPPING
index d070d25..d82d26e 100644
--- a/media/libstagefright/id3/TEST_MAPPING
+++ b/media/libstagefright/id3/TEST_MAPPING
@@ -7,7 +7,7 @@
{ "name": "ID3Test" }
],
- "presubmit": [
+ "presubmit-large": [
// this doesn't seem to run any tests.
// but: cts-tradefed run -m CtsMediaTestCases -t android.media.cts.MediaMetadataRetrieverTest
// does run he 32 and 64 bit tests, but not the instant tests
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 4c97b4d..30bc44e 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -31,6 +31,7 @@
#include <OMX_Audio.h>
#include <hardware/gralloc.h>
#include <nativebase/nativebase.h>
+#include <android/hardware/graphics/common/1.2/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMemory.h>
@@ -54,6 +55,7 @@
struct DescribeColorFormat2Params;
struct DataConverter;
+using android::hardware::graphics::common::V1_2::BufferUsage;
typedef hidl::allocator::V1_0::IAllocator TAllocator;
typedef hidl::memory::V1_0::IMemory TMemory;
@@ -165,7 +167,8 @@
enum {
kVideoGrallocUsage = (GRALLOC_USAGE_HW_TEXTURE
| GRALLOC_USAGE_HW_COMPOSER
- | GRALLOC_USAGE_EXTERNAL_DISP),
+ | GRALLOC_USAGE_EXTERNAL_DISP)
+ | static_cast<uint64_t>(BufferUsage::VIDEO_DECODER),
};
struct BufferInfo {
diff --git a/media/libstagefright/include/media/stagefright/MediaBuffer.h b/media/libstagefright/include/media/stagefright/MediaBuffer.h
index 9145b63..2c03f27 100644
--- a/media/libstagefright/include/media/stagefright/MediaBuffer.h
+++ b/media/libstagefright/include/media/stagefright/MediaBuffer.h
@@ -46,7 +46,7 @@
explicit MediaBuffer(size_t size);
explicit MediaBuffer(const sp<ABuffer> &buffer);
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
MediaBuffer(const sp<IMemory> &mem) :
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
@@ -97,7 +97,7 @@
}
virtual int remoteRefcount() const {
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
// Either document why it is safe in this case or address the
@@ -114,7 +114,7 @@
// returns old value
int addRemoteRefcount(int32_t value) {
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
// Either document why it is safe in this case or address the
@@ -132,7 +132,7 @@
}
static bool isDeadObject(const sp<IMemory> &memory) {
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
// Either document why it is safe in this case or address the
@@ -235,7 +235,7 @@
};
inline SharedControl *getSharedControl() const {
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
// Either document why it is safe in this case or address the
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecList.h b/media/libstagefright/include/media/stagefright/MediaCodecList.h
index e681d25..78d1005 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecList.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecList.h
@@ -88,7 +88,7 @@
static sp<IMediaCodecList> sCodecList;
static sp<IMediaCodecList> sRemoteList;
- status_t mInitCheck;
+ status_t mInitCheck{NO_INIT};
sp<AMessage> mGlobalSettings;
std::vector<sp<MediaCodecInfo> > mCodecInfos;
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index f260510..940bd86 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -225,6 +225,8 @@
kKeyExifSize = 'exsz', // int64_t, Exif data size
kKeyExifTiffOffset = 'thdr', // int32_t, if > 0, buffer contains exif data block with
// tiff hdr at specified offset
+ kKeyXmpOffset = 'xmof', // int64_t, XMP data offset
+ kKeyXmpSize = 'xmsz', // int64_t, XMP data size
kKeyPcmBigEndian = 'pcmb', // bool (int32_t)
// Key for ALAC Magic Cookie
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index 227cead..d8f2b00 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -47,12 +47,14 @@
SAMPLE_FLAG_ENCRYPTED = 2,
};
+ typedef IMediaExtractor::EntryPoint EntryPoint;
+
// identical to IMediaExtractor::GetTrackMetaDataFlags
enum GetTrackFormatFlags {
kIncludeExtensiveMetaData = 1, // reads sample table and possibly stream headers
};
- NuMediaExtractor();
+ explicit NuMediaExtractor(EntryPoint entryPoint);
status_t setDataSource(
const sp<MediaHTTPService> &httpService,
@@ -128,6 +130,8 @@
uint32_t mTrackFlags; // bitmask of "TrackFlags"
};
+ const EntryPoint mEntryPoint;
+
mutable Mutex mLock;
sp<DataSource> mDataSource;
@@ -139,6 +143,8 @@
int64_t mTotalBitrate; // in bits/sec
int64_t mDurationUs;
+ void setEntryPointToRemoteMediaExtractor();
+
ssize_t fetchAllTrackSamples(
int64_t seekTimeUs = -1ll,
MediaSource::ReadOptions::SeekMode mode =
diff --git a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
index 2ce7bc7..25125f2 100644
--- a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
@@ -42,6 +42,7 @@
virtual uint32_t flags() const;
virtual status_t setMediaCas(const HInterfaceToken &casToken);
virtual String8 name();
+ virtual status_t setEntryPoint(EntryPoint entryPoint);
private:
MediaExtractor *mExtractor;
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index 62e3a4b..27a94fd 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -60,21 +60,23 @@
mIsAudio = false;
mIsVideo = false;
+ const char *mime;
- if (meta == NULL) {
+ // Do not use meta if no mime.
+ if (meta == NULL || !meta->findCString(kKeyMIMEType, &mime)) {
return;
}
mFormat = meta;
- const char *mime;
- CHECK(meta->findCString(kKeyMIMEType, &mime));
if (!strncasecmp("audio/", mime, 6)) {
mIsAudio = true;
- } else if (!strncasecmp("video/", mime, 6)) {
+ } else if (!strncasecmp("video/", mime, 6)) {
mIsVideo = true;
+ } else if (!strncasecmp("text/", mime, 5) || !strncasecmp("application/", mime, 12)) {
+ return;
} else {
- CHECK(!strncasecmp("text/", mime, 5) || !strncasecmp("application/", mime, 12));
+ ALOGW("Unsupported mime type: %s", mime);
}
}
diff --git a/media/libstagefright/renderfright/include/renderengine/RenderEngine.h b/media/libstagefright/renderfright/include/renderengine/RenderEngine.h
index 09a0f65..40fdff4 100644
--- a/media/libstagefright/renderfright/include/renderengine/RenderEngine.h
+++ b/media/libstagefright/renderfright/include/renderengine/RenderEngine.h
@@ -33,7 +33,7 @@
/**
* Allows to set RenderEngine backend to GLES (default) or Vulkan (NOT yet supported).
*/
-#define PROPERTY_DEBUG_RENDERENGINE_BACKEND "debug.renderengine.backend"
+#define PROPERTY_DEBUG_RENDERENGINE_BACKEND "debug.stagefright.renderengine.backend"
struct ANativeWindowBuffer;
diff --git a/media/libstagefright/renderfright/tests/RenderEngineTest.cpp b/media/libstagefright/renderfright/tests/RenderEngineTest.cpp
index 730f606..2697ff4 100644
--- a/media/libstagefright/renderfright/tests/RenderEngineTest.cpp
+++ b/media/libstagefright/renderfright/tests/RenderEngineTest.cpp
@@ -111,9 +111,9 @@
std::vector<uint8_t> outBuffer(mBuffer->getWidth() * mBuffer->getHeight() * 3);
auto outPtr = reinterpret_cast<uint8_t*>(outBuffer.data());
- for (int32_t j = 0; j < mBuffer->getHeight(); j++) {
+ for (uint32_t j = 0; j < mBuffer->getHeight(); j++) {
const uint8_t* src = pixels + (mBuffer->getStride() * j) * 4;
- for (int32_t i = 0; i < mBuffer->getWidth(); i++) {
+ for (uint32_t i = 0; i < mBuffer->getWidth(); i++) {
// Only copy R, G and B components
outPtr[0] = src[0];
outPtr[1] = src[1];
@@ -419,9 +419,9 @@
buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&pixels));
- for (int32_t j = 0; j < buf->getHeight(); j++) {
+ for (uint32_t j = 0; j < buf->getHeight(); j++) {
uint8_t* iter = pixels + (buf->getStride() * j) * 4;
- for (int32_t i = 0; i < buf->getWidth(); i++) {
+ for (uint32_t i = 0; i < buf->getWidth(); i++) {
iter[0] = uint8_t(r * 255);
iter[1] = uint8_t(g * 255);
iter[2] = uint8_t(b * 255);
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index f57077c..07f9dd3 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -131,7 +131,7 @@
unsigned start = (unsigned)((rand()* 1000LL)/RAND_MAX) + 15550;
start &= ~1;
- for (unsigned port = start; port < 65536; port += 2) {
+ for (unsigned port = start; port < 65535; port += 2) {
struct sockaddr_in addr;
memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
addr.sin_family = AF_INET;
@@ -149,6 +149,13 @@
(const struct sockaddr *)&addr, sizeof(addr)) == 0) {
*rtpPort = port;
return;
+ } else {
+ // we should recreate a RTP socket to avoid bind other port in same RTP socket
+ close(*rtpSocket);
+
+ *rtpSocket = socket(AF_INET, SOCK_DGRAM, 0);
+ CHECK_GE(*rtpSocket, 0);
+ bumpSocketBufferSize(*rtpSocket);
}
}
diff --git a/media/libstagefright/tests/Android.bp b/media/libstagefright/tests/Android.bp
index a7f94c1..5f3f72c 100644
--- a/media/libstagefright/tests/Android.bp
+++ b/media/libstagefright/tests/Android.bp
@@ -20,7 +20,7 @@
"frameworks/native/include/media/openmax",
],
- compile_multilib: "32",
+ compile_multilib: "prefer32",
cflags: [
"-Werror",
@@ -44,4 +44,4 @@
"-Werror",
"-Wall",
],
-}
\ No newline at end of file
+}
diff --git a/media/libstagefright/writer_fuzzers/Android.bp b/media/libstagefright/writer_fuzzers/Android.bp
new file mode 100644
index 0000000..224aeb3
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/Android.bp
@@ -0,0 +1,60 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+cc_defaults {
+ name: "writer-fuzzerbase-defaults",
+ local_include_dirs: [
+ "include",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
+ static_libs: [
+ "liblog",
+ "libstagefright_foundation",
+ "libstagefright",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "libutils",
+ ],
+}
+
+cc_defaults {
+ name: "writer-fuzzer-defaults",
+ defaults: ["writer-fuzzerbase-defaults"],
+ static_libs: [
+ "libwriterfuzzerbase",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
+
+cc_library_static {
+ name: "libwriterfuzzerbase",
+ defaults: ["writer-fuzzerbase-defaults"],
+ srcs: [
+ "WriterFuzzerBase.cpp",
+ ],
+}
diff --git a/media/libstagefright/writer_fuzzers/README.md b/media/libstagefright/writer_fuzzers/README.md
new file mode 100644
index 0000000..037236a
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/README.md
@@ -0,0 +1,46 @@
+# Fuzzer for writers
+
+## Table of contents
+ [libwriterfuzzerbase](#WriterFuzzerBase)
+
+# <a name="WriterFuzzerBase"></a> Fuzzer for libwriterfuzzerbase
+All the writers have a common API - creating a writer, adding a source for
+all the tracks, etc. These common APIs have been abstracted in a base class
+called `WriterFuzzerBase` to ensure code is reused between fuzzer plugins.
+
+## Plugin Design Considerations
+The fuzzer plugin for writers is designed based on the understanding of the
+writer and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+Fuzzer for writers supports the following parameters:
+1. Track Mime (parameter name: `mime`)
+2. Channel Count (parameter name: `channel-count`)
+3. Sample Rate (parameter name: `sample-rate`)
+4. Frame Height (parameter name: `height`)
+5. Frame Width (parameter name: `width`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `mime` | 0. `audio/3gpp` 1. `audio/amr-wb` 2. `audio/vorbis` 3. `audio/opus` 4. `audio/mp4a-latm` 5. `video/avc` 6. `video/hevc` 7. `video/mp4v-es` 8. `video/3gpp` 9. `video/x-vnd.on2.vp8` 10. `video/x-vnd.on2.vp9` | All the bits of 2nd byte of data for first track and 11th byte of data for second track (if present) modulus 10 |
+| `channel-count` | In the range `0 to INT32_MAX` | All the bits of 3rd byte to 6th bytes of data if first track is audio and 12th to 15th bytes of data if second track is audio |
+| `sample-rate` | In the range `1 to INT32_MAX` | All the bits of 7th byte to 10th bytes of data if first track is audio and 16th to 19th bytes of data if second track is audio |
+| `height` | In the range `0 to INT32_MAX` | All the bits of 3rd byte to 6th bytes of data if first track is video and 12th to 15th bytes of data if second track is video |
+| `width` | In the range `0 to INT32_MAX` | All the bits of 7th byte to 10th bytes of data if first track is video and 16th to 19th bytes of data if second track is video |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin divides the entire input data into frames based on frame markers.
+If no frame marker is found then the entire input data is treated as single frame.
+
+This ensures that the plugin tolerates any kind of input (huge,
+malformed, etc) and thereby increasing the chance of identifying vulnerabilities.
+
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
new file mode 100644
index 0000000..65593e7
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
@@ -0,0 +1,260 @@
+/*
+ * 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.
+ */
+#include <utils/Log.h>
+
+#include "WriterFuzzerBase.h"
+
+using namespace android;
+
+/**
+ * Buffer source implementations to parse input file
+ */
+
+uint32_t WriterFuzzerBase::BufferSource::getNumTracks() {
+ uint32_t numTracks = 0;
+ if (mSize > sizeof(uint8_t)) {
+ numTracks = min(mData[0], kMaxTrackCount);
+ mReadIndex += sizeof(uint8_t);
+ }
+ return numTracks;
+}
+
+bool WriterFuzzerBase::BufferSource::searchForMarker(size_t startIndex) {
+ while (true) {
+ if (isMarker()) {
+ return true;
+ }
+ --mReadIndex;
+ if (mReadIndex < startIndex) {
+ break;
+ }
+ }
+ return false;
+}
+
+ConfigFormat WriterFuzzerBase::BufferSource::getConfigFormat(int32_t trackIndex) {
+ return mParams[trackIndex];
+}
+
+int32_t WriterFuzzerBase::BufferSource::getNumCsds(int32_t trackIndex) {
+ return mNumCsds[trackIndex];
+}
+
+vector<FrameData> WriterFuzzerBase::BufferSource::getFrameList(int32_t trackIndex) {
+ return mFrameList[trackIndex];
+}
+
+void WriterFuzzerBase::BufferSource::getFrameInfo() {
+ size_t readIndexStart = mReadIndex;
+ if (mSize - mReadIndex > kMarkerSize + kMarkerSuffixSize) {
+ bool isFrameAvailable = true;
+ size_t bytesRemaining = mSize;
+ mReadIndex = mSize - kMarkerSize;
+ while (isFrameAvailable) {
+ isFrameAvailable = searchForMarker(readIndexStart);
+ if (isFrameAvailable) {
+ size_t location = mReadIndex + kMarkerSize;
+ if (location + kMarkerSuffixSize >= bytesRemaining) {
+ break;
+ }
+ bool isCSD = isCSDMarker(location);
+ location += kMarkerSuffixSize;
+ uint8_t *framePtr = const_cast<uint8_t *>(&mData[location]);
+ size_t frameSize = bytesRemaining - location, bufferSize = 0;
+ uint8_t trackIndex = framePtr[0] % kMaxTrackCount;
+ ++framePtr;
+ uint8_t flags = 0;
+ int64_t pts = 0;
+ if (isCSD && frameSize > 1) {
+ flags |= kCodecConfigFlag;
+ pts = 0;
+ ++mNumCsds[trackIndex];
+ bufferSize = frameSize - 1;
+ } else if (frameSize > sizeof(uint8_t) + sizeof(int64_t) + 1) {
+ flags = flagTypes[framePtr[0] % size(flagTypes)];
+ ++framePtr;
+ copy(framePtr, framePtr + sizeof(int64_t), reinterpret_cast<uint8_t *>(&pts));
+ framePtr += sizeof(int64_t);
+ bufferSize = frameSize - (sizeof(uint8_t) + sizeof(int64_t)) - 1;
+ } else {
+ break;
+ }
+ mFrameList[trackIndex].insert(
+ mFrameList[trackIndex].begin(),
+ FrameData{static_cast<int32_t>(bufferSize), flags, pts, framePtr});
+ bytesRemaining -= (frameSize + kMarkerSize + kMarkerSuffixSize);
+ --mReadIndex;
+ }
+ }
+ }
+ if (mFrameList[0].empty() && mFrameList[1].empty()) {
+ /**
+ * Scenario where input data does not contain the custom frame markers.
+ * Hence feed the entire data as single frame.
+ */
+ mFrameList[0].emplace_back(
+ FrameData{static_cast<int32_t>(mSize - readIndexStart), 0, 0, mData + readIndexStart});
+ }
+}
+bool WriterFuzzerBase::BufferSource::getTrackInfo(int32_t trackIndex) {
+ if (mSize <= mReadIndex + 2 * sizeof(int) + sizeof(uint8_t)) {
+ return false;
+ }
+ size_t mimeTypeIdx = mData[mReadIndex] % kSupportedMimeTypes;
+ char *mime = (char *)supportedMimeTypes[mimeTypeIdx].c_str();
+ mParams[trackIndex].mime = mime;
+ ++mReadIndex;
+
+ if (!strncmp(mime, "audio/", 6)) {
+ copy(mData + mReadIndex, mData + mReadIndex + sizeof(int),
+ reinterpret_cast<char *>(&mParams[trackIndex].channelCount));
+ copy(mData + mReadIndex + sizeof(int), mData + mReadIndex + 2 * sizeof(int),
+ reinterpret_cast<char *>(&mParams[trackIndex].sampleRate));
+ } else {
+ copy(mData + mReadIndex, mData + mReadIndex + sizeof(int),
+ reinterpret_cast<char *>(&mParams[trackIndex].height));
+ copy(mData + mReadIndex + sizeof(int), mData + mReadIndex + 2 * sizeof(int),
+ reinterpret_cast<char *>(&mParams[trackIndex].width));
+ }
+ mReadIndex += 2 * sizeof(int);
+ return true;
+}
+
+void writeHeaderBuffers(vector<FrameData> &bufferInfo, sp<AMessage> &format, int32_t numCsds) {
+ char csdName[kMaxCSDStrlen];
+ for (int csdId = 0; csdId < numCsds; ++csdId) {
+ int32_t flags = bufferInfo[csdId].flags;
+ if (flags == kCodecConfigFlag) {
+ sp<ABuffer> csdBuffer =
+ ABuffer::CreateAsCopy((void *)bufferInfo[csdId].buf, bufferInfo[csdId].size);
+ if (csdBuffer.get() == nullptr || csdBuffer->base() == nullptr) {
+ return;
+ }
+ snprintf(csdName, sizeof(csdName), "csd-%d", csdId);
+ format->setBuffer(csdName, csdBuffer);
+ }
+ }
+}
+
+bool WriterFuzzerBase::createOutputFile() {
+ mFd = memfd_create(mOutputFileName.c_str(), MFD_ALLOW_SEALING);
+ if (mFd == -1) {
+ return false;
+ }
+ return true;
+}
+
+void WriterFuzzerBase::addWriterSource(int32_t trackIndex) {
+ ConfigFormat params = mBufferSource->getConfigFormat(trackIndex);
+ sp<AMessage> format = new AMessage;
+ format->setString("mime", params.mime);
+ if (!strncmp(params.mime, "audio/", 6)) {
+ if (!strncmp(params.mime, "audio/3gpp", 10)) {
+ params.channelCount = 1;
+ params.sampleRate = 8000;
+ } else if (!strncmp(params.mime, "audio/amr-wb", 12)) {
+ params.channelCount = 1;
+ params.sampleRate = 16000;
+ } else {
+ params.sampleRate = max(1, params.sampleRate);
+ }
+ format->setInt32("channel-count", params.channelCount);
+ format->setInt32("sample-rate", params.sampleRate);
+ } else {
+ format->setInt32("width", params.width);
+ format->setInt32("height", params.height);
+ }
+ int32_t numCsds = mBufferSource->getNumCsds(trackIndex);
+ if (numCsds) {
+ vector<FrameData> mFrames = mBufferSource->getFrameList(trackIndex);
+ writeHeaderBuffers(mFrames, format, numCsds);
+ }
+ sp<MetaData> trackMeta = new MetaData;
+ convertMessageToMetaData(format, trackMeta);
+ mCurrentTrack[trackIndex] = new MediaAdapter(trackMeta);
+ mWriter->addSource(mCurrentTrack[trackIndex]);
+}
+
+void WriterFuzzerBase::start() {
+ mFileMeta->setInt32(kKeyRealTimeRecording, false);
+ mWriter->start(mFileMeta.get());
+}
+
+void WriterFuzzerBase::sendBuffersToWriter(sp<MediaAdapter> ¤tTrack, int32_t trackIndex) {
+ int32_t numCsds = mBufferSource->getNumCsds(trackIndex);
+ vector<FrameData> bufferInfo = mBufferSource->getFrameList(trackIndex);
+ int32_t range = bufferInfo.size();
+ for (int idx = numCsds; idx < range; ++idx) {
+ sp<ABuffer> buffer = new ABuffer((void *)bufferInfo[idx].buf, bufferInfo[idx].size);
+ MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
+
+ // Released in MediaAdapter::signalBufferReturned().
+ mediaBuffer->add_ref();
+ mediaBuffer->set_range(buffer->offset(), buffer->size());
+ MetaDataBase &sampleMetaData = mediaBuffer->meta_data();
+ sampleMetaData.setInt64(kKeyTime, bufferInfo[idx].timeUs);
+
+ // Just set the kKeyDecodingTime as the presentation time for now.
+ sampleMetaData.setInt64(kKeyDecodingTime, bufferInfo[idx].timeUs);
+ if (bufferInfo[idx].flags == 1) {
+ sampleMetaData.setInt32(kKeyIsSyncFrame, true);
+ }
+
+ // This pushBuffer will wait until the mediaBuffer is consumed.
+ currentTrack->pushBuffer(mediaBuffer);
+ }
+}
+
+void WriterFuzzerBase::processData(const uint8_t *data, size_t size) {
+ if (!createOutputFile()) {
+ return;
+ }
+ if (!createWriter()) {
+ return;
+ }
+ mBufferSource = new BufferSource(data, size);
+ if (!mBufferSource) {
+ return;
+ }
+ mNumTracks = mBufferSource->getNumTracks();
+ if (mNumTracks > 0) {
+ for (int32_t idx = 0; idx < mNumTracks; ++idx) {
+ if (!mBufferSource->getTrackInfo(idx)) {
+ if (idx == 0) {
+ delete mBufferSource;
+ return;
+ }
+ mNumTracks = idx;
+ break;
+ }
+ }
+ mBufferSource->getFrameInfo();
+ for (int32_t idx = 0; idx < mNumTracks; ++idx) {
+ addWriterSource(idx);
+ }
+ start();
+ for (int32_t idx = 0; idx < mNumTracks; ++idx) {
+ sendBuffersToWriter(mCurrentTrack[idx], idx);
+ }
+ for (int32_t idx = 0; idx < mNumTracks; ++idx) {
+ if (mCurrentTrack[idx]) {
+ mCurrentTrack[idx]->stop();
+ }
+ }
+ }
+ delete mBufferSource;
+ mWriter->stop();
+}
diff --git a/media/libstagefright/writer_fuzzers/include/WriterFuzzerBase.h b/media/libstagefright/writer_fuzzers/include/WriterFuzzerBase.h
new file mode 100644
index 0000000..d819d43
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/include/WriterFuzzerBase.h
@@ -0,0 +1,168 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#ifndef __WRITER_FUZZER_BASE_H__
+#define __WRITER_FUZZER_BASE_H__
+
+#include <media/stagefright/MediaAdapter.h>
+#include <media/stagefright/MediaWriter.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <algorithm>
+#include <cstring>
+#include <vector>
+
+using namespace std;
+
+constexpr uint32_t kMimeSize = 128;
+constexpr uint8_t kMaxTrackCount = 2;
+constexpr uint32_t kMaxCSDStrlen = 16;
+constexpr uint32_t kCodecConfigFlag = 32;
+
+namespace android {
+
+struct ConfigFormat {
+ char* mime;
+ int32_t width;
+ int32_t height;
+ int32_t sampleRate;
+ int32_t channelCount;
+};
+
+struct FrameData {
+ int32_t size;
+ uint8_t flags;
+ int64_t timeUs;
+ const uint8_t* buf;
+};
+
+static string supportedMimeTypes[] = {
+ "audio/3gpp", "audio/amr-wb", "audio/vorbis", "audio/opus",
+ "audio/mp4a-latm", "video/avc", "video/hevc", "video/mp4v-es",
+ "video/3gpp", "video/x-vnd.on2.vp8", "video/x-vnd.on2.vp9",
+};
+
+enum {
+ DEFAULT_FLAG = 0,
+ SYNC_FLAG = 1,
+ ENCRYPTED_FLAG = 2,
+};
+
+static uint8_t flagTypes[] = {DEFAULT_FLAG, SYNC_FLAG, ENCRYPTED_FLAG};
+
+class WriterFuzzerBase {
+ public:
+ WriterFuzzerBase() = default;
+ virtual ~WriterFuzzerBase() {
+ if (mFileMeta) {
+ mFileMeta.clear();
+ mFileMeta = nullptr;
+ }
+ if (mWriter) {
+ mWriter.clear();
+ mWriter = nullptr;
+ }
+ for (int32_t idx = 0; idx < kMaxTrackCount; ++idx) {
+ if (mCurrentTrack[idx]) {
+ mCurrentTrack[idx]->stop();
+ mCurrentTrack[idx].clear();
+ mCurrentTrack[idx] = nullptr;
+ }
+ }
+ close(mFd);
+ };
+
+ /** Function to create the media writer component.
+ * To be implemented by the derived class.
+ */
+ virtual bool createWriter() = 0;
+
+ /** Parent class functions to be reused by derived class.
+ * These are common for all media writer components.
+ */
+ bool createOutputFile();
+
+ void addWriterSource(int32_t trackIndex);
+
+ void start();
+
+ void sendBuffersToWriter(sp<MediaAdapter>& currentTrack, int32_t trackIndex);
+
+ void processData(const uint8_t* data, size_t size);
+
+ protected:
+ class BufferSource {
+ public:
+ BufferSource(const uint8_t* data, size_t size) : mData(data), mSize(size), mReadIndex(0) {}
+ ~BufferSource() {
+ mData = nullptr;
+ mSize = 0;
+ mReadIndex = 0;
+ for (int32_t idx = 0; idx < kMaxTrackCount; ++idx) {
+ mFrameList[idx].clear();
+ }
+ }
+ uint32_t getNumTracks();
+ bool getTrackInfo(int32_t trackIndex);
+ void getFrameInfo();
+ ConfigFormat getConfigFormat(int32_t trackIndex);
+ int32_t getNumCsds(int32_t trackIndex);
+ vector<FrameData> getFrameList(int32_t trackIndex);
+
+ private:
+ bool isMarker() { return (memcmp(&mData[mReadIndex], kMarker, kMarkerSize) == 0); }
+
+ bool isCSDMarker(size_t position) {
+ return (memcmp(&mData[position], kCsdMarkerSuffix, kMarkerSuffixSize) == 0);
+ }
+
+ bool searchForMarker(size_t startIndex);
+
+ const uint8_t* mData = nullptr;
+ size_t mSize = 0;
+ size_t mReadIndex = 0;
+ ConfigFormat mParams[kMaxTrackCount] = {};
+ int32_t mNumCsds[kMaxTrackCount] = {0};
+ vector<FrameData> mFrameList[kMaxTrackCount];
+
+ static constexpr int kSupportedMimeTypes = size(supportedMimeTypes);
+ static constexpr uint8_t kMarker[] = "_MARK";
+ static constexpr uint8_t kCsdMarkerSuffix[] = "_H_";
+ static constexpr uint8_t kFrameMarkerSuffix[] = "_F_";
+ // All markers should be 5 bytes long ( sizeof '_MARK' which is 5)
+ static constexpr size_t kMarkerSize = (sizeof(kMarker) - 1);
+ // All marker types should be 3 bytes long ('_H_', '_F_')
+ static constexpr size_t kMarkerSuffixSize = 3;
+ };
+
+ BufferSource* mBufferSource = nullptr;
+ int32_t mFd = -1;
+ uint32_t mNumTracks = 0;
+ string mOutputFileName = "writer.out";
+ sp<MediaWriter> mWriter = nullptr;
+ sp<MetaData> mFileMeta = nullptr;
+ sp<MediaAdapter> mCurrentTrack[kMaxTrackCount] = {};
+};
+
+} // namespace android
+
+#endif // __WRITER_FUZZER_BASE_H__
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index 8d5c77f..ee7285d 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -17,6 +17,7 @@
shared_libs: [
"android.hardware.media.omx@1.0",
"libandroidicu",
+ "libfmq",
"libbinder",
"libhidlbase",
"liblog",
diff --git a/media/mediaserver/mediaserver.rc b/media/mediaserver/mediaserver.rc
index 05373c9..c82e532 100644
--- a/media/mediaserver/mediaserver.rc
+++ b/media/mediaserver/mediaserver.rc
@@ -7,3 +7,9 @@
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
ioprio rt 4
task_profiles ProcessCapacityHigh HighPerformance
+
+# media.transcoding service is defined on com.android.media apex which goes back
+# to API29, but we only want it started on API31+ devices. So we declare it as
+# "disabled" and start it explicitly on boot.
+on boot
+ start media.transcoding
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index 1145b7b..5fdd45a 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -58,7 +58,7 @@
if (mIsClosed) {
return;
}
- if (!mReader->mIsClosed) {
+ if (mReader->mIsOpen) {
mReader->releaseImageLocked(this, releaseFenceFd);
}
// Should have been set to nullptr in releaseImageLocked
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index 5d8f0b8..b75901a 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -273,7 +273,7 @@
AImageReader::~AImageReader() {
Mutex::Autolock _l(mLock);
- LOG_FATAL_IF("AImageReader not closed before destruction", mIsClosed != true);
+ LOG_FATAL_IF(mIsOpen, "AImageReader not closed before destruction");
}
media_status_t
@@ -347,16 +347,16 @@
}
mHandler = new CallbackHandler(this);
mCbLooper->registerHandler(mHandler);
-
+ mIsOpen = true;
return AMEDIA_OK;
}
void AImageReader::close() {
Mutex::Autolock _l(mLock);
- if (mIsClosed) {
+ if (!mIsOpen) {
return;
}
- mIsClosed = true;
+ mIsOpen = false;
AImageReader_ImageListener nullListener = {nullptr, nullptr};
setImageListenerLocked(&nullListener);
diff --git a/media/ndk/NdkImageReaderPriv.h b/media/ndk/NdkImageReaderPriv.h
index 0779a71..37c606e 100644
--- a/media/ndk/NdkImageReaderPriv.h
+++ b/media/ndk/NdkImageReaderPriv.h
@@ -166,7 +166,7 @@
native_handle_t* mWindowHandle = nullptr;
List<AImage*> mAcquiredImages;
- bool mIsClosed = false;
+ bool mIsOpen = false;
Mutex mLock;
};
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index 0da0740..0c65e9e 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -22,6 +22,7 @@
#include <media/NdkMediaExtractor.h>
#include <media/NdkMediaErrorPriv.h>
#include <media/NdkMediaFormatPriv.h>
+#include "NdkJavaVMHelperPriv.h"
#include "NdkMediaDataSourcePriv.h"
@@ -63,7 +64,10 @@
AMediaExtractor* AMediaExtractor_new() {
ALOGV("ctor");
AMediaExtractor *mData = new AMediaExtractor();
- mData->mImpl = new NuMediaExtractor();
+ mData->mImpl = new NuMediaExtractor(
+ NdkJavaVMHelper::getJNIEnv() != nullptr
+ ? NuMediaExtractor::EntryPoint::NDK_WITH_JVM
+ : NuMediaExtractor::EntryPoint::NDK_NO_JVM );
return mData;
}
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 47214c5..8e673ca 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -384,6 +384,8 @@
EXPORT const char* AMEDIAFORMAT_KEY_TRACK_INDEX = "track-index";
EXPORT const char* AMEDIAFORMAT_KEY_VALID_SAMPLES = "valid-samples";
EXPORT const char* AMEDIAFORMAT_KEY_WIDTH = "width";
+EXPORT const char* AMEDIAFORMAT_KEY_XMP_OFFSET = "xmp-offset";
+EXPORT const char* AMEDIAFORMAT_KEY_XMP_SIZE = "xmp-size";
EXPORT const char* AMEDIAFORMAT_KEY_YEAR = "year";
} // extern "C"
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 8f39929..0b9024f 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -325,6 +325,8 @@
#if __ANDROID_API__ >= 31
extern const char* AMEDIAFORMAT_KEY_SLOW_MOTION_MARKERS __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_CSD_AV1C __INTRODUCED_IN(31);
+extern const char* AMEDIAFORMAT_KEY_XMP_OFFSET __INTRODUCED_IN(31);
+extern const char* AMEDIAFORMAT_KEY_XMP_SIZE __INTRODUCED_IN(31);
#endif /* __ANDROID_API__ >= 31 */
__END_DECLS
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 96f1710..2b389fe 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -151,6 +151,8 @@
AMEDIAFORMAT_KEY_TRACK_ID; # var introduced=28
AMEDIAFORMAT_KEY_VALID_SAMPLES; # var introduced=29
AMEDIAFORMAT_KEY_WIDTH; # var introduced=21
+ AMEDIAFORMAT_KEY_XMP_OFFSET; # var introduced=31
+ AMEDIAFORMAT_KEY_XMP_SIZE; # var introduced=31
AMEDIAFORMAT_KEY_YEAR; # var introduced=29
AMediaCodecActionCode_isRecoverable; # introduced=28
AMediaCodecActionCode_isTransient; # introduced=28
@@ -165,11 +167,11 @@
AMediaCodecCryptoInfo_setPattern; # introduced=24
AMediaCodec_configure;
AMediaCodec_createCodecByName;
- AMediaCodec_createCodecByNameForClient; # apex #introduced = 31
+ AMediaCodec_createCodecByNameForClient; # apex # introduced=31
AMediaCodec_createDecoderByType;
- AMediaCodec_createDecoderByTypeForClient; # apex #introduced = 31
+ AMediaCodec_createDecoderByTypeForClient; # apex # introduced=31
AMediaCodec_createEncoderByType;
- AMediaCodec_createEncoderByTypeForClient; # apex #introduced = 31
+ AMediaCodec_createEncoderByTypeForClient; # apex # introduced=31
AMediaCodec_delete;
AMediaCodec_dequeueInputBuffer;
AMediaCodec_dequeueOutputBuffer;
diff --git a/media/tests/benchmark/src/native/decoder/C2Decoder.cpp b/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
index 46c4a7c..6539f24 100644
--- a/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
+++ b/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
@@ -53,8 +53,8 @@
}
int64_t sTime = mStats->getCurTime();
- mComponent = mClient->CreateComponentByName(compName.c_str(), mListener, &mClient);
- if (mComponent == nullptr) {
+ if (mClient->CreateComponentByName(compName.c_str(), mListener, &mComponent, &mClient) !=
+ C2_OK) {
ALOGE("Create component failed for %s", compName.c_str());
return -1;
}
diff --git a/media/tests/benchmark/src/native/encoder/C2Encoder.cpp b/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
index 6a50d40..ca79881 100644
--- a/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
+++ b/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
@@ -68,8 +68,8 @@
}
int64_t sTime = mStats->getCurTime();
- mComponent = mClient->CreateComponentByName(compName.c_str(), mListener, &mClient);
- if (mComponent == nullptr) {
+ if (mClient->CreateComponentByName(compName.c_str(), mListener, &mComponent, &mClient) !=
+ C2_OK) {
ALOGE("Create component failed for %s", compName.c_str());
return -1;
}
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 87ea084..2c8a452 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -22,6 +22,7 @@
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
#include "mediautils/ServiceUtilities.h"
+#include <system/audio-hal-enums.h>
#include <iterator>
#include <algorithm>
@@ -61,8 +62,20 @@
return packages[0];
}
+static int32_t getOpForSource(audio_source_t source) {
+ switch (source) {
+ case AUDIO_SOURCE_HOTWORD:
+ return AppOpsManager::OP_RECORD_AUDIO_HOTWORD;
+ case AUDIO_SOURCE_REMOTE_SUBMIX:
+ return AppOpsManager::OP_RECORD_AUDIO_OUTPUT;
+ case AUDIO_SOURCE_DEFAULT:
+ default:
+ return AppOpsManager::OP_RECORD_AUDIO;
+ }
+}
+
static bool checkRecordingInternal(const String16& opPackageName, pid_t pid,
- uid_t uid, bool start) {
+ uid_t uid, bool start, audio_source_t source) {
// Okay to not track in app ops as audio server or media server is us and if
// device is rooted security model is considered compromised.
// system_server loses its RECORD_AUDIO permission when a secondary
@@ -87,16 +100,21 @@
}
AppOpsManager appOps;
- const int32_t op = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+ const int32_t op = getOpForSource(source);
if (start) {
- if (appOps.startOpNoThrow(op, uid, resolvedOpPackageName, /*startIfModeDefault*/ false)
- != AppOpsManager::MODE_ALLOWED) {
- ALOGE("Request denied by app op: %d", op);
+ if (int32_t mode = appOps.startOpNoThrow(
+ op, uid, resolvedOpPackageName, /*startIfModeDefault*/ false);
+ mode != AppOpsManager::MODE_ALLOWED) {
+ ALOGE("Request start for \"%s\" (uid %d) denied by app op: %d, mode: %d",
+ String8(resolvedOpPackageName).c_str(), uid, op, mode);
return false;
}
} else {
- if (appOps.checkOp(op, uid, resolvedOpPackageName) != AppOpsManager::MODE_ALLOWED) {
- ALOGE("Request denied by app op: %d", op);
+ // Always use OP_RECORD_AUDIO for checks at creation time.
+ if (int32_t mode = appOps.checkOp(op, uid, resolvedOpPackageName);
+ mode != AppOpsManager::MODE_ALLOWED) {
+ ALOGE("Request check for \"%s\" (uid %d) denied by app op: %d, mode: %d",
+ String8(resolvedOpPackageName).c_str(), uid, op, mode);
return false;
}
}
@@ -105,14 +123,14 @@
}
bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid) {
- return checkRecordingInternal(opPackageName, pid, uid, /*start*/ false);
+ return checkRecordingInternal(opPackageName, pid, uid, /*start*/ false, AUDIO_SOURCE_DEFAULT);
}
-bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid) {
- return checkRecordingInternal(opPackageName, pid, uid, /*start*/ true);
+bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, audio_source_t source) {
+ return checkRecordingInternal(opPackageName, pid, uid, /*start*/ true, source);
}
-void finishRecording(const String16& opPackageName, uid_t uid) {
+void finishRecording(const String16& opPackageName, uid_t uid, audio_source_t source) {
// Okay to not track in app ops as audio server is us and if
// device is rooted security model is considered compromised.
if (isAudioServerOrRootUid(uid)) return;
@@ -125,7 +143,8 @@
}
AppOpsManager appOps;
- const int32_t op = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+
+ const int32_t op = getOpForSource(source);
appOps.finishOp(op, uid, resolvedOpPackageName);
}
@@ -145,6 +164,14 @@
return ok;
}
+bool captureTunerAudioInputAllowed(pid_t pid, uid_t uid) {
+ if (isAudioServerOrRootUid(uid)) return true;
+ static const String16 sCaptureTunerAudioInput("android.permission.CAPTURE_TUNER_AUDIO_INPUT");
+ bool ok = PermissionCache::checkPermission(sCaptureTunerAudioInput, pid, uid);
+ if (!ok) ALOGV("Request requires android.permission.CAPTURE_TUNER_AUDIO_INPUT");
+ return ok;
+}
+
bool captureVoiceCommunicationOutputAllowed(pid_t pid, uid_t uid) {
if (isAudioServerOrRootUid(uid)) return true;
static const String16 sCaptureVoiceCommOutput(
@@ -259,7 +286,7 @@
return NO_ERROR;
}
-sp<content::pm::IPackageManagerNative> MediaPackageManager::retreivePackageManager() {
+sp<content::pm::IPackageManagerNative> MediaPackageManager::retrievePackageManager() {
const sp<IServiceManager> sm = defaultServiceManager();
if (sm == nullptr) {
ALOGW("%s: failed to retrieve defaultServiceManager", __func__);
@@ -276,27 +303,27 @@
std::optional<bool> MediaPackageManager::doIsAllowed(uid_t uid) {
if (mPackageManager == nullptr) {
/** Can not fetch package manager at construction it may not yet be registered. */
- mPackageManager = retreivePackageManager();
+ mPackageManager = retrievePackageManager();
if (mPackageManager == nullptr) {
ALOGW("%s: Playback capture is denied as package manager is not reachable", __func__);
return std::nullopt;
}
}
+ // Retrieve package names for the UID and transform to a std::vector<std::string>.
+ Vector<String16> str16PackageNames;
+ PermissionController{}.getPackagesForUid(uid, str16PackageNames);
std::vector<std::string> packageNames;
- auto status = mPackageManager->getNamesForUids({(int32_t)uid}, &packageNames);
- if (!status.isOk()) {
- ALOGW("%s: Playback capture is denied for uid %u as the package names could not be "
- "retrieved from the package manager: %s", __func__, uid, status.toString8().c_str());
- return std::nullopt;
+ for (const auto& str16PackageName : str16PackageNames) {
+ packageNames.emplace_back(String8(str16PackageName).string());
}
if (packageNames.empty()) {
ALOGW("%s: Playback capture for uid %u is denied as no package name could be retrieved "
- "from the package manager: %s", __func__, uid, status.toString8().c_str());
+ "from the package manager.", __func__, uid);
return std::nullopt;
}
std::vector<bool> isAllowed;
- status = mPackageManager->isAudioPlaybackCaptureAllowed(packageNames, &isAllowed);
+ auto status = mPackageManager->isAudioPlaybackCaptureAllowed(packageNames, &isAllowed);
if (!status.isOk()) {
ALOGW("%s: Playback capture is denied for uid %u as the manifest property could not be "
"retrieved from the package manager: %s", __func__, uid, status.toString8().c_str());
diff --git a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
index 3d141b5..f4c815c 100644
--- a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
+++ b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
@@ -17,6 +17,7 @@
#include <fcntl.h>
#include <functional>
+#include <type_traits>
#include "fuzzer/FuzzedDataProvider.h"
#include "mediautils/ServiceUtilities.h"
@@ -44,6 +45,8 @@
FuzzedDataProvider data_provider(data, size);
uid_t uid = data_provider.ConsumeIntegral<uid_t>();
pid_t pid = data_provider.ConsumeIntegral<pid_t>();
+ audio_source_t source = static_cast<audio_source_t>(data_provider
+ .ConsumeIntegral<std::underlying_type_t<audio_source_t>>());
// There is not state here, and order is not significant,
// so we can simply call all of the target functions
@@ -54,8 +57,8 @@
std::string packageNameStr = data_provider.ConsumeRandomLengthString(kMaxStringLen);
android::String16 opPackageName(packageNameStr.c_str());
android::recordingAllowed(opPackageName, pid, uid);
- android::startRecording(opPackageName, pid, uid);
- android::finishRecording(opPackageName, uid);
+ android::startRecording(opPackageName, pid, uid, source);
+ android::finishRecording(opPackageName, uid, source);
android::captureAudioOutputAllowed(pid, uid);
android::captureMediaOutputAllowed(pid, uid);
android::captureHotwordAllowed(opPackageName, pid, uid);
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 212599a..03965db 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -24,6 +24,7 @@
#include <binder/PermissionController.h>
#include <cutils/multiuser.h>
#include <private/android_filesystem_config.h>
+#include <system/audio-hal-enums.h>
#include <map>
#include <optional>
@@ -79,10 +80,11 @@
}
bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
-bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid);
-void finishRecording(const String16& opPackageName, uid_t uid);
+bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, audio_source_t source);
+void finishRecording(const String16& opPackageName, uid_t uid, audio_source_t source);
bool captureAudioOutputAllowed(pid_t pid, uid_t uid);
bool captureMediaOutputAllowed(pid_t pid, uid_t uid);
+bool captureTunerAudioInputAllowed(pid_t pid, uid_t uid);
bool captureVoiceCommunicationOutputAllowed(pid_t pid, uid_t uid);
bool captureHotwordAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
bool settingsAllowed();
@@ -110,7 +112,7 @@
private:
static constexpr const char* nativePackageManagerName = "package_native";
std::optional<bool> doIsAllowed(uid_t uid);
- sp<content::pm::IPackageManagerNative> retreivePackageManager();
+ sp<content::pm::IPackageManagerNative> retrievePackageManager();
sp<content::pm::IPackageManagerNative> mPackageManager; // To check apps manifest
uint_t mPackageManagerErrors = 0;
struct Package {
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 87b5ff4..a005250 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -69,6 +69,7 @@
],
header_libs: [
+ "libaudioclient_headers",
"libaudiohal_headers",
"libmedia_headers",
],
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e7a12df..a6f0953 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -185,9 +185,15 @@
// ----------------------------------------------------------------------------
+void AudioFlinger::instantiate() {
+ sp<IServiceManager> sm(defaultServiceManager());
+ sm->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME),
+ new AudioFlingerServerAdapter(new AudioFlinger()), false,
+ IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
+}
+
AudioFlinger::AudioFlinger()
- : BnAudioFlinger(),
- mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
+ : mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
mPrimaryHardwareDev(NULL),
mAudioHwDevs(NULL),
mHardwareStatus(AUDIO_HW_IDLE),
@@ -1486,6 +1492,20 @@
}
}
+// Update downstream patches for all playback threads attached to an MSD module
+void AudioFlinger::updateDownStreamPatches_l(const struct audio_patch *patch,
+ const std::set<audio_io_handle_t> streams)
+{
+ for (const audio_io_handle_t stream : streams) {
+ PlaybackThread *playbackThread = checkPlaybackThread_l(stream);
+ if (playbackThread == nullptr || !playbackThread->isMsdDevice()) {
+ continue;
+ }
+ playbackThread->setDownStreamPatch(patch);
+ playbackThread->sendIoConfigEvent(AUDIO_OUTPUT_CONFIG_CHANGED);
+ }
+}
+
// Filter reserved keys from setParameters() before forwarding to audio HAL or acting upon.
// Some keys are used for audio routing and audio path configuration and should be reserved for use
// by audio policy and audio flinger for functional, privacy and security reasons.
@@ -2569,7 +2589,11 @@
*output, thread.get());
}
mPlaybackThreads.add(*output, thread);
- mPatchPanel.notifyStreamOpened(outHwDev, *output);
+ struct audio_patch patch;
+ mPatchPanel.notifyStreamOpened(outHwDev, *output, &patch);
+ if (thread->isMsdDevice()) {
+ thread->setDownStreamPatch(&patch);
+ }
return thread;
}
}
@@ -2587,7 +2611,7 @@
sp<DeviceDescriptorBase> device = VALUE_OR_RETURN_STATUS(
aidl2legacy_DeviceDescriptorBase(request.device));
audio_output_flags_t flags = VALUE_OR_RETURN_STATUS(
- aidl2legacy_audio_output_flags_mask(request.flags));
+ aidl2legacy_int32_t_audio_output_flags_t_mask(request.flags));
audio_io_handle_t output;
uint32_t latencyMs;
@@ -2637,7 +2661,8 @@
response->output = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
response->config = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_config_t_AudioConfig(config));
response->latencyMs = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(latencyMs));
- response->flags = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_output_flags_mask(flags));
+ response->flags = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
return NO_ERROR;
}
@@ -2813,7 +2838,7 @@
device.mType,
device.address().c_str(),
VALUE_OR_RETURN_STATUS(aidl2legacy_AudioSourceType_audio_source_t(request.source)),
- VALUE_OR_RETURN_STATUS(aidl2legacy_audio_input_flags_mask(request.flags)),
+ VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_input_flags_t_mask(request.flags)),
AUDIO_DEVICE_NONE,
String8{});
@@ -4042,42 +4067,40 @@
// ----------------------------------------------------------------------------
-status_t AudioFlinger::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+status_t AudioFlinger::onPreTransact(
+ TransactionCode code, const Parcel& /* data */, uint32_t /* flags */)
{
// make sure transactions reserved to AudioPolicyManager do not come from other processes
switch (code) {
- case SET_STREAM_VOLUME:
- case SET_STREAM_MUTE:
- case OPEN_OUTPUT:
- case OPEN_DUPLICATE_OUTPUT:
- case CLOSE_OUTPUT:
- case SUSPEND_OUTPUT:
- case RESTORE_OUTPUT:
- case OPEN_INPUT:
- case CLOSE_INPUT:
- case INVALIDATE_STREAM:
- case SET_VOICE_VOLUME:
- case MOVE_EFFECTS:
- case SET_EFFECT_SUSPENDED:
- case LOAD_HW_MODULE:
- case LIST_AUDIO_PORTS:
- case GET_AUDIO_PORT:
- case CREATE_AUDIO_PATCH:
- case RELEASE_AUDIO_PATCH:
- case LIST_AUDIO_PATCHES:
- case SET_AUDIO_PORT_CONFIG:
- case SET_RECORD_SILENCED:
+ case TransactionCode::SET_STREAM_VOLUME:
+ case TransactionCode::SET_STREAM_MUTE:
+ case TransactionCode::OPEN_OUTPUT:
+ case TransactionCode::OPEN_DUPLICATE_OUTPUT:
+ case TransactionCode::CLOSE_OUTPUT:
+ case TransactionCode::SUSPEND_OUTPUT:
+ case TransactionCode::RESTORE_OUTPUT:
+ case TransactionCode::OPEN_INPUT:
+ case TransactionCode::CLOSE_INPUT:
+ case TransactionCode::INVALIDATE_STREAM:
+ case TransactionCode::SET_VOICE_VOLUME:
+ case TransactionCode::MOVE_EFFECTS:
+ case TransactionCode::SET_EFFECT_SUSPENDED:
+ case TransactionCode::LOAD_HW_MODULE:
+ case TransactionCode::GET_AUDIO_PORT:
+ case TransactionCode::CREATE_AUDIO_PATCH:
+ case TransactionCode::RELEASE_AUDIO_PATCH:
+ case TransactionCode::LIST_AUDIO_PATCHES:
+ case TransactionCode::SET_AUDIO_PORT_CONFIG:
+ case TransactionCode::SET_RECORD_SILENCED:
ALOGW("%s: transaction %d received from PID %d",
__func__, code, IPCThreadState::self()->getCallingPid());
// return status only for non void methods
switch (code) {
- case SET_RECORD_SILENCED:
- case SET_EFFECT_SUSPENDED:
+ case TransactionCode::SET_RECORD_SILENCED:
+ case TransactionCode::SET_EFFECT_SUSPENDED:
break;
default:
- reply->writeInt32(static_cast<int32_t> (INVALID_OPERATION));
- break;
+ return INVALID_OPERATION;
}
return OK;
default:
@@ -4086,24 +4109,24 @@
// make sure the following transactions come from system components
switch (code) {
- case SET_MASTER_VOLUME:
- case SET_MASTER_MUTE:
- case SET_MODE:
- case SET_MIC_MUTE:
- case SET_LOW_RAM_DEVICE:
- case SYSTEM_READY:
- case SET_AUDIO_HAL_PIDS: {
+ case TransactionCode::SET_MASTER_VOLUME:
+ case TransactionCode::SET_MASTER_MUTE:
+ case TransactionCode::MASTER_MUTE:
+ case TransactionCode::SET_MODE:
+ case TransactionCode::SET_MIC_MUTE:
+ case TransactionCode::SET_LOW_RAM_DEVICE:
+ case TransactionCode::SYSTEM_READY:
+ case TransactionCode::SET_AUDIO_HAL_PIDS: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
// return status only for non void methods
switch (code) {
- case SYSTEM_READY:
+ case TransactionCode::SYSTEM_READY:
break;
default:
- reply->writeInt32(static_cast<int32_t> (INVALID_OPERATION));
- break;
+ return INVALID_OPERATION;
}
return OK;
}
@@ -4117,14 +4140,14 @@
// most relevant events.
// TODO should select more wisely the items from the list
switch (code) {
- case CREATE_TRACK:
- case CREATE_RECORD:
- case SET_MASTER_VOLUME:
- case SET_MASTER_MUTE:
- case SET_MIC_MUTE:
- case SET_PARAMETERS:
- case CREATE_EFFECT:
- case SYSTEM_READY: {
+ case TransactionCode::CREATE_TRACK:
+ case TransactionCode::CREATE_RECORD:
+ case TransactionCode::SET_MASTER_VOLUME:
+ case TransactionCode::SET_MASTER_MUTE:
+ case TransactionCode::SET_MIC_MUTE:
+ case TransactionCode::SET_PARAMETERS:
+ case TransactionCode::CREATE_EFFECT:
+ case TransactionCode::SYSTEM_READY: {
requestLogMerge();
break;
}
@@ -4132,7 +4155,8 @@
break;
}
- std::string tag("IAudioFlinger command " + std::to_string(code));
+ std::string tag("IAudioFlinger command " +
+ std::to_string(static_cast<std::underlying_type_t<TransactionCode>>(code)));
TimeCheck check(tag.c_str());
// Make sure we connect to Audio Policy Service before calling into AudioFlinger:
@@ -4145,7 +4169,7 @@
AudioSystem::get_audio_policy_service();
}
- return BnAudioFlinger::onTransact(code, data, reply, flags);
+ return OK;
}
} // namespace android
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index a2e50f8..1c6f57c 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -123,16 +123,12 @@
#define INCLUDING_FROM_AUDIOFLINGER_H
-class AudioFlinger :
- public BinderService<AudioFlinger>,
- public BnAudioFlinger
+class AudioFlinger : public AudioFlingerServerAdapter::Delegate
{
- friend class BinderService<AudioFlinger>; // for AudioFlinger()
-
public:
- static const char* getServiceName() ANDROID_API { return "media.audio_flinger"; }
+ static void instantiate() ANDROID_API;
- virtual status_t dump(int fd, const Vector<String16>& args);
+ status_t dump(int fd, const Vector<String16>& args) override;
// IAudioFlinger interface, in binder opcode order
status_t createTrack(const media::CreateTrackRequest& input,
@@ -270,11 +266,7 @@
virtual status_t setAudioHalPids(const std::vector<pid_t>& pids);
- virtual status_t onTransact(
- uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags);
+ status_t onPreTransact(TransactionCode code, const Parcel& data, uint32_t flags) override;
// end of IAudioFlinger interface
@@ -300,6 +292,9 @@
status_t removeEffectFromHal(audio_port_handle_t deviceId,
audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect);
+ void updateDownStreamPatches_l(const struct audio_patch *patch,
+ const std::set<audio_io_handle_t> streams);
+
private:
// FIXME The 400 is temporarily too high until a leak of writers in media.log is fixed.
static const size_t kLogMemorySize = 400 * 1024;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index eaad6ef..3ab7737 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -60,6 +60,7 @@
namespace android {
+using aidl_utils::statusTFromBinderStatus;
using binder::Status;
namespace {
@@ -3027,7 +3028,7 @@
bs = handle.second->disable(&status);
}
if (!bs.isOk()) {
- status = bs.transactionError();
+ status = statusTFromBinderStatus(bs);
}
}
}
@@ -3142,7 +3143,7 @@
bs = (*handle)->disable(&status);
}
if (!bs.isOk()) {
- status = bs.transactionError();
+ status = statusTFromBinderStatus(bs);
}
}
return status;
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 03bdc60..89321f9 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -373,8 +373,8 @@
DISALLOW_COPY_AND_ASSIGN(EffectHandle);
Mutex mLock; // protects IEffect method calls
- wp<EffectBase> mEffect; // pointer to controlled EffectModule
- sp<media::IEffectClient> mEffectClient; // callback interface for client notifications
+ const wp<EffectBase> mEffect; // pointer to controlled EffectModule
+ const sp<media::IEffectClient> mEffectClient; // callback interface for client notifications
/*const*/ sp<Client> mClient; // client for shared memory allocation, see
// disconnect()
sp<IMemory> mCblkMemory; // shared memory for control block
@@ -558,6 +558,8 @@
wp<ThreadBase> thread() { return mThread; }
+ // TODO(b/161341295) secure this against concurrent access to mThread
+ // by other callers.
void setThread(const wp<ThreadBase>& thread) {
mThread = thread;
sp<ThreadBase> p = thread.promote();
@@ -565,9 +567,9 @@
}
private:
- wp<EffectChain> mChain;
- wp<ThreadBase> mThread;
- wp<AudioFlinger> mAudioFlinger;
+ const wp<EffectChain> mChain;
+ wp<ThreadBase> mThread; // TODO(b/161341295) protect against concurrent access
+ wp<AudioFlinger> mAudioFlinger; // this could be const with some rearrangement.
};
friend class AudioFlinger; // for mThread, mEffects
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 1e11660..806cd86 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -435,10 +435,10 @@
*handle = (audio_patch_handle_t) mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH);
newPatch.mHalHandle = halHandle;
mAudioFlinger.mDeviceEffectManager.createAudioPatch(*handle, newPatch);
- mPatches.insert(std::make_pair(*handle, std::move(newPatch)));
if (insertedModule != AUDIO_MODULE_HANDLE_NONE) {
- addSoftwarePatchToInsertedModules(insertedModule, *handle);
+ addSoftwarePatchToInsertedModules(insertedModule, *handle, &newPatch.mAudioPatch);
}
+ mPatches.insert(std::make_pair(*handle, std::move(newPatch)));
} else {
newPatch.clearConnections(this);
}
@@ -803,10 +803,20 @@
}
void AudioFlinger::PatchPanel::notifyStreamOpened(
- AudioHwDevice *audioHwDevice, audio_io_handle_t stream)
+ AudioHwDevice *audioHwDevice, audio_io_handle_t stream, struct audio_patch *patch)
{
if (audioHwDevice->isInsert()) {
mInsertedModules[audioHwDevice->handle()].streams.insert(stream);
+ if (patch != nullptr) {
+ std::vector <SoftwarePatch> swPatches;
+ getDownstreamSoftwarePatches(stream, &swPatches);
+ if (swPatches.size() > 0) {
+ auto iter = mPatches.find(swPatches[0].getPatchHandle());
+ if (iter != mPatches.end()) {
+ *patch = iter->second.mAudioPatch;
+ }
+ }
+ }
}
}
@@ -835,9 +845,13 @@
}
void AudioFlinger::PatchPanel::addSoftwarePatchToInsertedModules(
- audio_module_handle_t module, audio_patch_handle_t handle)
+ audio_module_handle_t module, audio_patch_handle_t handle,
+ const struct audio_patch *patch)
{
mInsertedModules[module].sw_patches.insert(handle);
+ if (!mInsertedModules[module].streams.empty()) {
+ mAudioFlinger.updateDownStreamPatches_l(patch, mInsertedModules[module].streams);
+ }
}
void AudioFlinger::PatchPanel::removeSoftwarePatchFromInsertedModules(
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 2568dd3..c4c28fa 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -71,7 +71,8 @@
std::vector<SoftwarePatch> *patches) const;
// Notifies patch panel about all opened and closed streams.
- void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream);
+ void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream,
+ struct audio_patch *patch);
void notifyStreamClosed(audio_io_handle_t stream);
void dump(int fd) const;
@@ -226,7 +227,8 @@
AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module);
sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module);
void addSoftwarePatchToInsertedModules(
- audio_module_handle_t module, audio_patch_handle_t handle);
+ audio_module_handle_t module, audio_patch_handle_t handle,
+ const struct audio_patch *patch);
void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
void erasePatch(audio_patch_handle_t handle);
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index a4b8650..dbc190c 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -148,7 +148,7 @@
*/
bool readAndClearHasChanged() { return !mChangeNotified.test_and_set(); }
- using SourceMetadatas = std::vector<playback_track_metadata_t>;
+ using SourceMetadatas = std::vector<playback_track_metadata_v7_t>;
using MetadataInserter = std::back_insert_iterator<SourceMetadatas>;
/** Copy the track metadata in the provided iterator. Thread safe. */
virtual void copyMetadataTo(MetadataInserter& backInserter) const;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index b13b7be..7e1c67e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1876,7 +1876,8 @@
// index 0 is reserved for normal mixer's submix
mFastTrackAvailMask(((1 << FastMixerState::sMaxFastTracks) - 1) & ~1),
mHwSupportsPause(false), mHwPaused(false), mFlushPending(false),
- mLeftVolFloat(-1.0), mRightVolFloat(-1.0)
+ mLeftVolFloat(-1.0), mRightVolFloat(-1.0),
+ mDownStreamPatch{}
{
snprintf(mThreadName, kThreadNameLength, "AudioOut_%X", id);
mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
@@ -2660,12 +2661,16 @@
ALOGV("PlaybackThread::ioConfigChanged, thread %p, event %d", this, event);
desc->mIoHandle = mId;
+ struct audio_patch patch = mPatch;
+ if (isMsdDevice()) {
+ patch = mDownStreamPatch;
+ }
switch (event) {
case AUDIO_OUTPUT_OPENED:
case AUDIO_OUTPUT_REGISTERED:
case AUDIO_OUTPUT_CONFIG_CHANGED:
- desc->mPatch = mPatch;
+ desc->mPatch = patch;
desc->mChannelMask = mChannelMask;
desc->mSamplingRate = mSampleRate;
desc->mFormat = mFormat;
@@ -2675,7 +2680,7 @@
desc->mLatency = latency_l();
break;
case AUDIO_CLIENT_STARTED:
- desc->mPatch = mPatch;
+ desc->mPatch = patch;
desc->mPortId = portId;
break;
case AUDIO_OUTPUT_CLOSED:
@@ -8097,10 +8102,15 @@
StreamInHalInterface::SinkMetadata metadata;
for (const sp<RecordTrack> &track : mActiveTracks) {
// No track is invalid as this is called after prepareTrack_l in the same critical section
- metadata.tracks.push_back({
+ record_track_metadata_v7_t trackMetadata;
+ trackMetadata.base = {
.source = track->attributes().source,
.gain = 1, // capture tracks do not have volumes
- });
+ };
+ trackMetadata.channel_mask = track->channelMask(),
+ strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+
+ metadata.tracks.push_back(trackMetadata);
}
mInput->stream->updateSinkMetadata(metadata);
}
@@ -8684,6 +8694,7 @@
void AudioFlinger::RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
{
+ Mutex::Autolock _l(mLock);
mOutDevices = outDevices;
mOutDeviceTypeAddrs = deviceTypeAddrsFromDescriptors(mOutDevices);
for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -9674,11 +9685,15 @@
StreamOutHalInterface::SourceMetadata metadata;
for (const sp<MmapTrack> &track : mActiveTracks) {
// No track is invalid as this is called after prepareTrack_l in the same critical section
- metadata.tracks.push_back({
+ playback_track_metadata_v7_t trackMetadata;
+ trackMetadata.base = {
.usage = track->attributes().usage,
.content_type = track->attributes().content_type,
.gain = mHalVolFloat, // TODO: propagate from aaudio pre-mix volume
- });
+ };
+ trackMetadata.channel_mask = track->channelMask(),
+ strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ metadata.tracks.push_back(trackMetadata);
}
mOutput->stream->updateSourceMetadata(metadata);
}
@@ -9799,10 +9814,14 @@
StreamInHalInterface::SinkMetadata metadata;
for (const sp<MmapTrack> &track : mActiveTracks) {
// No track is invalid as this is called after prepareTrack_l in the same critical section
- metadata.tracks.push_back({
+ record_track_metadata_v7_t trackMetadata;
+ trackMetadata.base = {
.source = track->attributes().source,
.gain = 1, // capture tracks do not have volumes
- });
+ };
+ trackMetadata.channel_mask = track->channelMask(),
+ strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ metadata.tracks.push_back(trackMetadata);
}
mInput->stream->updateSinkMetadata(metadata);
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 014f2d7..cf4bb8a 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -967,6 +967,11 @@
return (mHapticChannelMask & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE;
}
+ void setDownStreamPatch(const struct audio_patch *patch) {
+ Mutex::Autolock _l(mLock);
+ mDownStreamPatch = *patch;
+ }
+
protected:
// updated by readOutputParameters_l()
size_t mNormalFrameCount; // normal mixer and effects
@@ -1250,6 +1255,10 @@
// volumes last sent to audio HAL with stream->setVolume()
float mLeftVolFloat;
float mRightVolFloat;
+
+ // audio patch used by the downstream software patch.
+ // Only used if ThreadBase::mIsMsdDevice is true.
+ struct audio_patch mDownStreamPatch;
};
class MixerThread : public PlaybackThread {
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 01d5345..38dab5b 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -253,6 +253,8 @@
// Called to tally underrun frames in playback.
virtual void tallyUnderrunFrames(size_t /* frames */) {}
+ audio_channel_mask_t channelMask() const { return mChannelMask; }
+
protected:
DISALLOW_COPY_AND_ASSIGN(TrackBase);
@@ -278,8 +280,6 @@
size_t frameSize() const { return mFrameSize; }
- audio_channel_mask_t channelMask() const { return mChannelMask; }
-
virtual uint32_t sampleRate() const { return mSampleRate; }
bool isStopped() const {
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 68b709f..06cbe87 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -54,6 +54,7 @@
namespace android {
+using aidl_utils::binderStatusFromStatusT;
using binder::Status;
using media::VolumeShaper;
// ----------------------------------------------------------------------------
@@ -371,7 +372,7 @@
if (*_aidl_return != OK) {
return Status::ok();
}
- *timestamp = legacy2aidl_AudioTimestamp(legacy).value();
+ *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
return Status::ok();
}
@@ -1309,11 +1310,15 @@
void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backInserter) const
{
- *backInserter++ = {
+ playback_track_metadata_v7_t metadata;
+ metadata.base = {
.usage = mAttr.usage,
.content_type = mAttr.content_type,
.gain = mFinalVolume,
};
+ metadata.channel_mask = mChannelMask,
+ strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ *backInserter++ = metadata;
}
void AudioFlinger::PlaybackThread::Track::setTeePatches(TeePatches teePatches) {
@@ -2132,7 +2137,7 @@
binder::Status AudioFlinger::RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
int /*audio_session_t*/ triggerSession) {
ALOGV("%s()", __func__);
- return binder::Status::fromStatusT(
+ return binderStatusFromStatusT(
mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
}
@@ -2155,19 +2160,19 @@
for (size_t i = 0; status == OK && i < mics.size(); ++i) {
status = mics[i].writeToParcelable(&activeMicrophones->at(i));
}
- return binder::Status::fromStatusT(status);
+ return binderStatusFromStatusT(status);
}
binder::Status AudioFlinger::RecordHandle::setPreferredMicrophoneDirection(
int /*audio_microphone_direction_t*/ direction) {
ALOGV("%s()", __func__);
- return binder::Status::fromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
+ return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
static_cast<audio_microphone_direction_t>(direction)));
}
binder::Status AudioFlinger::RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
ALOGV("%s()", __func__);
- return binder::Status::fromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
+ return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
}
// ----------------------------------------------------------------------------
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index b00426f..e52ad5e 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -133,8 +133,8 @@
virtual status_t startOutput(audio_port_handle_t portId) = 0;
// indicates to the audio policy manager that the output stops being used by corresponding stream.
virtual status_t stopOutput(audio_port_handle_t portId) = 0;
- // releases the output.
- virtual void releaseOutput(audio_port_handle_t portId) = 0;
+ // releases the output, return true if the output descriptor is reopened.
+ virtual bool releaseOutput(audio_port_handle_t portId) = 0;
// request an input appropriate for record from the supplied device with supplied parameters.
virtual status_t getInputForAttr(const audio_attributes_t *attr,
@@ -220,16 +220,16 @@
virtual status_t dump(int fd) = 0;
virtual status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags) = 0;
- virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo) = 0;
+ virtual audio_offload_mode_t getOffloadSupport(const audio_offload_info_t& offloadInfo) = 0;
virtual bool isDirectOutputSupported(const audio_config_base_t& config,
const audio_attributes_t& attributes) = 0;
virtual status_t listAudioPorts(audio_port_role_t role,
audio_port_type_t type,
unsigned int *num_ports,
- struct audio_port *ports,
+ struct audio_port_v7 *ports,
unsigned int *generation) = 0;
- virtual status_t getAudioPort(struct audio_port *port) = 0;
+ virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
virtual status_t createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
uid_t uid) = 0;
@@ -439,6 +439,8 @@
audio_patch_handle_t patchHandle,
audio_source_t source) = 0;
+ virtual void onRoutingUpdated() = 0;
+
// Used to notify the sound trigger module that an audio capture is about to
// take place. This should typically result in any active recognition
// sessions to be preempted on modules that do not support sound trigger
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 6f47abc..a40f6aa 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -72,7 +72,7 @@
const struct audio_port_config *srcConfig = NULL) const;
virtual sp<AudioPort> getAudioPort() const { return mProfile; }
- void toAudioPort(struct audio_port *port) const;
+ void toAudioPort(struct audio_port_v7 *port) const;
void setPreemptedSessions(const SortedVector<audio_session_t>& sessions);
SortedVector<audio_session_t> getPreemptedSessions() const;
bool hasPreemptedSession(audio_session_t session) const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 1302486..1f9b535 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -261,7 +261,7 @@
const struct audio_port_config *srcConfig = NULL) const;
virtual sp<AudioPort> getAudioPort() const { return mPolicyAudioPort->asAudioPort(); }
- virtual void toAudioPort(struct audio_port *port) const;
+ virtual void toAudioPort(struct audio_port_v7 *port) const;
audio_module_handle_t getModuleHandle() const;
@@ -338,6 +338,8 @@
bool sharesHwModuleWith(const sp<SwAudioOutputDescriptor>& outputDesc);
virtual DeviceVector supportedDevices() const;
virtual bool devicesSupportEncodedFormats(const DeviceTypeSet& deviceTypes);
+ virtual bool containsSingleDeviceSupportingEncodedFormats(
+ const sp<DeviceDescriptor>& device) const;
virtual uint32_t latency();
virtual bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); }
virtual bool isFixedVolume(const DeviceTypeSet& deviceTypes);
@@ -358,7 +360,7 @@
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
- virtual void toAudioPort(struct audio_port *port) const;
+ virtual void toAudioPort(struct audio_port_v7 *port) const;
status_t open(const audio_config_t *config,
const DeviceVector &devices,
@@ -396,6 +398,14 @@
bool supportsAllDevices(const DeviceVector &devices) const;
/**
+ * @brief supportsDevicesForPlayback
+ * @param devices to be checked against
+ * @return true if the devices is a supported combo for playback
+ * false otherwise
+ */
+ bool supportsDevicesForPlayback(const DeviceVector &devices) const;
+
+ /**
* @brief filterSupportedDevices takes a vector of devices and filters them according to the
* device supported by this output (the profile from which this output derives from)
* @param devices reference device vector to be filtered
@@ -412,6 +422,7 @@
sp<SwAudioOutputDescriptor> mOutput2; // used by duplicated outputs: second output
uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only)
audio_session_t mDirectClientSession; // session id of the direct output client
+ bool mPendingReopenToQueryProfiles = false;
};
// Audio output driven by an input device directly.
@@ -432,7 +443,7 @@
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
- virtual void toAudioPort(struct audio_port *port) const;
+ virtual void toAudioPort(struct audio_port_v7 *port) const;
const sp<SourceClientDescriptor> mSource;
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index 80afe9d..59876c6 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -198,10 +198,18 @@
~SourceClientDescriptor() override = default;
+ void connect(audio_patch_handle_t patchHandle, const sp<DeviceDescriptor>& sinkDevice) {
+ mPatchHandle = patchHandle;
+ mSinkDevice = sinkDevice;
+ }
+ void disconnect() {
+ mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
+ mSinkDevice = nullptr;
+ }
+ bool isConnected() const { return mPatchHandle != AUDIO_PATCH_HANDLE_NONE; }
audio_patch_handle_t getPatchHandle() const { return mPatchHandle; }
- void setPatchHandle(audio_patch_handle_t patchHandle) { mPatchHandle = patchHandle; }
-
sp<DeviceDescriptor> srcDevice() const { return mSrcDevice; }
+ sp<DeviceDescriptor> sinkDevice() const { return mSinkDevice; }
wp<SwAudioOutputDescriptor> swOutput() const { return mSwOutput; }
void setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput);
wp<HwAudioOutputDescriptor> hwOutput() const { return mHwOutput; }
@@ -213,6 +221,7 @@
private:
audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
const sp<DeviceDescriptor> mSrcDevice;
+ sp<DeviceDescriptor> mSinkDevice;
wp<SwAudioOutputDescriptor> mSwOutput;
wp<HwAudioOutputDescriptor> mHwOutput;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 80190b7..3d338ea 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -65,9 +65,6 @@
bool supportsFormat(audio_format_t format);
- void setDynamic() { mIsDynamic = true; }
- bool isDynamic() const { return mIsDynamic; }
-
// PolicyAudioPortConfig
virtual sp<PolicyAudioPort> getPolicyAudioPort() const {
return static_cast<PolicyAudioPort*>(const_cast<DeviceDescriptor*>(this));
@@ -108,8 +105,6 @@
std::string mTagName; // Unique human readable identifier for a device port found in conf file.
FormatVector mEncodedFormats;
audio_format_t mCurrentEncodedFormat;
- bool mIsDynamic = false;
- const std::string mDeclaredAddress; // Original device address
};
class DeviceVector : public SortedVector<sp<DeviceDescriptor> >
@@ -270,6 +265,8 @@
return String8("");
}
+ const AudioProfileVector& getSupportedProfiles() { return mSupportedProfiles; }
+
// Return a string to describe the DeviceVector. The sensitive information will only be
// added to the string if `includeSensitiveInfo` is true.
std::string toString(bool includeSensitiveInfo = false) const;
@@ -278,7 +275,9 @@
private:
void refreshTypes();
+ void refreshAudioProfiles();
DeviceTypeSet mDeviceTypes;
+ AudioProfileVector mSupportedProfiles;
};
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index b5b10f3..23f0c9a 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -131,17 +131,8 @@
public:
sp<HwModule> getModuleFromName(const char *name) const;
- /**
- * @brief getModuleForDeviceType try to get a device from type / format on all modules
- * @param device type to consider
- * @param encodedFormat to consider
- * @param[out] tagName if not null, if a matching device is found, will return the tagName
- * of original device from XML file so that audio routes matchin rules work.
- * @return valid module if considered device found, nullptr otherwise.
- */
sp<HwModule> getModuleForDeviceType(audio_devices_t device,
- audio_format_t encodedFormat,
- std::string *tagName = nullptr) const;
+ audio_format_t encodedFormat) const;
sp<HwModule> getModuleForDevice(const sp<DeviceDescriptor> &device,
audio_format_t encodedFormat) const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 11d3a99..a5cd534 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -112,19 +112,6 @@
}
/**
- * @brief getTag
- * @param deviceTypes to be considered
- * @return tagName of first matching device for the considered types, empty string otherwise.
- */
- std::string getTag(const DeviceTypeSet& deviceTypes) const
- {
- if (supportsDeviceTypes(deviceTypes)) {
- return mSupportedDevices.getDevicesFromTypes(deviceTypes).itemAt(0)->getTagName();
- }
- return {};
- }
-
- /**
* @brief supportsDevice
* @param device to be checked against
* forceCheckOnAddress if true, check on type and address whatever the type, otherwise
@@ -144,7 +131,7 @@
bool devicesSupportEncodedFormats(DeviceTypeSet deviceTypes) const
{
if (deviceTypes.empty()) {
- return true; // required for isOffloadSupported() check
+ return true; // required for getOffloadSupport() check
}
DeviceVector deviceList =
mSupportedDevices.getDevicesFromTypes(deviceTypes);
@@ -156,6 +143,8 @@
return false;
}
+ bool containsSingleDeviceSupportingEncodedFormats(const sp<DeviceDescriptor>& device) const;
+
void clearSupportedDevices() { mSupportedDevices.clear(); }
void addSupportedDevice(const sp<DeviceDescriptor> &device)
{
@@ -163,12 +152,6 @@
}
void removeSupportedDevice(const sp<DeviceDescriptor> &device)
{
- ssize_t ret = mSupportedDevices.indexOf(device);
- if (ret >= 0 && !mSupportedDevices.itemAt(ret)->isDynamic()) {
- // devices equality checks only type, address, name and format
- // Prevents from removing non dynamically added devices
- return;
- }
mSupportedDevices.remove(device);
}
void setSupportedDevices(const DeviceVector &devices)
diff --git a/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h b/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
index e6eef24..d2f6297 100644
--- a/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
@@ -42,11 +42,6 @@
virtual const std::string getTagName() const = 0;
- bool equals(const sp<PolicyAudioPort> &right) const
- {
- return getTagName() == right->getTagName();
- }
-
virtual sp<AudioPort> asAudioPort() const = 0;
virtual void setFlags(uint32_t flags)
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 4922ebe..7016a08 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -92,7 +92,7 @@
dstConfig->ext.mix.usecase.source = source();
}
-void AudioInputDescriptor::toAudioPort(struct audio_port *port) const
+void AudioInputDescriptor::toAudioPort(struct audio_port_v7 *port) const
{
ALOG_ASSERT(mProfile != 0, "toAudioPort() called on input with null profile %d", mIoHandle);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 1756021..b872709 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -215,7 +215,7 @@
dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT;
}
-void AudioOutputDescriptor::toAudioPort(struct audio_port *port) const
+void AudioOutputDescriptor::toAudioPort(struct audio_port_v7 *port) const
{
// Should not be called for duplicated ports, see SwAudioOutputDescriptor::toAudioPortConfig.
mPolicyAudioPort->asAudioPort()->toAudioPort(port);
@@ -344,6 +344,13 @@
return supportedDevices().containsAllDevices(devices);
}
+bool SwAudioOutputDescriptor::supportsDevicesForPlayback(const DeviceVector &devices) const
+{
+ // No considering duplicated output
+ // TODO: need to verify if the profile supports the devices combo for playback.
+ return !isDuplicated() && supportsAllDevices(devices);
+}
+
DeviceVector SwAudioOutputDescriptor::filterSupportedDevices(const DeviceVector &devices) const
{
DeviceVector filteredDevices = supportedDevices();
@@ -360,6 +367,16 @@
}
}
+bool SwAudioOutputDescriptor::containsSingleDeviceSupportingEncodedFormats(
+ const sp<DeviceDescriptor>& device) const
+{
+ if (isDuplicated()) {
+ return (mOutput1->containsSingleDeviceSupportingEncodedFormats(device) &&
+ mOutput2->containsSingleDeviceSupportingEncodedFormats(device));
+ }
+ return mProfile->containsSingleDeviceSupportingEncodedFormats(device);
+}
+
uint32_t SwAudioOutputDescriptor::latency()
{
if (isDuplicated()) {
@@ -406,8 +423,7 @@
dstConfig->ext.mix.handle = mIoHandle;
}
-void SwAudioOutputDescriptor::toAudioPort(
- struct audio_port *port) const
+void SwAudioOutputDescriptor::toAudioPort(struct audio_port_v7 *port) const
{
ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle);
@@ -654,8 +670,7 @@
mSource->srcDevice()->toAudioPortConfig(dstConfig, srcConfig);
}
-void HwAudioOutputDescriptor::toAudioPort(
- struct audio_port *port) const
+void HwAudioOutputDescriptor::toAudioPort(struct audio_port_v7 *port) const
{
mSource->srcDevice()->toAudioPort(port);
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
index c8e4e76..2a18f19 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
@@ -39,12 +39,12 @@
bool AudioRoute::supportsPatch(const sp<PolicyAudioPort> &srcPort,
const sp<PolicyAudioPort> &dstPort) const
{
- if (mSink == 0 || dstPort == 0 || !dstPort->equals(mSink)) {
+ if (mSink == 0 || dstPort == 0 || dstPort != mSink) {
return false;
}
ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().c_str());
for (const auto &sourcePort : mSources) {
- if (sourcePort->equals(srcPort)) {
+ if (sourcePort == srcPort) {
ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().c_str());
return true;
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index e43ca0f..6c31b79 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -52,8 +52,7 @@
DeviceDescriptor::DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr,
const std::string &tagName,
const FormatVector &encodedFormats) :
- DeviceDescriptorBase(deviceTypeAddr), mTagName(tagName), mEncodedFormats(encodedFormats),
- mDeclaredAddress(deviceTypeAddr.getAddress())
+ DeviceDescriptorBase(deviceTypeAddr), mTagName(tagName), mEncodedFormats(encodedFormats)
{
mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
/* If framework runs against a pre 5.0 Audio HAL, encoded formats are absent from the config.
@@ -76,10 +75,6 @@
void DeviceDescriptor::detach() {
mId = AUDIO_PORT_HANDLE_NONE;
PolicyAudioPort::detach();
- // The device address may have been overwritten on device connection
- setAddress(mDeclaredAddress);
- // Device Port does not have a name unless provided by setDeviceConnectionState
- setName("");
}
template<typename T>
@@ -222,6 +217,18 @@
ALOGV("DeviceVector::refreshTypes() mDeviceTypes %s", dumpDeviceTypes(mDeviceTypes).c_str());
}
+void DeviceVector::refreshAudioProfiles() {
+ if (empty()) {
+ mSupportedProfiles.clear();
+ return;
+ }
+ mSupportedProfiles = itemAt(0)->getAudioProfiles();
+ for (size_t i = 1; i < size(); ++i) {
+ mSupportedProfiles = intersectAudioProfiles(
+ mSupportedProfiles, itemAt(i)->getAudioProfiles());
+ }
+}
+
ssize_t DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
{
for (size_t i = 0; i < size(); i++) {
@@ -243,6 +250,7 @@
}
if (added) {
refreshTypes();
+ refreshAudioProfiles();
}
}
@@ -255,6 +263,7 @@
ret = SortedVector::add(item);
if (ret >= 0) {
refreshTypes();
+ refreshAudioProfiles();
}
} else {
ALOGW("DeviceVector::add device %08x already in", item->type());
@@ -273,6 +282,7 @@
ret = SortedVector::removeAt(ret);
if (ret >= 0) {
refreshTypes();
+ refreshAudioProfiles();
}
}
return ret;
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 2967014..d31e443 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -271,9 +271,8 @@
return nullptr;
}
-sp<HwModule> HwModuleCollection::getModuleForDeviceType(audio_devices_t type,
- audio_format_t encodedFormat,
- std::string *tagName) const
+sp <HwModule> HwModuleCollection::getModuleForDeviceType(audio_devices_t type,
+ audio_format_t encodedFormat) const
{
for (const auto& module : *this) {
const auto& profiles = audio_is_output_device(type) ?
@@ -285,15 +284,9 @@
sp <DeviceDescriptor> deviceDesc =
declaredDevices.getDevice(type, String8(), encodedFormat);
if (deviceDesc) {
- if (tagName != nullptr) {
- *tagName = deviceDesc->getTagName();
- }
return module;
}
} else {
- if (tagName != nullptr) {
- *tagName = profile->getTag({type});
- }
return module;
}
}
@@ -332,32 +325,15 @@
}
for (const auto& hwModule : *this) {
- if (!allowToCreate) {
- auto dynamicDevices = hwModule->getDynamicDevices();
- auto dynamicDevice = dynamicDevices.getDevice(deviceType, devAddress, encodedFormat);
- if (dynamicDevice) {
- return dynamicDevice;
- }
- }
DeviceVector moduleDevices = hwModule->getAllDevices();
auto moduleDevice = moduleDevices.getDevice(deviceType, devAddress, encodedFormat);
-
- // Prevent overwritting moduleDevice address if connected device does not have the same
- // address (since getDevice with empty address ignores match on address), use dynamic device
- if (moduleDevice && allowToCreate &&
- (!moduleDevice->address().empty() &&
- (moduleDevice->address().compare(devAddress.c_str()) != 0))) {
- break;
- }
if (moduleDevice) {
if (encodedFormat != AUDIO_FORMAT_DEFAULT) {
moduleDevice->setEncodedFormat(encodedFormat);
}
if (allowToCreate) {
moduleDevice->attach(hwModule);
- // Name may be overwritten, restored on detach.
moduleDevice->setAddress(devAddress.string());
- // Name may be overwritten, restored on detach.
moduleDevice->setName(name);
}
return moduleDevice;
@@ -376,19 +352,18 @@
const char *name,
const audio_format_t encodedFormat) const
{
- std::string tagName = {};
- sp<HwModule> hwModule = getModuleForDeviceType(type, encodedFormat, &tagName);
+ sp<HwModule> hwModule = getModuleForDeviceType(type, encodedFormat);
if (hwModule == 0) {
ALOGE("%s: could not find HW module for device %04x address %s", __FUNCTION__, type,
address);
return nullptr;
}
- sp<DeviceDescriptor> device = new DeviceDescriptor(type, tagName, address);
+ sp<DeviceDescriptor> device = new DeviceDescriptor(type, name, address);
device->setName(name);
device->setEncodedFormat(encodedFormat);
- device->setDynamic();
- // Add the device to the list of dynamic devices
+
+ // Add the device to the list of dynamic devices
hwModule->addDynamicDevice(device);
// Reciprocally attach the device to the module
device->attach(hwModule);
@@ -400,7 +375,7 @@
for (const auto &profile : profiles) {
// Add the device as supported to all profile supporting "weakly" or not the device
// according to its type
- if (profile->supportsDevice(device, false /*matchAddress*/)) {
+ if (profile->supportsDevice(device, false /*matchAdress*/)) {
// @todo quid of audio profile? import the profile from device of the same type?
const auto &isoTypeDeviceForProfile =
@@ -431,9 +406,10 @@
device->detach();
// Only remove from dynamic list, not from declared list!!!
- if (!hwModule->removeDynamicDevice(device)) {
+ if (!hwModule->getDynamicDevices().contains(device)) {
return;
}
+ hwModule->removeDynamicDevice(device);
ALOGV("%s: removed dynamic device %s from module %s", __FUNCTION__,
device->toString().c_str(), hwModule->getName());
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index ae92b40..09b614d 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -105,6 +105,17 @@
return true;
}
+bool IOProfile::containsSingleDeviceSupportingEncodedFormats(
+ const sp<DeviceDescriptor>& device) const {
+ if (device == nullptr) {
+ return false;
+ }
+ DeviceVector deviceList = mSupportedDevices.getDevicesFromType(device->type());
+ return std::count_if(deviceList.begin(), deviceList.end(),
+ [&device](sp<DeviceDescriptor> deviceDesc) {
+ return device == deviceDesc && deviceDesc->hasCurrentEncodedFormat(); }) == 1;
+}
+
void IOProfile::dump(String8 *dst) const
{
std::string portStr;
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index eccde7b..d038ce5 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -184,16 +184,7 @@
break;
case STRATEGY_DTMF:
- if (!isInCall()) {
- // when off call, DTMF strategy follows the same rules as MEDIA strategy
- devices = getDevicesForStrategyInt(
- STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
- break;
- }
- // when in call, DTMF and PHONE strategies follow the same rules
- FALLTHROUGH_INTENDED;
-
- case STRATEGY_PHONE:
+ case STRATEGY_PHONE: {
// Force use of only devices on primary output if:
// - in call AND
// - cannot route from voice call RX OR
@@ -216,84 +207,24 @@
availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID));
if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
- String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
- ((availPrimaryInputDevices.getDevice(
- txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
- (primaryOutput->getPolicyAudioPort()->getModuleVersionMajor() < 3))) {
+ String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
+ ((availPrimaryInputDevices.getDevice(
+ txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
+ (primaryOutput->getPolicyAudioPort()->getModuleVersionMajor() < 3))) {
availableOutputDevices = availPrimaryOutputDevices;
}
}
- // for phone strategy, we first consider the forced use and then the available devices by
- // order of priority
- switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
- case AUDIO_POLICY_FORCE_BT_SCO:
- if (!isInCall() || strategy != STRATEGY_DTMF) {
- devices = availableOutputDevices.getDevicesFromType(
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
- if (!devices.isEmpty()) break;
- }
- devices = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
- if (!devices.isEmpty()) break;
- // if SCO device is requested but no SCO device is available, fall back to default case
- FALLTHROUGH_INTENDED;
-
- default: // FORCE_NONE
- devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
- if (!devices.isEmpty()) break;
-
- // TODO (b/161358428): remove when preferred device
- // for strategy phone will be used instead of AUDIO_POLICY_FORCE_FOR_COMMUNICATION
- devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_BLE_HEADSET);
- if (!devices.isEmpty()) break;
-
- // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
- if (!isInCall() &&
- (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
- devices = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES});
- if (!devices.isEmpty()) break;
- }
- devices = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADSET,
- AUDIO_DEVICE_OUT_LINE, AUDIO_DEVICE_OUT_USB_HEADSET,
- AUDIO_DEVICE_OUT_USB_DEVICE});
- if (!devices.isEmpty()) break;
- if (!isInCall()) {
- devices = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
- AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
- if (!devices.isEmpty()) break;
- }
- devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_EARPIECE);
- break;
-
- case AUDIO_POLICY_FORCE_SPEAKER:
- // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
- // A2DP speaker when forcing to speaker output
- if (!isInCall()) {
- devices = availableOutputDevices.getDevicesFromType(
- AUDIO_DEVICE_OUT_BLE_SPEAKER);
- if (!devices.isEmpty()) break;
-
- if ((getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
- devices = availableOutputDevices.getDevicesFromType(
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
- if (!devices.isEmpty()) break;
- }
- }
- if (!isInCall()) {
- devices = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_DEVICE,
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_AUX_DIGITAL,
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
- if (!devices.isEmpty()) break;
- }
- devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
- break;
- }
- break;
+ devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
+ if (!devices.isEmpty()) break;
+ devices = availableOutputDevices.getFirstDevicesFromTypes({
+ AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+ AUDIO_DEVICE_OUT_WIRED_HEADSET,
+ AUDIO_DEVICE_OUT_LINE,
+ AUDIO_DEVICE_OUT_USB_HEADSET,
+ AUDIO_DEVICE_OUT_USB_DEVICE});
+ if (!devices.isEmpty()) break;
+ devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_EARPIECE);
+ } break;
case STRATEGY_SONIFICATION:
@@ -336,7 +267,8 @@
}
}
// Use both Bluetooth SCO and phone default output when ringing in normal mode
- if (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) == AUDIO_POLICY_FORCE_BT_SCO) {
+ if (audio_is_bluetooth_out_sco_device(getPreferredDeviceTypeForLegacyStrategy(
+ availableOutputDevices, STRATEGY_PHONE))) {
if (strategy == STRATEGY_SONIFICATION) {
devices.replaceDevicesByType(
AUDIO_DEVICE_OUT_SPEAKER,
@@ -510,13 +442,16 @@
}
}
+ audio_devices_t commDeviceType =
+ getPreferredDeviceTypeForLegacyStrategy(availableOutputDevices, STRATEGY_PHONE);
+
switch (inputSource) {
case AUDIO_SOURCE_DEFAULT:
case AUDIO_SOURCE_MIC:
device = availableDevices.getDevice(
AUDIO_DEVICE_IN_BLUETOOTH_A2DP, String8(""), AUDIO_FORMAT_DEFAULT);
if (device != nullptr) break;
- if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
+ if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
device = availableDevices.getDevice(
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
if (device != nullptr) break;
@@ -524,7 +459,7 @@
device = availableDevices.getFirstExistingDevice({
AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET,
AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_IN_USB_DEVICE,
- AUDIO_DEVICE_IN_BUILTIN_MIC});
+ AUDIO_DEVICE_IN_BLUETOOTH_BLE, AUDIO_DEVICE_IN_BUILTIN_MIC});
break;
case AUDIO_SOURCE_VOICE_COMMUNICATION:
@@ -537,43 +472,56 @@
availableDevices = availablePrimaryDevices;
}
- switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
- case AUDIO_POLICY_FORCE_BT_SCO:
+ if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
// if SCO device is requested but no SCO device is available, fall back to default case
device = availableDevices.getDevice(
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
if (device != nullptr) {
break;
}
- FALLTHROUGH_INTENDED;
-
- default: // FORCE_NONE
- // TODO (b/161358428): remove AUDIO_DEVICE_IN_BLE_HEADSET from the list
- // when preferred device for strategy phone will be used instead of
- // AUDIO_POLICY_FORCE_FOR_COMMUNICATION.
+ }
+ switch (commDeviceType) {
+ case AUDIO_DEVICE_OUT_BLE_HEADSET:
+ device = availableDevices.getDevice(
+ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+ break;
+ case AUDIO_DEVICE_OUT_SPEAKER:
device = availableDevices.getFirstExistingDevice({
- AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET,
- AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_IN_USB_DEVICE,
+ AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC,
+ AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_USB_HEADSET});
+ break;
+ default: // FORCE_NONE
+ device = availableDevices.getFirstExistingDevice({
+ AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
+ AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BLUETOOTH_BLE,
AUDIO_DEVICE_IN_BUILTIN_MIC});
break;
- case AUDIO_POLICY_FORCE_SPEAKER:
- device = availableDevices.getFirstExistingDevice({
- AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC});
- break;
}
break;
case AUDIO_SOURCE_VOICE_RECOGNITION:
case AUDIO_SOURCE_UNPROCESSED:
- case AUDIO_SOURCE_HOTWORD:
- if (inputSource == AUDIO_SOURCE_HOTWORD) {
- // We should not use primary output criteria for Hotword but rather limit
- // to devices attached to the same HW module as the build in mic
- LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
- availableDevices = availablePrimaryDevices;
+ if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
+ device = availableDevices.getDevice(
+ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+ if (device != nullptr) break;
}
- if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
+ // we need to make BLUETOOTH_BLE has higher priority than BUILTIN_MIC,
+ // because sometimes user want to do voice search by bt remote
+ // even if BUILDIN_MIC is available.
+ device = availableDevices.getFirstExistingDevice({
+ AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET,
+ AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_IN_USB_DEVICE,
+ AUDIO_DEVICE_IN_BLUETOOTH_BLE, AUDIO_DEVICE_IN_BUILTIN_MIC});
+
+ break;
+ case AUDIO_SOURCE_HOTWORD:
+ // We should not use primary output criteria for Hotword but rather limit
+ // to devices attached to the same HW module as the build in mic
+ LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
+ availableDevices = availablePrimaryDevices;
+ if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
device = availableDevices.getDevice(
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
if (device != nullptr) break;
@@ -598,7 +546,8 @@
case AUDIO_SOURCE_VOICE_PERFORMANCE:
device = availableDevices.getFirstExistingDevice({
AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
- AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
+ AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BLUETOOTH_BLE,
+ AUDIO_DEVICE_IN_BUILTIN_MIC});
break;
case AUDIO_SOURCE_REMOTE_SUBMIX:
device = availableDevices.getDevice(
@@ -623,6 +572,7 @@
ALOGE_IF(device == nullptr,
"getDeviceForInputSource() no default device defined");
}
+
ALOGV_IF(device != nullptr,
"getDeviceForInputSource()input source %d, device %08x",
inputSource, device->type());
@@ -640,17 +590,35 @@
}
}
-DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
- DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
+product_strategy_t Engine::getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const {
+ for (const auto& strategyMap : mLegacyStrategyMap) {
+ if (strategyMap.second == legacyStrategy) {
+ return strategyMap.first;
+ }
+ }
+ return PRODUCT_STRATEGY_NONE;
+}
- // check if this strategy has a preferred device that is available,
- // if yes, give priority to it
+audio_devices_t Engine::getPreferredDeviceTypeForLegacyStrategy(
+ const DeviceVector& availableOutputDevices, legacy_strategy legacyStrategy) const {
+ product_strategy_t strategy = getProductStrategyFromLegacy(legacyStrategy);
+ DeviceVector devices = getPreferredAvailableDevicesForProductStrategy(
+ availableOutputDevices, strategy);
+ if (devices.size() > 0) {
+ return devices[0]->type();
+ }
+ return AUDIO_DEVICE_NONE;
+}
+
+DeviceVector Engine::getPreferredAvailableDevicesForProductStrategy(
+ const DeviceVector& availableOutputDevices, product_strategy_t strategy) const {
+ DeviceVector preferredAvailableDevVec = {};
AudioDeviceTypeAddrVector preferredStrategyDevices;
const status_t status = getDevicesForRoleAndStrategy(
strategy, DEVICE_ROLE_PREFERRED, preferredStrategyDevices);
if (status == NO_ERROR) {
// there is a preferred device, is it available?
- DeviceVector preferredAvailableDevVec =
+ preferredAvailableDevVec =
availableOutputDevices.getDevicesFromDeviceTypeAddrVec(preferredStrategyDevices);
if (preferredAvailableDevVec.size() == preferredAvailableDevVec.size()) {
ALOGVV("%s using pref device %s for strategy %u",
@@ -658,11 +626,30 @@
return preferredAvailableDevVec;
}
}
+ return preferredAvailableDevVec;
+}
+
+DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
+ DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
+ auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
+ mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
+
+ // When not in call, STRATEGY_PHONE and STRATEGY_DTMF follow STRATEGY_MEDIA
+ if (!isInCall() && (legacyStrategy == STRATEGY_PHONE || legacyStrategy == STRATEGY_DTMF)) {
+ legacyStrategy = STRATEGY_MEDIA;
+ strategy = getProductStrategyFromLegacy(STRATEGY_MEDIA);
+ }
+ // check if this strategy has a preferred device that is available,
+ // if yes, give priority to it.
+ DeviceVector preferredAvailableDevVec =
+ getPreferredAvailableDevicesForProductStrategy(availableOutputDevices, strategy);
+ if (!preferredAvailableDevVec.isEmpty()) {
+ return preferredAvailableDevVec;
+ }
DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();
- auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
- mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
+
return getDevicesForStrategyInt(legacyStrategy,
availableOutputDevices,
availableInputDevices, outputs);
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index bb9e2df..6214fe7 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -83,6 +83,12 @@
sp<DeviceDescriptor> getDeviceForInputSource(audio_source_t inputSource) const;
+ product_strategy_t getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const;
+ audio_devices_t getPreferredDeviceTypeForLegacyStrategy(
+ const DeviceVector& availableOutputDevices, legacy_strategy legacyStrategy) const;
+ DeviceVector getPreferredAvailableDevicesForProductStrategy(
+ const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
+
DeviceStrategyMap mDevicesForStrategies;
std::map<product_strategy_t, legacy_strategy> mLegacyStrategyMap;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index cc4ec36..51abef1 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -206,6 +206,9 @@
// Reset active device codec
device->setEncodedFormat(AUDIO_FORMAT_DEFAULT);
+ // remove device from mReportedFormatsMap cache
+ mReportedFormatsMap.erase(device);
+
} break;
default:
@@ -243,6 +246,7 @@
if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) ||
(((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
(desc->mDirectOpenCount == 0))) {
+ clearAudioSourcesForOutput(output);
closeOutput(output);
}
}
@@ -262,7 +266,10 @@
DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
updateCallRouting(newDevices);
}
+ std::vector<audio_io_handle_t> outputsToReopen;
const DeviceVector msdOutDevices = getMsdAudioOutDevices();
+ const DeviceVector activeMediaDevices =
+ mEngine->getActiveMediaDevices(mAvailableOutputDevices);
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (desc != mPrimaryOutput)) {
@@ -277,6 +284,28 @@
|| (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
setOutputDevices(desc, newDevices, force, 0);
}
+ if (!desc->isDuplicated() && desc->mProfile->hasDynamicAudioProfile() &&
+ desc->devices() != activeMediaDevices &&
+ desc->supportsDevicesForPlayback(activeMediaDevices)) {
+ // Reopen the output to query the dynamic profiles when there is not active
+ // clients or all active clients will be rerouted. Otherwise, set the flag
+ // `mPendingReopenToQueryProfiles` in the SwOutputDescriptor so that the output
+ // can be reopened to query dynamic profiles when all clients are inactive.
+ if (areAllActiveTracksRerouted(desc)) {
+ outputsToReopen.push_back(mOutputs.keyAt(i));
+ } else {
+ desc->mPendingReopenToQueryProfiles = true;
+ }
+ }
+ if (!desc->supportsDevicesForPlayback(activeMediaDevices)) {
+ // Clear the flag that previously set for re-querying profiles.
+ desc->mPendingReopenToQueryProfiles = false;
+ }
+ }
+ for (const auto& output : outputsToReopen) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
+ closeOutput(output);
+ openOutputWithProfileAndDevice(desc->mProfile, activeMediaDevices);
}
if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
@@ -334,6 +363,9 @@
mAvailableInputDevices.remove(device);
checkInputsForDevice(device, state);
+
+ // remove device from mReportedFormatsMap cache
+ mReportedFormatsMap.erase(device);
} break;
default:
@@ -353,7 +385,11 @@
DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
updateCallRouting(newDevices);
}
-
+ // Reconnect Audio Source
+ for (const auto &strategy : mEngine->getOrderedProductStrategies()) {
+ auto attributes = mEngine->getAllAttributesForProductStrategy(strategy).front();
+ checkAudioSourceForAttributes(attributes);
+ }
if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
cleanUpForDevice(device);
}
@@ -438,7 +474,7 @@
// Case 1: A2DP active device switches from primary to primary
// module
// Case 2: A2DP device config changes on primary module.
- if (audio_is_a2dp_out_device(device)) {
+ if (audio_is_a2dp_out_device(device) && hasPrimaryOutput()) {
sp<HwModule> module = mHwModules.getModuleForDeviceType(device, encodedFormat);
audio_module_handle_t primaryHandle = mPrimaryOutput->getModuleHandle();
if (availablePrimaryOutputDevices().contains(devDesc) &&
@@ -532,11 +568,7 @@
ALOGV("updateCallRouting device rxDevice %s txDevice %s",
rxDevices.itemAt(0)->toString().c_str(), txSourceDevice->toString().c_str());
- // release existing RX patch if any
- if (mCallRxPatch != 0) {
- releaseAudioPatchInternal(mCallRxPatch->getHandle());
- mCallRxPatch.clear();
- }
+ disconnectTelephonyRxAudioSource();
// release TX patch if any
if (mCallTxPatch != 0) {
releaseAudioPatchInternal(mCallTxPatch->getHandle());
@@ -584,8 +616,7 @@
if (!createRxPatch) {
muteWaitMs = setOutputDevices(mPrimaryOutput, rxDevices, true, delayMs);
} else { // create RX path audio patch
- mCallRxPatch = createTelephonyPatch(true /*isRx*/, rxDevices.itemAt(0), delayMs);
-
+ connectTelephonyRxAudioSource();
// If the TX device is on the primary HW module but RX device is
// on other HW module, SinkMetaData of telephony input should handle it
// assuming the device uses audio HAL V5.0 and above
@@ -648,6 +679,24 @@
return false;
}
+void AudioPolicyManager::connectTelephonyRxAudioSource()
+{
+ disconnectTelephonyRxAudioSource();
+ const struct audio_port_config source = {
+ .role = AUDIO_PORT_ROLE_SOURCE, .type = AUDIO_PORT_TYPE_DEVICE,
+ .ext.device.type = AUDIO_DEVICE_IN_TELEPHONY_RX, .ext.device.address = ""
+ };
+ const auto aa = mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL);
+ status_t status = startAudioSource(&source, &aa, &mCallRxSourceClientPort, 0/*uid*/);
+ ALOGE_IF(status != NO_ERROR, "%s failed to start Telephony Rx AudioSource", __func__);
+}
+
+void AudioPolicyManager::disconnectTelephonyRxAudioSource()
+{
+ stopAudioSource(mCallRxSourceClientPort);
+ mCallRxSourceClientPort = AUDIO_PORT_HANDLE_NONE;
+}
+
void AudioPolicyManager::setPhoneState(audio_mode_t state)
{
ALOGV("setPhoneState() state %d", state);
@@ -715,10 +764,7 @@
if (state == AUDIO_MODE_IN_CALL) {
updateCallRouting(rxDevices, delayMs);
} else if (oldState == AUDIO_MODE_IN_CALL) {
- if (mCallRxPatch != 0) {
- releaseAudioPatchInternal(mCallRxPatch->getHandle());
- mCallRxPatch.clear();
- }
+ disconnectTelephonyRxAudioSource();
if (mCallTxPatch != 0) {
releaseAudioPatchInternal(mCallTxPatch->getHandle());
mCallTxPatch.clear();
@@ -786,16 +832,7 @@
}
updateCallAndOutputRouting(forceVolumeReeval, delayMs);
-
- for (const auto& activeDesc : mInputs.getActiveInputs()) {
- auto newDevice = getNewInputDevice(activeDesc);
- // Force new input selection if the new device can not be reached via current input
- if (activeDesc->mProfile->getSupportedDevices().contains(newDevice)) {
- setInputDevice(activeDesc->mIoHandle, newDevice);
- } else {
- closeInput(activeDesc->mIoHandle);
- }
- }
+ updateInputRouting();
}
void AudioPolicyManager::setSystemProperty(const char* property, const char* value)
@@ -1031,7 +1068,6 @@
if (*output != AUDIO_IO_HANDLE_NONE && setMsdPatch(device) == NO_ERROR) {
ALOGV("%s() Using MSD devices %s instead of devices %s",
__func__, msdDevices.toString().c_str(), outputDevices.toString().c_str());
- outputDevices = msdDevices;
} else {
*output = AUDIO_IO_HANDLE_NONE;
}
@@ -1936,7 +1972,7 @@
}
}
-void AudioPolicyManager::releaseOutput(audio_port_handle_t portId)
+bool AudioPolicyManager::releaseOutput(audio_port_handle_t portId)
{
ALOGV("%s portId %d", __FUNCTION__, portId);
@@ -1949,7 +1985,7 @@
//
// Here we just log a warning, instead of a fatal error.
ALOGW("releaseOutput() no output for client %d", portId);
- return;
+ return false;
}
ALOGV("releaseOutput() %d", outputDesc->mIoHandle);
@@ -1964,7 +2000,7 @@
if (outputDesc->mDirectOpenCount <= 0) {
ALOGW("releaseOutput() invalid open count %d for output %d",
outputDesc->mDirectOpenCount, outputDesc->mIoHandle);
- return;
+ return false;
}
if (--outputDesc->mDirectOpenCount == 0) {
closeOutput(outputDesc->mIoHandle);
@@ -1973,6 +2009,18 @@
}
outputDesc->removeClient(portId);
+ if (outputDesc->mPendingReopenToQueryProfiles && outputDesc->getClientCount() == 0) {
+ // The output is pending reopened to query dynamic profiles and
+ // there is no active clients
+ closeOutput(outputDesc->mIoHandle);
+ sp<SwAudioOutputDescriptor> newOutputDesc = openOutputWithProfileAndDevice(
+ outputDesc->mProfile, mEngine->getActiveMediaDevices(mAvailableOutputDevices));
+ if (newOutputDesc == nullptr) {
+ ALOGE("%s failed to open output", __func__);
+ }
+ return true;
+ }
+ return false;
}
status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
@@ -3158,6 +3206,7 @@
return res;
}
+
status_t AudioPolicyManager::setDevicesRoleForStrategy(product_strategy_t strategy,
device_role_t role,
const AudioDeviceTypeAddrVector &devices) {
@@ -3175,7 +3224,17 @@
}
checkForDeviceAndOutputChanges();
- updateCallAndOutputRouting();
+
+ bool forceVolumeReeval = false;
+ // FIXME: workaround for truncated touch sounds
+ // to be removed when the problem is handled by system UI
+ uint32_t delayMs = 0;
+ if (strategy == mCommunnicationStrategy) {
+ forceVolumeReeval = true;
+ delayMs = TOUCH_SOUND_FIXED_DELAY_MS;
+ updateInputRouting();
+ }
+ updateCallAndOutputRouting(forceVolumeReeval, delayMs);
return NO_ERROR;
}
@@ -3206,6 +3265,18 @@
}
}
+void AudioPolicyManager::updateInputRouting() {
+ for (const auto& activeDesc : mInputs.getActiveInputs()) {
+ auto newDevice = getNewInputDevice(activeDesc);
+ // Force new input selection if the new device can not be reached via current input
+ if (activeDesc->mProfile->getSupportedDevices().contains(newDevice)) {
+ setInputDevice(activeDesc->mIoHandle, newDevice);
+ } else {
+ closeInput(activeDesc->mIoHandle);
+ }
+ }
+}
+
status_t AudioPolicyManager::removeDevicesRoleForStrategy(product_strategy_t strategy,
device_role_t role)
{
@@ -3213,12 +3284,23 @@
status_t status = mEngine->removeDevicesRoleForStrategy(strategy, role);
if (status != NO_ERROR) {
- ALOGW("Engine could not remove preferred device for strategy %d", strategy);
+ ALOGV("Engine could not remove preferred device for strategy %d status %d",
+ strategy, status);
return status;
}
checkForDeviceAndOutputChanges();
- updateCallAndOutputRouting();
+
+ bool forceVolumeReeval = false;
+ // FIXME: workaround for truncated touch sounds
+ // to be removed when the problem is handled by system UI
+ uint32_t delayMs = 0;
+ if (strategy == mCommunnicationStrategy) {
+ forceVolumeReeval = true;
+ delayMs = TOUCH_SOUND_FIXED_DELAY_MS;
+ updateInputRouting();
+ }
+ updateCallAndOutputRouting(forceVolumeReeval, delayMs);
return NO_ERROR;
}
@@ -3258,6 +3340,7 @@
"Engine could not add preferred devices %s for audio source %d role %d",
dumpAudioDeviceTypeAddrVector(devices).c_str(), audioSource, role);
+ updateInputRouting();
return status;
}
@@ -3276,6 +3359,7 @@
ALOGW_IF(status != NO_ERROR,
"Engine could not remove devices role (%d) for capture preset %d", role, audioSource);
+ updateInputRouting();
return status;
}
@@ -3287,6 +3371,7 @@
ALOGW_IF(status != NO_ERROR,
"Engine could not clear devices role (%d) for capture preset %d", role, audioSource);
+ updateInputRouting();
return status;
}
@@ -3356,7 +3441,9 @@
}
dst->appendFormat(" TTS output %savailable\n", mTtsOutputAvailable ? "" : "not ");
dst->appendFormat(" Master mono: %s\n", mMasterMono ? "on" : "off");
+ dst->appendFormat(" Communnication Strategy: %d\n", mCommunnicationStrategy);
dst->appendFormat(" Config source: %s\n", mConfig.getSource().c_str()); // getConfig not const
+
mAvailableOutputDevices.dump(dst, String8("Available output"));
mAvailableInputDevices.dump(dst, String8("Available input"));
mHwModulesAll.dump(dst);
@@ -3393,38 +3480,38 @@
// This function checks for the parameters which can be offloaded.
// This can be enhanced depending on the capability of the DSP and policy
// of the system.
-bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadInfo)
+audio_offload_mode_t AudioPolicyManager::getOffloadSupport(const audio_offload_info_t& offloadInfo)
{
- ALOGV("isOffloadSupported: SR=%u, CM=0x%x, Format=0x%x, StreamType=%d,"
+ ALOGV("%s: SR=%u, CM=0x%x, Format=0x%x, StreamType=%d,"
" BitRate=%u, duration=%" PRId64 " us, has_video=%d",
- offloadInfo.sample_rate, offloadInfo.channel_mask,
+ __func__, offloadInfo.sample_rate, offloadInfo.channel_mask,
offloadInfo.format,
offloadInfo.stream_type, offloadInfo.bit_rate, offloadInfo.duration_us,
offloadInfo.has_video);
if (mMasterMono) {
- return false; // no offloading if mono is set.
+ return AUDIO_OFFLOAD_NOT_SUPPORTED; // no offloading if mono is set.
}
// Check if offload has been disabled
if (property_get_bool("audio.offload.disable", false /* default_value */)) {
- ALOGV("offload disabled by audio.offload.disable");
- return false;
+ ALOGV("%s: offload disabled by audio.offload.disable", __func__);
+ return AUDIO_OFFLOAD_NOT_SUPPORTED;
}
// Check if stream type is music, then only allow offload as of now.
if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC)
{
- ALOGV("isOffloadSupported: stream_type != MUSIC, returning false");
- return false;
+ ALOGV("%s: stream_type != MUSIC, returning false", __func__);
+ return AUDIO_OFFLOAD_NOT_SUPPORTED;
}
//TODO: enable audio offloading with video when ready
const bool allowOffloadWithVideo =
property_get_bool("audio.offload.video", false /* default_value */);
if (offloadInfo.has_video && !allowOffloadWithVideo) {
- ALOGV("isOffloadSupported: has_video == true, returning false");
- return false;
+ ALOGV("%s: has_video == true, returning false", __func__);
+ return AUDIO_OFFLOAD_NOT_SUPPORTED;
}
//If duration is less than minimum value defined in property, return false
@@ -3432,13 +3519,14 @@
"audio.offload.min.duration.secs", -1 /* default_value */);
if (min_duration_secs >= 0) {
if (offloadInfo.duration_us < min_duration_secs * 1000000LL) {
- ALOGV("Offload denied by duration < audio.offload.min.duration.secs(=%d)",
- min_duration_secs);
- return false;
+ ALOGV("%s: Offload denied by duration < audio.offload.min.duration.secs(=%d)",
+ __func__, min_duration_secs);
+ return AUDIO_OFFLOAD_NOT_SUPPORTED;
}
} else if (offloadInfo.duration_us < OFFLOAD_DEFAULT_MIN_DURATION_SECS * 1000000) {
- ALOGV("Offload denied by duration < default min(=%u)", OFFLOAD_DEFAULT_MIN_DURATION_SECS);
- return false;
+ ALOGV("%s: Offload denied by duration < default min(=%u)",
+ __func__, OFFLOAD_DEFAULT_MIN_DURATION_SECS);
+ return AUDIO_OFFLOAD_NOT_SUPPORTED;
}
// Do not allow offloading if one non offloadable effect is enabled. This prevents from
@@ -3448,7 +3536,7 @@
// This may prevent offloading in rare situations where effects are left active by apps
// in the background.
if (mEffects.isNonOffloadableEffectEnabled()) {
- return false;
+ return AUDIO_OFFLOAD_NOT_SUPPORTED;
}
// See if there is a profile to support this.
@@ -3459,8 +3547,14 @@
offloadInfo.channel_mask,
AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD,
true /* directOnly */);
- ALOGV("isOffloadSupported() profile %sfound", profile != 0 ? "" : "NOT ");
- return (profile != 0);
+ ALOGV("%s: profile %sfound", __func__, profile != 0 ? "" : "NOT ");
+ if (profile == nullptr) {
+ return AUDIO_OFFLOAD_NOT_SUPPORTED;
+ }
+ if ((profile->getFlags() & AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD) != 0) {
+ return AUDIO_OFFLOAD_GAPLESS_SUPPORTED;
+ }
+ return AUDIO_OFFLOAD_SUPPORTED;
}
bool AudioPolicyManager::isDirectOutputSupported(const audio_config_base_t& config,
@@ -3484,15 +3578,15 @@
status_t AudioPolicyManager::listAudioPorts(audio_port_role_t role,
audio_port_type_t type,
unsigned int *num_ports,
- struct audio_port *ports,
+ struct audio_port_v7 *ports,
unsigned int *generation)
{
- if (num_ports == NULL || (*num_ports != 0 && ports == NULL) ||
- generation == NULL) {
+ if (num_ports == nullptr || (*num_ports != 0 && ports == nullptr) ||
+ generation == nullptr) {
return BAD_VALUE;
}
ALOGV("listAudioPorts() role %d type %d num_ports %d ports %p", role, type, *num_ports, ports);
- if (ports == NULL) {
+ if (ports == nullptr) {
*num_ports = 0;
}
@@ -3550,7 +3644,7 @@
return NO_ERROR;
}
-status_t AudioPolicyManager::getAudioPort(struct audio_port *port)
+status_t AudioPolicyManager::getAudioPort(struct audio_port_v7 *port)
{
if (port == nullptr || port->id == AUDIO_PORT_HANDLE_NONE) {
return BAD_VALUE;
@@ -3779,6 +3873,41 @@
sinkDevice->toAudioPortConfig(&sinkPortConfig, &patch->sinks[i]);
patchBuilder.addSink(sinkPortConfig);
+ // Whatever Sw or Hw bridge, we do attach an SwOutput to an Audio Source for
+ // volume management purpose (tracking activity)
+ // In case of Hw bridge, it is a Work Around. The mixPort used is the one declared
+ // in config XML to reach the sink so that is can be declared as available.
+ audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+ sp<SwAudioOutputDescriptor> outputDesc = nullptr;
+ if (sourceDesc != nullptr) {
+ // take care of dynamic routing for SwOutput selection,
+ audio_attributes_t attributes = sourceDesc->attributes();
+ audio_stream_type_t stream = sourceDesc->stream();
+ audio_attributes_t resultAttr;
+ audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+ config.sample_rate = sourceDesc->config().sample_rate;
+ config.channel_mask = sourceDesc->config().channel_mask;
+ config.format = sourceDesc->config().format;
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ bool isRequestedDeviceForExclusiveUse = false;
+ output_type_t outputType;
+ getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
+ &stream, sourceDesc->uid(), &config, &flags,
+ &selectedDeviceId, &isRequestedDeviceForExclusiveUse,
+ nullptr, &outputType);
+ if (output == AUDIO_IO_HANDLE_NONE) {
+ ALOGV("%s no output for device %s",
+ __FUNCTION__, sinkDevice->toString().c_str());
+ return INVALID_OPERATION;
+ }
+ outputDesc = mOutputs.valueFor(output);
+ if (outputDesc->isDuplicated()) {
+ ALOGE("%s output is duplicated", __func__);
+ return INVALID_OPERATION;
+ }
+ sourceDesc->setSwOutput(outputDesc);
+ }
// create a software bridge in PatchPanel if:
// - source and sink devices are on different HW modules OR
// - audio HAL version is < 3.0
@@ -3794,49 +3923,25 @@
if (patch->num_sinks > 1) {
return INVALID_OPERATION;
}
- audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- if (sourceDesc != nullptr) {
- // take care of dynamic routing for SwOutput selection,
- audio_attributes_t attributes = sourceDesc->attributes();
- audio_stream_type_t stream = sourceDesc->stream();
- audio_attributes_t resultAttr;
- audio_config_t config = AUDIO_CONFIG_INITIALIZER;
- config.sample_rate = sourceDesc->config().sample_rate;
- config.channel_mask = sourceDesc->config().channel_mask;
- config.format = sourceDesc->config().format;
- audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
- audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- bool isRequestedDeviceForExclusiveUse = false;
- output_type_t outputType;
- getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
- &stream, sourceDesc->uid(), &config, &flags,
- &selectedDeviceId, &isRequestedDeviceForExclusiveUse,
- nullptr, &outputType);
- if (output == AUDIO_IO_HANDLE_NONE) {
- ALOGV("%s no output for device %s",
- __FUNCTION__, sinkDevice->toString().c_str());
- return INVALID_OPERATION;
- }
- } else {
+ if (sourceDesc == nullptr) {
SortedVector<audio_io_handle_t> outputs =
getOutputsForDevices(DeviceVector(sinkDevice), mOutputs);
// if the sink device is reachable via an opened output stream, request to
// go via this output stream by adding a second source to the patch
// description
output = selectOutput(outputs);
- }
- if (output != AUDIO_IO_HANDLE_NONE) {
- sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
- if (outputDesc->isDuplicated()) {
- ALOGV("%s output for device %s is duplicated",
- __FUNCTION__, sinkDevice->toString().c_str());
- return INVALID_OPERATION;
+ if (output != AUDIO_IO_HANDLE_NONE) {
+ outputDesc = mOutputs.valueFor(output);
+ if (outputDesc->isDuplicated()) {
+ ALOGV("%s output for device %s is duplicated",
+ __FUNCTION__, sinkDevice->toString().c_str());
+ return INVALID_OPERATION;
+ }
}
+ }
+ if (outputDesc != nullptr) {
audio_port_config srcMixPortConfig = {};
outputDesc->toAudioPortConfig(&srcMixPortConfig, &patch->sources[0]);
- if (sourceDesc != nullptr) {
- sourceDesc->setSwOutput(outputDesc);
- }
// for volume control, we may need a valid stream
srcMixPortConfig.ext.mix.usecase.stream = sourceDesc != nullptr ?
sourceDesc->stream() : AUDIO_STREAM_PATCH;
@@ -3927,8 +4032,9 @@
sp<SwAudioOutputDescriptor> outputDesc =
mOutputs.getOutputFromId(patch->sources[1].id);
if (outputDesc == NULL) {
- ALOGE("%s output not found for id %d", __func__, patch->sources[0].id);
- return BAD_VALUE;
+ ALOGW("%s output not found for id %d", __func__, patch->sources[0].id);
+ // releaseOutput has already called closeOuput in case of direct output
+ return NO_ERROR;
}
if (patchDesc->getHandle() != outputDesc->getPatchHandle()) {
// force SwOutput patch removal as AF counter part patch has already gone.
@@ -4194,15 +4300,19 @@
disconnectAudioSource(sourceDesc);
audio_attributes_t attributes = sourceDesc->attributes();
- sp<DeviceDescriptor> srcDevice = sourceDesc->srcDevice();
-
+ // May the device (dynamic) have been disconnected/reconnected, id has changed.
+ sp<DeviceDescriptor> srcDevice = mAvailableInputDevices.getDevice(
+ sourceDesc->srcDevice()->type(),
+ String8(sourceDesc->srcDevice()->address().c_str()),
+ AUDIO_FORMAT_DEFAULT);
DeviceVector sinkDevices =
- mEngine->getOutputDevicesForAttributes(attributes, nullptr, true);
+ mEngine->getOutputDevicesForAttributes(attributes, nullptr, false /*fromCache*/);
ALOG_ASSERT(!sinkDevices.isEmpty(), "connectAudioSource(): no device found for attributes");
sp<DeviceDescriptor> sinkDevice = sinkDevices.itemAt(0);
- ALOG_ASSERT(mAvailableOutputDevices.contains(sinkDevice), "%s: Device %s not available",
- __FUNCTION__, sinkDevice->toString().c_str());
-
+ if (!mAvailableOutputDevices.contains(sinkDevice)) {
+ ALOGE("%s Device %s not available", __func__, sinkDevice->toString().c_str());
+ return INVALID_OPERATION;
+ }
PatchBuilder patchBuilder;
patchBuilder.addSink(sinkDevice).addSource(srcDevice);
audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
@@ -4212,7 +4322,7 @@
ALOGW("%s patch panel could not connect device patch, error %d", __func__, status);
return INVALID_OPERATION;
}
- sourceDesc->setPatchHandle(handle);
+ sourceDesc->connect(handle, sinkDevice);
// SW Bridge? (@todo: HW bridge, keep track of HwOutput for device selection "reconsideration")
sp<SwAudioOutputDescriptor> swOutput = sourceDesc->swOutput().promote();
if (swOutput != 0) {
@@ -4332,14 +4442,28 @@
// checkOutputsForDevice().
for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) {
sp<DeviceDescriptor> device = mAvailableOutputDevices[i];
- FormatVector supportedFormats =
- device->getAudioPort()->getAudioProfiles().getSupportedFormats();
- for (size_t j = 0; j < supportedFormats.size(); j++) {
- if (mConfig.getSurroundFormats().count(supportedFormats[j]) != 0) {
- formats.insert(supportedFormats[j]);
+ audio_devices_t deviceType = device->type();
+ // Enabling/disabling formats are applied to only HDMI devices. So, this function
+ // returns formats reported by HDMI devices.
+ if (deviceType != AUDIO_DEVICE_OUT_HDMI) {
+ continue;
+ }
+ // Formats reported by sink devices
+ std::unordered_set<audio_format_t> formatset;
+ if (auto it = mReportedFormatsMap.find(device); it != mReportedFormatsMap.end()) {
+ formatset.insert(it->second.begin(), it->second.end());
+ }
+
+ // Formats hard-coded in the in policy configuration file (if any).
+ FormatVector encodedFormats = device->encodedFormats();
+ formatset.insert(encodedFormats.begin(), encodedFormats.end());
+ // Filter the formats which are supported by the vendor hardware.
+ for (auto it = formatset.begin(); it != formatset.end(); ++it) {
+ if (mConfig.getSurroundFormats().count(*it) != 0) {
+ formats.insert(*it);
} else {
for (const auto& pair : mConfig.getSurroundFormats()) {
- if (pair.second.count(supportedFormats[j]) != 0) {
+ if (pair.second.count(*it) != 0) {
formats.insert(pair.first);
break;
}
@@ -4495,13 +4619,21 @@
status_t AudioPolicyManager::disconnectAudioSource(const sp<SourceClientDescriptor>& sourceDesc)
{
ALOGV("%s port Id %d", __FUNCTION__, sourceDesc->portId());
+ if (!sourceDesc->isConnected()) {
+ ALOGV("%s port Id %d already disconnected", __FUNCTION__, sourceDesc->portId());
+ return NO_ERROR;
+ }
sp<SwAudioOutputDescriptor> swOutput = sourceDesc->swOutput().promote();
if (swOutput != 0) {
status_t status = stopSource(swOutput, sourceDesc);
if (status == NO_ERROR) {
swOutput->stop();
}
- releaseOutput(sourceDesc->portId());
+ if (releaseOutput(sourceDesc->portId())) {
+ // The output descriptor is reopened to query dynamic profiles. In that case, there is
+ // no need to release audio patch here but just return NO_ERROR.
+ return NO_ERROR;
+ }
} else {
sp<HwAudioOutputDescriptor> hwOutputDesc = sourceDesc->hwOutput().promote();
if (hwOutputDesc != 0) {
@@ -4510,7 +4642,9 @@
ALOGW("%s source has neither SW nor HW output", __FUNCTION__);
}
}
- return releaseAudioPatchInternal(sourceDesc->getPatchHandle());
+ status_t status = releaseAudioPatchInternal(sourceDesc->getPatchHandle());
+ sourceDesc->disconnect();
+ return status;
}
sp<SourceClientDescriptor> AudioPolicyManager::getSourceForAttributesOnOutput(
@@ -4601,6 +4735,9 @@
return status;
}
+ mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
+ mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
+
// after parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices;
// open all output streams needed to access attached devices
onNewAudioModulesAvailableInt(nullptr /*newDevices*/);
@@ -4622,10 +4759,7 @@
}
}
- if (mPrimaryOutput == 0) {
- ALOGE("Failed to open primary output");
- status = NO_INIT;
- }
+ ALOGW_IF(mPrimaryOutput == nullptr, "The policy configuration does not declare a primary output");
// Silence ALOGV statements
property_set("log.tag." LOG_TAG, "D");
@@ -4735,7 +4869,7 @@
setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
}
}
- if (mPrimaryOutput == 0 &&
+ if (mPrimaryOutput == nullptr &&
outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
mPrimaryOutput = outputDesc;
}
@@ -4812,6 +4946,10 @@
void AudioPolicyManager::removeOutput(audio_io_handle_t output)
{
+ if (mPrimaryOutput != 0 && mPrimaryOutput == mOutputs.valueFor(output)) {
+ ALOGV("%s: removing primary output", __func__);
+ mPrimaryOutput = nullptr;
+ }
mOutputs.removeItem(output);
selectOutputForMusicEffects();
}
@@ -4905,82 +5043,8 @@
ALOGV("opening output for device %08x with params %s profile %p name %s",
deviceType, address.string(), profile.get(), profile->getName().c_str());
- desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
- audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- status = desc->open(nullptr, DeviceVector(device),
- AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
-
- if (status == NO_ERROR) {
- // Here is where the out_set_parameters() for card & device gets called
- if (!address.isEmpty()) {
- char *param = audio_device_address_to_parameter(deviceType, address);
- mpClientInterface->setParameters(output, String8(param));
- free(param);
- }
- updateAudioProfiles(device, output, profile->getAudioProfiles());
- if (!profile->hasValidAudioProfile()) {
- ALOGW("checkOutputsForDevice() missing param");
- desc->close();
- output = AUDIO_IO_HANDLE_NONE;
- } else if (profile->hasDynamicAudioProfile()) {
- desc->close();
- output = AUDIO_IO_HANDLE_NONE;
- audio_config_t config = AUDIO_CONFIG_INITIALIZER;
- profile->pickAudioProfile(
- config.sample_rate, config.channel_mask, config.format);
- config.offload_info.sample_rate = config.sample_rate;
- config.offload_info.channel_mask = config.channel_mask;
- config.offload_info.format = config.format;
-
- status = desc->open(&config, DeviceVector(device),
- AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
- if (status != NO_ERROR) {
- output = AUDIO_IO_HANDLE_NONE;
- }
- }
-
- if (output != AUDIO_IO_HANDLE_NONE) {
- addOutput(output, desc);
- if (audio_is_remote_submix_device(deviceType) && address != "0") {
- sp<AudioPolicyMix> policyMix;
- if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix)
- == NO_ERROR) {
- policyMix->setOutput(desc);
- desc->mPolicyMix = policyMix;
- } else {
- ALOGW("checkOutputsForDevice() cannot find policy for address %s",
- address.string());
- }
-
- } else if (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
- hasPrimaryOutput()) {
- // no duplicated output for direct outputs and
- // outputs used by dynamic policy mixes
- audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE;
-
- //TODO: configure audio effect output stage here
-
- // open a duplicating output thread for the new output and the primary output
- sp<SwAudioOutputDescriptor> dupOutputDesc =
- new SwAudioOutputDescriptor(NULL, mpClientInterface);
- status = dupOutputDesc->openDuplicating(mPrimaryOutput, desc,
- &duplicatedOutput);
- if (status == NO_ERROR) {
- // add duplicated output descriptor
- addOutput(duplicatedOutput, dupOutputDesc);
- } else {
- ALOGW("checkOutputsForDevice() could not open dup output for %d and %d",
- mPrimaryOutput->mIoHandle, output);
- desc->close();
- removeOutput(output);
- nextAudioPortGeneration();
- output = AUDIO_IO_HANDLE_NONE;
- }
- }
- }
- } else {
- output = AUDIO_IO_HANDLE_NONE;
- }
+ desc = openOutputWithProfileAndDevice(profile, DeviceVector(device));
+ audio_io_handle_t output = desc == nullptr ? AUDIO_IO_HANDLE_NONE : desc->mIoHandle;
if (output == AUDIO_IO_HANDLE_NONE) {
ALOGW("checkOutputsForDevice() could not open output for device %x", deviceType);
profiles.removeAt(profile_index);
@@ -4989,6 +5053,8 @@
outputs.add(output);
// Load digital format info only for digital devices
if (audio_device_is_digital(deviceType)) {
+ // TODO: when getAudioPort is ready, it may not be needed to import the audio
+ // port but just pick audio profile
device->importAudioPortAndPickAudioProfile(profile);
}
@@ -5013,7 +5079,7 @@
if (!desc->isDuplicated()) {
// exact match on device
if (device_distinguishes_on_address(deviceType) && desc->supportsDevice(device)
- && desc->devicesSupportEncodedFormats({deviceType})) {
+ && desc->containsSingleDeviceSupportingEncodedFormats(device)) {
outputs.add(mOutputs.keyAt(i));
} else if (!mAvailableOutputDevices.containsAtLeastOne(desc->supportedDevices())) {
ALOGV("checkOutputsForDevice(): disconnecting adding output %d",
@@ -5026,11 +5092,30 @@
for (const auto& hwModule : mHwModules) {
for (size_t j = 0; j < hwModule->getOutputProfiles().size(); j++) {
sp<IOProfile> profile = hwModule->getOutputProfiles()[j];
- if (profile->supportsDevice(device)) {
- ALOGV("checkOutputsForDevice(): "
- "clearing direct output profile %zu on module %s",
- j, hwModule->getName());
- profile->clearAudioProfiles();
+ if (!profile->supportsDevice(device)) {
+ continue;
+ }
+ ALOGV("checkOutputsForDevice(): "
+ "clearing direct output profile %zu on module %s",
+ j, hwModule->getName());
+ profile->clearAudioProfiles();
+ if (!profile->hasDynamicAudioProfile()) {
+ continue;
+ }
+ // When a device is disconnected, if there is an IOProfile that contains dynamic
+ // profiles and supports the disconnected device, call getAudioPort to repopulate
+ // the capabilities of the devices that is supported by the IOProfile.
+ for (const auto& supportedDevice : profile->getSupportedDevices()) {
+ if (supportedDevice == device ||
+ !mAvailableOutputDevices.contains(supportedDevice)) {
+ continue;
+ }
+ struct audio_port_v7 port;
+ supportedDevice->toAudioPort(&port);
+ status_t status = mpClientInterface->getAudioPort(&port);
+ if (status == NO_ERROR) {
+ supportedDevice->importAudioPort(port);
+ }
}
}
}
@@ -5302,6 +5387,8 @@
if (mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD) != 0) {
setMsdPatch();
}
+ // an event that changed routing likely occurred, inform upper layers
+ mpClientInterface->onRoutingUpdated();
}
bool AudioPolicyManager::followsSameRouting(const audio_attributes_t &lAttr,
@@ -5311,6 +5398,29 @@
mEngine->getProductStrategyForAttributes(rAttr);
}
+void AudioPolicyManager::checkAudioSourceForAttributes(const audio_attributes_t &attr)
+{
+ for (size_t i = 0; i < mAudioSources.size(); i++) {
+ sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
+ if (sourceDesc != nullptr && followsSameRouting(attr, sourceDesc->attributes())
+ && sourceDesc->getPatchHandle() == AUDIO_PATCH_HANDLE_NONE
+ && !isCallRxAudioSource(sourceDesc)) {
+ connectAudioSource(sourceDesc);
+ }
+ }
+}
+
+void AudioPolicyManager::clearAudioSourcesForOutput(audio_io_handle_t output)
+{
+ for (size_t i = 0; i < mAudioSources.size(); i++) {
+ sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
+ if (sourceDesc != nullptr && sourceDesc->swOutput().promote() != nullptr
+ && sourceDesc->swOutput().promote()->mIoHandle == output) {
+ disconnectAudioSource(sourceDesc);
+ }
+ }
+}
+
void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr)
{
auto psId = mEngine->getProductStrategyForAttributes(attr);
@@ -5407,7 +5517,7 @@
newDevices.types());
}
sp<SourceClientDescriptor> source = getSourceForAttributesOnOutput(srcOut, attr);
- if (source != 0){
+ if (source != nullptr && !isCallRxAudioSource(source)) {
connectAudioSource(source);
}
}
@@ -5430,6 +5540,7 @@
for (const auto &strategy : mEngine->getOrderedProductStrategies()) {
auto attributes = mEngine->getAllAttributesForProductStrategy(strategy).front();
checkOutputForAttributes(attributes);
+ checkAudioSourceForAttributes(attributes);
}
}
@@ -5465,6 +5576,17 @@
}
}
+bool AudioPolicyManager::isScoRequestedForComm() const {
+ AudioDeviceTypeAddrVector devices;
+ mEngine->getDevicesForRoleAndStrategy(mCommunnicationStrategy, DEVICE_ROLE_PREFERRED, devices);
+ for (const auto &device : devices) {
+ if (audio_is_bluetooth_out_sco_device(device.mType)) {
+ return true;
+ }
+ }
+ return false;
+}
+
void AudioPolicyManager::checkA2dpSuspend()
{
audio_io_handle_t a2dpOutput = mOutputs.getA2dpOutput();
@@ -5476,23 +5598,21 @@
bool isScoConnected =
(mAvailableInputDevices.types().count(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) != 0 ||
!Intersection(mAvailableOutputDevices.types(), getAudioDeviceOutAllScoSet()).empty());
+ bool isScoRequested = isScoRequestedForComm();
// if suspended, restore A2DP output if:
// ((SCO device is NOT connected) ||
- // ((forced usage communication is NOT SCO) && (forced usage for record is NOT SCO) &&
+ // ((SCO is not requested) &&
// (phone state is NOT in call) && (phone state is NOT ringing)))
//
// if not suspended, suspend A2DP output if:
// (SCO device is connected) &&
- // ((forced usage for communication is SCO) || (forced usage for record is SCO) ||
+ // ((SCO is requested) ||
// ((phone state is in call) || (phone state is ringing)))
//
if (mA2dpSuspended) {
if (!isScoConnected ||
- ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) !=
- AUDIO_POLICY_FORCE_BT_SCO) &&
- (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) !=
- AUDIO_POLICY_FORCE_BT_SCO) &&
+ (!isScoRequested &&
(mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) &&
(mEngine->getPhoneState() != AUDIO_MODE_RINGTONE))) {
@@ -5501,10 +5621,7 @@
}
} else {
if (isScoConnected &&
- ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) ==
- AUDIO_POLICY_FORCE_BT_SCO) ||
- (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) ==
- AUDIO_POLICY_FORCE_BT_SCO) ||
+ (isScoRequested ||
(mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) ||
(mEngine->getPhoneState() == AUDIO_MODE_RINGTONE))) {
@@ -6216,15 +6333,14 @@
bool isVoiceVolSrc = callVolSrc == volumeSource;
bool isBtScoVolSrc = btScoVolSrc == volumeSource;
- audio_policy_forced_cfg_t forceUseForComm =
- mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION);
+ bool isScoRequested = isScoRequestedForComm();
// do not change in call volume if bluetooth is connected and vice versa
// if sco and call follow same curves, bypass forceUseForComm
if ((callVolSrc != btScoVolSrc) &&
- ((isVoiceVolSrc && forceUseForComm == AUDIO_POLICY_FORCE_BT_SCO) ||
- (isBtScoVolSrc && forceUseForComm != AUDIO_POLICY_FORCE_BT_SCO))) {
- ALOGV("%s cannot set volume group %d volume with force use = %d for comm", __func__,
- volumeSource, forceUseForComm);
+ ((isVoiceVolSrc && isScoRequested) ||
+ (isBtScoVolSrc && !isScoRequested))) {
+ ALOGV("%s cannot set volume group %d volume when is%srequested for comm", __func__,
+ volumeSource, isScoRequested ? " " : "n ot ");
// Do not return an error here as AudioService will always set both voice call
// and bluetooth SCO volumes due to stream aliasing.
return NO_ERROR;
@@ -6396,9 +6512,10 @@
{
for (ssize_t i = (ssize_t)mAudioSources.size() - 1; i >= 0; i--) {
sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
- if (sourceDesc->srcDevice()->equals(deviceDesc)) {
- ALOGV("%s releasing audio source %d", __FUNCTION__, sourceDesc->portId());
- stopAudioSource(sourceDesc->portId());
+ if (sourceDesc->isConnected() && (sourceDesc->srcDevice()->equals(deviceDesc) ||
+ sourceDesc->sinkDevice()->equals(deviceDesc))
+ && !isCallRxAudioSource(sourceDesc)) {
+ disconnectAudioSource(sourceDesc);
}
}
@@ -6412,10 +6529,14 @@
release = true;
}
}
+ const char *address = deviceDesc->address().c_str();
for (size_t j = 0; j < patchDesc->mPatch.num_sinks && !release; j++) {
const struct audio_port_config *sink = &patchDesc->mPatch.sinks[j];
if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
- sink->ext.device.type == deviceDesc->type()) {
+ sink->ext.device.type == deviceDesc->type() &&
+ (strnlen(address, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0
+ || strncmp(sink->ext.device.address, address,
+ AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
release = true;
}
}
@@ -6538,6 +6659,7 @@
return;
}
FormatVector formats = formatsFromString(reply.string());
+ mReportedFormatsMap[devDesc] = formats;
if (device == AUDIO_DEVICE_OUT_HDMI
|| isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD)) {
modifySurroundFormats(devDesc, &formats);
@@ -6637,4 +6759,129 @@
return status;
}
+bool AudioPolicyManager::areAllActiveTracksRerouted(const sp<SwAudioOutputDescriptor>& output)
+{
+ const TrackClientVector activeClients = output->getActiveClients();
+ if (activeClients.empty()) {
+ return true;
+ }
+ ssize_t index = mAudioPatches.indexOfKey(output->getPatchHandle());
+ if (index < 0) {
+ ALOGE("%s, no audio patch found while there are active clients on output %d",
+ __func__, output->getId());
+ return false;
+ }
+ sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
+ DeviceVector routedDevices;
+ for (int i = 0; i < patchDesc->mPatch.num_sinks; ++i) {
+ sp<DeviceDescriptor> device = mAvailableOutputDevices.getDeviceFromId(
+ patchDesc->mPatch.sinks[i].id);
+ if (device == nullptr) {
+ ALOGE("%s, no audio device found with id(%d)",
+ __func__, patchDesc->mPatch.sinks[i].id);
+ return false;
+ }
+ routedDevices.add(device);
+ }
+ for (const auto& client : activeClients) {
+ // TODO: b/175343099 only travel the valid client
+ sp<DeviceDescriptor> preferredDevice =
+ mAvailableOutputDevices.getDeviceFromId(client->preferredDeviceId());
+ if (mEngine->getOutputDevicesForAttributes(
+ client->attributes(), preferredDevice, false) == routedDevices) {
+ return false;
+ }
+ }
+ return true;
+}
+
+sp<SwAudioOutputDescriptor> AudioPolicyManager::openOutputWithProfileAndDevice(
+ const sp<IOProfile>& profile, const DeviceVector& devices)
+{
+ for (const auto& device : devices) {
+ // TODO: This should be checking if the profile supports the device combo.
+ if (!profile->supportsDevice(device)) {
+ return nullptr;
+ }
+ }
+ sp<SwAudioOutputDescriptor> desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
+ audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+ status_t status = desc->open(nullptr, devices,
+ AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
+ if (status != NO_ERROR) {
+ return nullptr;
+ }
+
+ // Here is where the out_set_parameters() for card & device gets called
+ sp<DeviceDescriptor> device = devices.getDeviceForOpening();
+ const audio_devices_t deviceType = device->type();
+ const String8 &address = String8(device->address().c_str());
+ if (!address.isEmpty()) {
+ char *param = audio_device_address_to_parameter(deviceType, address.c_str());
+ mpClientInterface->setParameters(output, String8(param));
+ free(param);
+ }
+ updateAudioProfiles(device, output, profile->getAudioProfiles());
+ if (!profile->hasValidAudioProfile()) {
+ ALOGW("%s() missing param", __func__);
+ desc->close();
+ return nullptr;
+ } else if (profile->hasDynamicAudioProfile()) {
+ desc->close();
+ output = AUDIO_IO_HANDLE_NONE;
+ audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+ profile->pickAudioProfile(
+ config.sample_rate, config.channel_mask, config.format);
+ config.offload_info.sample_rate = config.sample_rate;
+ config.offload_info.channel_mask = config.channel_mask;
+ config.offload_info.format = config.format;
+
+ status = desc->open(&config, devices,
+ AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
+ if (status != NO_ERROR) {
+ return nullptr;
+ }
+ }
+
+ addOutput(output, desc);
+ if (audio_is_remote_submix_device(deviceType) && address != "0") {
+ sp<AudioPolicyMix> policyMix;
+ if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix) == NO_ERROR) {
+ policyMix->setOutput(desc);
+ desc->mPolicyMix = policyMix;
+ } else {
+ ALOGW("checkOutputsForDevice() cannot find policy for address %s",
+ address.string());
+ }
+
+ } else if (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) && hasPrimaryOutput()) {
+ // no duplicated output for direct outputs and
+ // outputs used by dynamic policy mixes
+ audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE;
+
+ //TODO: configure audio effect output stage here
+
+ // open a duplicating output thread for the new output and the primary output
+ sp<SwAudioOutputDescriptor> dupOutputDesc =
+ new SwAudioOutputDescriptor(nullptr, mpClientInterface);
+ status = dupOutputDesc->openDuplicating(mPrimaryOutput, desc, &duplicatedOutput);
+ if (status == NO_ERROR) {
+ // add duplicated output descriptor
+ addOutput(duplicatedOutput, dupOutputDesc);
+ } else {
+ ALOGW("checkOutputsForDevice() could not open dup output for %d and %d",
+ mPrimaryOutput->mIoHandle, output);
+ desc->close();
+ removeOutput(output);
+ nextAudioPortGeneration();
+ return nullptr;
+ }
+ }
+ if (mPrimaryOutput == nullptr && profile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
+ ALOGV("%s(): re-assigning mPrimaryOutput", __func__);
+ mPrimaryOutput = desc;
+ }
+ return desc;
+}
+
} // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 217013f..eba0c44 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -125,7 +125,7 @@
output_type_t *outputType) override;
virtual status_t startOutput(audio_port_handle_t portId);
virtual status_t stopOutput(audio_port_handle_t portId);
- virtual void releaseOutput(audio_port_handle_t portId);
+ virtual bool releaseOutput(audio_port_handle_t portId);
virtual status_t getInputForAttr(const audio_attributes_t *attr,
audio_io_handle_t *input,
audio_unique_id_t riid,
@@ -225,7 +225,7 @@
status_t dump(int fd) override;
status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t capturePolicy) override;
- virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo);
+ virtual audio_offload_mode_t getOffloadSupport(const audio_offload_info_t& offloadInfo);
virtual bool isDirectOutputSupported(const audio_config_base_t& config,
const audio_attributes_t& attributes);
@@ -233,9 +233,9 @@
virtual status_t listAudioPorts(audio_port_role_t role,
audio_port_type_t type,
unsigned int *num_ports,
- struct audio_port *ports,
+ struct audio_port_v7 *ports,
unsigned int *generation);
- virtual status_t getAudioPort(struct audio_port *port);
+ virtual status_t getAudioPort(struct audio_port_v7 *port);
virtual status_t createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
uid_t uid) {
@@ -556,6 +556,20 @@
*/
void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0);
+ bool isCallRxAudioSource(const sp<SourceClientDescriptor> &source) {
+ return mCallRxSourceClientPort != AUDIO_PORT_HANDLE_NONE
+ && source == mAudioSources.valueFor(mCallRxSourceClientPort);
+ }
+
+ void connectTelephonyRxAudioSource();
+
+ void disconnectTelephonyRxAudioSource();
+
+ /**
+ * @brief updates routing for all inputs.
+ */
+ void updateInputRouting();
+
/**
* @brief checkOutputForAttributes checks and if necessary changes outputs used for the
* given audio attributes.
@@ -566,6 +580,16 @@
*/
void checkOutputForAttributes(const audio_attributes_t &attr);
+ /**
+ * @brief checkAudioSourceForAttributes checks if any AudioSource following the same routing
+ * as the given audio attributes is not routed and try to connect it.
+ * It must be called once checkOutputForAttributes has been called for orphans AudioSource,
+ * aka AudioSource not attached to any Audio Output (e.g. AudioSource connected to direct
+ * Output which has been disconnected (and output closed) due to sink device unavailable).
+ * @param attr to be considered
+ */
+ void checkAudioSourceForAttributes(const audio_attributes_t &attr);
+
bool followsSameRouting(const audio_attributes_t &lAttr,
const audio_attributes_t &rAttr) const;
@@ -735,6 +759,7 @@
sp<SourceClientDescriptor> getSourceForAttributesOnOutput(audio_io_handle_t output,
const audio_attributes_t &attr);
+ void clearAudioSourcesForOutput(audio_io_handle_t output);
void cleanUpForDevice(const sp<DeviceDescriptor>& deviceDesc);
@@ -781,7 +806,6 @@
SoundTriggerSessionCollection mSoundTriggerSessions;
sp<AudioPatch> mCallTxPatch;
- sp<AudioPatch> mCallRxPatch;
HwAudioOutputCollection mHwOutputs;
SourceClientCollection mAudioSources;
@@ -813,6 +837,17 @@
std::unordered_set<audio_format_t> mManualSurroundFormats;
std::unordered_map<uid_t, audio_flags_mask_t> mAllowedCapturePolicies;
+
+ // The map of device descriptor and formats reported by the device.
+ std::map<wp<DeviceDescriptor>, FormatVector> mReportedFormatsMap;
+
+ // Cached product strategy ID corresponding to legacy strategy STRATEGY_PHONE
+ product_strategy_t mCommunnicationStrategy;
+
+ // The port handle of the hardware audio source created internally for the Call RX audio
+ // end point.
+ audio_port_handle_t mCallRxSourceClientPort = AUDIO_PORT_HANDLE_NONE;
+
private:
void onNewAudioModulesAvailableInt(DeviceVector *newDevices);
@@ -968,6 +1003,13 @@
std::function<bool(audio_devices_t)> predicate,
const char* context);
+ bool isScoRequestedForComm() const;
+
+ bool areAllActiveTracksRerouted(const sp<SwAudioOutputDescriptor>& output);
+
+ sp<SwAudioOutputDescriptor> openOutputWithProfileAndDevice(const sp<IOProfile>& profile,
+ const DeviceVector& devices);
+
};
};
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index e823efa..ceddb7e 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -31,6 +31,7 @@
"libutils",
"audioclient-types-aidl-unstable-cpp",
"audioflinger-aidl-unstable-cpp",
+ "audiopolicy-aidl-unstable-cpp",
"capture_state_listener-aidl-cpp",
],
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index dd128a2..77b5200 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -57,7 +57,7 @@
request.module = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_module_handle_t_int32_t(module));
request.config = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_config_t_AudioConfig(*config));
request.device = VALUE_OR_RETURN_STATUS(legacy2aidl_DeviceDescriptorBase(device));
- request.flags = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_output_flags_mask(flags));
+ request.flags = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
status_t status = af->openOutput(request, &response);
if (status == OK) {
@@ -134,7 +134,7 @@
request.config = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_config_t_AudioConfig(*config));
request.device = VALUE_OR_RETURN_STATUS(legacy2aidl_AudioDeviceTypeAddress(deviceTypeAddr));
request.source = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_source_t_AudioSourceType(source));
- request.flags = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_input_flags_mask(flags));
+ request.flags = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
media::OpenInputResponse response;
status_t status = af->openInput(request, &response);
@@ -266,6 +266,11 @@
mAudioPolicyService->onAudioVolumeGroupChanged(group, flags);
}
+void AudioPolicyService::AudioPolicyClient::onRoutingUpdated()
+{
+ mAudioPolicyService->onRoutingUpdated();
+}
+
audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId(audio_unique_id_use_t use)
{
return AudioSystem::newAudioUniqueId(use);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index df8e4c5..10bf707 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -454,8 +454,9 @@
}
// check calling permissions.
- // Capturing from FM_TUNER source is controlled by captureAudioOutputAllowed() only as this
- // does not affect users privacy as does capturing from an actual microphone.
+ // Capturing from FM_TUNER source is controlled by captureTunerAudioInputAllowed() and
+ // captureAudioOutputAllowed() (deprecated) as this does not affect users privacy
+ // as does capturing from an actual microphone.
if (!(recordingAllowed(opPackageName, pid, uid) || attr->source == AUDIO_SOURCE_FM_TUNER)) {
ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
__func__, uid, pid);
@@ -466,9 +467,14 @@
if ((inputSource == AUDIO_SOURCE_VOICE_UPLINK ||
inputSource == AUDIO_SOURCE_VOICE_DOWNLINK ||
inputSource == AUDIO_SOURCE_VOICE_CALL ||
- inputSource == AUDIO_SOURCE_ECHO_REFERENCE||
- inputSource == AUDIO_SOURCE_FM_TUNER) &&
- !canCaptureOutput) {
+ inputSource == AUDIO_SOURCE_ECHO_REFERENCE)
+ && !canCaptureOutput) {
+ return PERMISSION_DENIED;
+ }
+
+ if (inputSource == AUDIO_SOURCE_FM_TUNER
+ && !captureTunerAudioInputAllowed(pid, uid)
+ && !canCaptureOutput) {
return PERMISSION_DENIED;
}
@@ -547,7 +553,7 @@
}
std::string AudioPolicyService::getDeviceTypeStrForPortId(audio_port_handle_t portId) {
- struct audio_port port = {};
+ struct audio_port_v7 port = {};
port.id = portId;
status_t status = mAudioPolicyManager->getAudioPort(&port);
if (status == NO_ERROR && port.type == AUDIO_PORT_TYPE_DEVICE) {
@@ -573,7 +579,8 @@
}
// check calling permissions
- if (!(startRecording(client->opPackageName, client->pid, client->uid)
+ if (!(startRecording(client->opPackageName, client->pid, client->uid,
+ client->attributes.source)
|| client->attributes.source == AUDIO_SOURCE_FM_TUNER)) {
ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
__func__, client->uid, client->pid);
@@ -661,7 +668,8 @@
client->active = false;
client->startTimeNs = 0;
updateUidStates_l();
- finishRecording(client->opPackageName, client->uid);
+ finishRecording(client->opPackageName, client->uid,
+ client->attributes.source);
}
return status;
@@ -687,7 +695,8 @@
updateUidStates_l();
// finish the recording app op
- finishRecording(client->opPackageName, client->uid);
+ finishRecording(client->opPackageName, client->uid,
+ client->attributes.source);
AutoCallerClear acc;
return mAudioPolicyManager->stopInput(portId);
}
@@ -1086,15 +1095,15 @@
return mAudioPolicyManager->setAllowedCapturePolicy(uid, capturePolicy);
}
-bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info)
+audio_offload_mode_t AudioPolicyService::getOffloadSupport(const audio_offload_info_t& info)
{
if (mAudioPolicyManager == NULL) {
ALOGV("mAudioPolicyManager == NULL");
- return false;
+ return AUDIO_OFFLOAD_NOT_SUPPORTED;
}
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
- return mAudioPolicyManager->isOffloadSupported(info);
+ return mAudioPolicyManager->getOffloadSupport(info);
}
bool AudioPolicyService::isDirectOutputSupported(const audio_config_base_t& config,
@@ -1117,7 +1126,7 @@
status_t AudioPolicyService::listAudioPorts(audio_port_role_t role,
audio_port_type_t type,
unsigned int *num_ports,
- struct audio_port *ports,
+ struct audio_port_v7 *ports,
unsigned int *generation)
{
Mutex::Autolock _l(mLock);
@@ -1128,7 +1137,7 @@
return mAudioPolicyManager->listAudioPorts(role, type, num_ports, ports, generation);
}
-status_t AudioPolicyService::getAudioPort(struct audio_port *port)
+status_t AudioPolicyService::getAudioPort(struct audio_port_v7 *port)
{
Mutex::Autolock _l(mLock);
if (mAudioPolicyManager == NULL) {
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index a6e8989..a898dff 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -35,6 +35,7 @@
#include <utils/threads.h>
#include "AudioPolicyService.h"
#include <hardware_legacy/power.h>
+#include <media/AidlConversion.h>
#include <media/AudioEffect.h>
#include <media/AudioParameter.h>
#include <mediautils/ServiceUtilities.h>
@@ -111,7 +112,7 @@
// A notification client is always registered by AudioSystem when the client process
// connects to AudioPolicyService.
-void AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client)
+void AudioPolicyService::registerClient(const sp<media::IAudioPolicyServiceClient>& client)
{
if (client == 0) {
ALOGW("%s got NULL client", __FUNCTION__);
@@ -274,6 +275,19 @@
}
}
+void AudioPolicyService::onRoutingUpdated()
+{
+ mOutputCommandThread->routingChangedCommand();
+}
+
+void AudioPolicyService::doOnRoutingUpdated()
+{
+ Mutex::Autolock _l(mNotificationClientsLock);
+ for (size_t i = 0; i < mNotificationClients.size(); i++) {
+ mNotificationClients.valueAt(i)->onRoutingUpdated();
+ }
+}
+
status_t AudioPolicyService::clientCreateAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
int delayMs)
@@ -293,10 +307,11 @@
return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs);
}
-AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service,
- const sp<IAudioPolicyServiceClient>& client,
- uid_t uid,
- pid_t pid)
+AudioPolicyService::NotificationClient::NotificationClient(
+ const sp<AudioPolicyService>& service,
+ const sp<media::IAudioPolicyServiceClient>& client,
+ uid_t uid,
+ pid_t pid)
: mService(service), mUid(uid), mPid(pid), mAudioPolicyServiceClient(client),
mAudioPortCallbacksEnabled(false), mAudioVolumeGroupCallbacksEnabled(false)
{
@@ -342,7 +357,8 @@
const String8& regId, int32_t state)
{
if (mAudioPolicyServiceClient != 0 && isServiceUid(mUid)) {
- mAudioPolicyServiceClient->onDynamicPolicyMixStateUpdate(regId, state);
+ mAudioPolicyServiceClient->onDynamicPolicyMixStateUpdate(
+ legacy2aidl_String8_string(regId).value(), state);
}
}
@@ -357,8 +373,37 @@
audio_source_t source)
{
if (mAudioPolicyServiceClient != 0 && isServiceUid(mUid)) {
- mAudioPolicyServiceClient->onRecordingConfigurationUpdate(event, clientInfo,
- clientConfig, clientEffects, deviceConfig, effects, patchHandle, source);
+ status_t status = [&]() -> status_t {
+ int32_t eventAidl = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(event));
+ media::RecordClientInfo clientInfoAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_record_client_info_t_RecordClientInfo(*clientInfo));
+ media::AudioConfigBase clientConfigAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_config_base_t_AudioConfigBase(*clientConfig));
+ std::vector<media::EffectDescriptor> clientEffectsAidl = VALUE_OR_RETURN_STATUS(
+ convertContainer<std::vector<media::EffectDescriptor>>(
+ clientEffects,
+ legacy2aidl_effect_descriptor_t_EffectDescriptor));
+ media::AudioConfigBase deviceConfigAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_config_base_t_AudioConfigBase(*deviceConfig));
+ std::vector<media::EffectDescriptor> effectsAidl = VALUE_OR_RETURN_STATUS(
+ convertContainer<std::vector<media::EffectDescriptor>>(
+ effects,
+ legacy2aidl_effect_descriptor_t_EffectDescriptor));
+ int32_t patchHandleAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_patch_handle_t_int32_t(patchHandle));
+ media::AudioSourceType sourceAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_source_t_AudioSourceType(source));
+ return aidl_utils::statusTFromBinderStatus(
+ mAudioPolicyServiceClient->onRecordingConfigurationUpdate(eventAidl,
+ clientInfoAidl,
+ clientConfigAidl,
+ clientEffectsAidl,
+ deviceConfigAidl,
+ effectsAidl,
+ patchHandleAidl,
+ sourceAidl));
+ }();
+ ALOGW_IF(status != OK, "onRecordingConfigurationUpdate() failed: %d", status);
}
}
@@ -372,6 +417,13 @@
mAudioVolumeGroupCallbacksEnabled = enabled;
}
+void AudioPolicyService::NotificationClient::onRoutingUpdated()
+{
+ if (mAudioPolicyServiceClient != 0 && isServiceUid(mUid)) {
+ mAudioPolicyServiceClient->onRoutingUpdated();
+ }
+}
+
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
IPCThreadState::self()->getCallingPid());
@@ -453,7 +505,7 @@
sp<AudioRecordClient> topActive;
sp<AudioRecordClient> latestActive;
sp<AudioRecordClient> topSensitiveActive;
- sp<AudioRecordClient> latestSensitiveActive;
+ sp<AudioRecordClient> latestSensitiveActiveOrComm;
nsecs_t topStartNs = 0;
nsecs_t latestStartNs = 0;
@@ -467,6 +519,7 @@
bool rttCallActive = (isInCall || isInCommunication)
&& mUidPolicy->isRttEnabled();
bool onlyHotwordActive = true;
+ bool isPhoneStateOwnerActive = false;
// if Sensor Privacy is enabled then all recordings should be silenced.
if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -494,6 +547,7 @@
bool isAssistant = mUidPolicy->isAssistantUid(current->uid);
bool isPrivacySensitive =
(current->attributes.flags & AUDIO_FLAG_CAPTURE_PRIVATE) != 0;
+
if (appState == APP_STATE_TOP) {
if (isPrivacySensitive) {
if (current->startTimeNs > topSensitiveStartNs) {
@@ -515,9 +569,15 @@
if (!(current->attributes.source == AUDIO_SOURCE_HOTWORD
|| ((isA11yOnTop || rttCallActive) && isAssistant))) {
if (isPrivacySensitive) {
- if (current->startTimeNs > latestSensitiveStartNs) {
- latestSensitiveActive = current;
- latestSensitiveStartNs = current->startTimeNs;
+ // if audio mode is IN_COMMUNICATION, make sure the audio mode owner
+ // is marked latest sensitive active even if another app qualifies.
+ if (current->startTimeNs > latestSensitiveStartNs
+ || (isInCommunication && current->uid == mPhoneStateOwnerUid)) {
+ if (!isInCommunication || latestSensitiveActiveOrComm == nullptr
+ || latestSensitiveActiveOrComm->uid != mPhoneStateOwnerUid) {
+ latestSensitiveActiveOrComm = current;
+ latestSensitiveStartNs = current->startTimeNs;
+ }
}
isSensitiveActive = true;
} else {
@@ -531,6 +591,9 @@
if (current->attributes.source != AUDIO_SOURCE_HOTWORD) {
onlyHotwordActive = false;
}
+ if (current->uid == mPhoneStateOwnerUid) {
+ isPhoneStateOwnerActive = true;
+ }
}
// if no active client with UI on Top, consider latest active as top
@@ -539,8 +602,15 @@
topStartNs = latestStartNs;
}
if (topSensitiveActive == nullptr) {
- topSensitiveActive = latestSensitiveActive;
+ topSensitiveActive = latestSensitiveActiveOrComm;
topSensitiveStartNs = latestSensitiveStartNs;
+ } else if (latestSensitiveActiveOrComm != nullptr) {
+ // if audio mode is IN_COMMUNICATION, favor audio mode owner over an app with
+ // foreground UI in case both are capturing with privacy sensitive flag.
+ if (isInCommunication && latestSensitiveActiveOrComm->uid == mPhoneStateOwnerUid) {
+ topSensitiveActive = latestSensitiveActiveOrComm;
+ topSensitiveStartNs = latestSensitiveStartNs;
+ }
}
// If both privacy sensitive and regular capture are active:
@@ -566,13 +636,11 @@
auto canCaptureIfInCallOrCommunication = [&](const auto &recordClient) REQUIRES(mLock) {
bool canCaptureCall = recordClient->canCaptureOutput;
- return !(isInCall && !canCaptureCall);
-//TODO(b/160260850): restore restriction to mode owner once fix for misbehaving apps is merged
-// bool canCaptureCommunication = recordClient->canCaptureOutput
-// || recordClient->uid == mPhoneStateOwnerUid
-// || isServiceUid(mPhoneStateOwnerUid);
-// return !(isInCall && !canCaptureCall)
-// && !(isInCommunication && !canCaptureCommunication);
+ bool canCaptureCommunication = recordClient->canCaptureOutput
+ || !isPhoneStateOwnerActive
+ || recordClient->uid == mPhoneStateOwnerUid;
+ return !(isInCall && !canCaptureCall)
+ && !(isInCommunication && !canCaptureCommunication);
};
// By default allow capture if:
@@ -1366,6 +1434,16 @@
svc->doOnNewAudioModulesAvailable();
mLock.lock();
} break;
+ case ROUTING_UPDATED: {
+ ALOGV("AudioCommandThread() processing routing update");
+ svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->doOnRoutingUpdated();
+ mLock.lock();
+ } break;
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
@@ -1662,6 +1740,14 @@
sendCommand(command);
}
+void AudioPolicyService::AudioCommandThread::routingChangedCommand()
+{
+ sp<AudioCommand>command = new AudioCommand();
+ command->mCommand = ROUTING_UPDATED;
+ ALOGV("AudioCommandThread() adding routing update");
+ sendCommand(command);
+}
+
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{
@@ -1825,6 +1911,10 @@
} break;
+ case ROUTING_UPDATED: {
+
+ } break;
+
default:
break;
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 70a0e3a..db84d54 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -192,16 +192,16 @@
virtual status_t setVoiceVolume(float volume, int delayMs = 0);
status_t setSupportedSystemUsages(const std::vector<audio_usage_t>& systemUsages);
status_t setAllowedCapturePolicy(uint_t uid, audio_flags_mask_t capturePolicy) override;
- virtual bool isOffloadSupported(const audio_offload_info_t &config);
+ virtual audio_offload_mode_t getOffloadSupport(const audio_offload_info_t &config);
virtual bool isDirectOutputSupported(const audio_config_base_t& config,
const audio_attributes_t& attributes);
virtual status_t listAudioPorts(audio_port_role_t role,
audio_port_type_t type,
unsigned int *num_ports,
- struct audio_port *ports,
+ struct audio_port_v7 *ports,
unsigned int *generation);
- virtual status_t getAudioPort(struct audio_port *port);
+ virtual status_t getAudioPort(struct audio_port_v7 *port);
virtual status_t createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle);
virtual status_t releaseAudioPatch(audio_patch_handle_t handle);
@@ -210,7 +210,7 @@
unsigned int *generation);
virtual status_t setAudioPortConfig(const struct audio_port_config *config);
- virtual void registerClient(const sp<IAudioPolicyServiceClient>& client);
+ virtual void registerClient(const sp<media::IAudioPolicyServiceClient>& client);
virtual void setAudioPortCallbacksEnabled(bool enabled);
@@ -345,6 +345,10 @@
void onAudioVolumeGroupChanged(volume_group_t group, int flags);
void doOnAudioVolumeGroupChanged(volume_group_t group, int flags);
+
+ void onRoutingUpdated();
+ void doOnRoutingUpdated();
+
void setEffectSuspended(int effectId,
audio_session_t sessionId,
bool suspended);
@@ -497,6 +501,7 @@
RECORDING_CONFIGURATION_UPDATE,
SET_EFFECT_SUSPENDED,
AUDIO_MODULES_UPDATE,
+ ROUTING_UPDATED,
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -543,6 +548,7 @@
audio_session_t sessionId,
bool suspended);
void audioModulesUpdateCommand();
+ void routingChangedCommand();
void insertCommand_l(AudioCommand *command, int delayMs = 0);
private:
class AudioCommandData;
@@ -761,6 +767,8 @@
virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags);
+ virtual void onRoutingUpdated();
+
virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
void setSoundTriggerCaptureState(bool active) override;
@@ -775,7 +783,7 @@
class NotificationClient : public IBinder::DeathRecipient {
public:
NotificationClient(const sp<AudioPolicyService>& service,
- const sp<IAudioPolicyServiceClient>& client,
+ const sp<media::IAudioPolicyServiceClient>& client,
uid_t uid, pid_t pid);
virtual ~NotificationClient();
@@ -793,6 +801,7 @@
std::vector<effect_descriptor_t> effects,
audio_patch_handle_t patchHandle,
audio_source_t source);
+ void onRoutingUpdated();
void setAudioPortCallbacksEnabled(bool enabled);
void setAudioVolumeGroupCallbacksEnabled(bool enabled);
@@ -807,12 +816,12 @@
NotificationClient(const NotificationClient&);
NotificationClient& operator = (const NotificationClient&);
- const wp<AudioPolicyService> mService;
- const uid_t mUid;
- const pid_t mPid;
- const sp<IAudioPolicyServiceClient> mAudioPolicyServiceClient;
- bool mAudioPortCallbacksEnabled;
- bool mAudioVolumeGroupCallbacksEnabled;
+ const wp<AudioPolicyService> mService;
+ const uid_t mUid;
+ const pid_t mPid;
+ const sp<media::IAudioPolicyServiceClient> mAudioPolicyServiceClient;
+ bool mAudioPortCallbacksEnabled;
+ bool mAudioVolumeGroupCallbacksEnabled;
};
class AudioClient : public virtual RefBase {
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index bdddf06..e2d7d17 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -121,6 +121,19 @@
size_t getAudioPortListUpdateCount() const { return mAudioPortListUpdateCount; }
+ virtual void addSupportedFormat(audio_format_t /* format */) {}
+
+ void onRoutingUpdated() override {
+ mRoutingUpdatedUpdateCount++;
+ }
+
+ void resetRoutingUpdatedCounter() {
+ mRoutingUpdatedUpdateCount = 0;
+ }
+
+ size_t getRoutingUpdatedCounter() const {
+ return mRoutingUpdatedUpdateCount; }
+
private:
audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
@@ -128,6 +141,7 @@
std::map<audio_patch_handle_t, struct audio_patch> mActivePatches;
std::set<std::string> mAllowedModuleNames;
size_t mAudioPortListUpdateCount = 0;
+ size_t mRoutingUpdatedUpdateCount = 0;
};
} // namespace android
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClientForHdmi.h b/services/audiopolicy/tests/AudioPolicyManagerTestClientForHdmi.h
new file mode 100644
index 0000000..a5ad9b1
--- /dev/null
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClientForHdmi.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#include <map>
+#include <set>
+
+#include <system/audio.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include "AudioPolicyTestClient.h"
+
+namespace android {
+
+class AudioPolicyManagerTestClientForHdmi : public AudioPolicyManagerTestClient {
+public:
+ String8 getParameters(audio_io_handle_t /* ioHandle */, const String8& /* keys*/ ) override {
+ return mAudioParameters.toString();
+ }
+
+ void addSupportedFormat(audio_format_t format) override {
+ mAudioParameters.add(
+ String8(AudioParameter::keyStreamSupportedFormats),
+ String8(audio_format_to_string(format)));
+ mAudioParameters.addInt(String8(AudioParameter::keyStreamSupportedSamplingRates), 48000);
+ mAudioParameters.add(String8(AudioParameter::keyStreamSupportedChannels), String8(""));
+ }
+
+private:
+ AudioParameter mAudioParameters;
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index fa6b90f..d289e15 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -83,6 +83,7 @@
std::vector<effect_descriptor_t> effects __unused,
audio_patch_handle_t patchHandle __unused,
audio_source_t source __unused) override { }
+ void onRoutingUpdated() override { }
void setEffectSuspended(int effectId __unused,
audio_session_t sessionId __unused,
bool suspended __unused) {}
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index 8bab020..be860e5 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -29,6 +29,7 @@
using AudioPolicyManager::getOutputs;
using AudioPolicyManager::getAvailableOutputDevices;
using AudioPolicyManager::getAvailableInputDevices;
+ using AudioPolicyManager::setSurroundFormatEnabled;
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 9a62e72..ca2f0c6 100644
--- a/services/audiopolicy/tests/audio_health_tests.cpp
+++ b/services/audiopolicy/tests/audio_health_tests.cpp
@@ -34,7 +34,7 @@
unsigned int numPorts;
unsigned int generation1;
unsigned int generation;
- struct audio_port *audioPorts = NULL;
+ struct audio_port_v7 *audioPorts = nullptr;
int attempts = 10;
do {
if (attempts-- < 0) {
@@ -43,13 +43,14 @@
}
numPorts = 0;
ASSERT_EQ(NO_ERROR, AudioSystem::listAudioPorts(
- AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_DEVICE, &numPorts, NULL, &generation1));
+ AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_DEVICE, &numPorts, nullptr, &generation1));
if (numPorts == 0) {
free(audioPorts);
GTEST_FAIL() << "Number of audio ports should not be zero";
}
- audioPorts = (struct audio_port *)realloc(audioPorts, numPorts * sizeof(struct audio_port));
+ audioPorts = (struct audio_port_v7 *)realloc(
+ audioPorts, numPorts * sizeof(struct audio_port_v7));
status_t status = AudioSystem::listAudioPorts(
AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_DEVICE, &numPorts, audioPorts, &generation);
if (status != NO_ERROR) {
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 7972dbf..3032589 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -33,6 +33,7 @@
#include "AudioPolicyInterface.h"
#include "AudioPolicyManagerTestClient.h"
+#include "AudioPolicyManagerTestClientForHdmi.h"
#include "AudioPolicyTestClient.h"
#include "AudioPolicyTestManager.h"
@@ -137,15 +138,16 @@
// Tries to find a device port. If 'foundPort' isn't nullptr,
// will generate a failure if the port hasn't been found.
bool findDevicePort(audio_port_role_t role, audio_devices_t deviceType,
- const std::string &address, audio_port *foundPort);
+ const std::string &address, audio_port_v7 *foundPort);
static audio_port_handle_t getDeviceIdFromPatch(const struct audio_patch* patch);
+ virtual AudioPolicyManagerTestClient* getClient() { return new AudioPolicyManagerTestClient; }
std::unique_ptr<AudioPolicyManagerTestClient> mClient;
std::unique_ptr<AudioPolicyTestManager> mManager;
};
void AudioPolicyManagerTest::SetUp() {
- mClient.reset(new AudioPolicyManagerTestClient);
+ mClient.reset(getClient());
mManager.reset(new AudioPolicyTestManager(mClient.get()));
SetUpManagerConfig(); // Subclasses may want to customize the config.
ASSERT_EQ(NO_ERROR, mManager->initialize());
@@ -244,7 +246,7 @@
}
bool AudioPolicyManagerTest::findDevicePort(audio_port_role_t role,
- audio_devices_t deviceType, const std::string &address, audio_port *foundPort) {
+ audio_devices_t deviceType, const std::string &address, audio_port_v7 *foundPort) {
uint32_t numPorts = 0;
uint32_t generation1;
status_t ret;
@@ -254,7 +256,7 @@
if (HasFailure()) return false;
uint32_t generation2;
- struct audio_port ports[numPorts];
+ struct audio_port_v7 ports[numPorts];
ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, ports, &generation2);
EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
EXPECT_EQ(generation1, generation2) << "Generations changed during ports retrieval";
@@ -354,6 +356,7 @@
sp<DeviceDescriptor> mMsdOutputDevice;
sp<DeviceDescriptor> mMsdInputDevice;
+ sp<DeviceDescriptor> mDefaultOutputDevice;
};
void AudioPolicyManagerTestMsd::SetUpManagerConfig() {
@@ -408,17 +411,21 @@
primaryEncodedOutputProfile->addSupportedDevice(config.getDefaultOutputDevice());
config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
addOutputProfile(primaryEncodedOutputProfile);
+
+ mDefaultOutputDevice = config.getDefaultOutputDevice();
}
void AudioPolicyManagerTestMsd::TearDown() {
mMsdOutputDevice.clear();
mMsdInputDevice.clear();
+ mDefaultOutputDevice.clear();
AudioPolicyManagerTest::TearDown();
}
TEST_F(AudioPolicyManagerTestMsd, InitSuccess) {
ASSERT_TRUE(mMsdOutputDevice);
ASSERT_TRUE(mMsdInputDevice);
+ ASSERT_TRUE(mDefaultOutputDevice);
}
TEST_F(AudioPolicyManagerTestMsd, Dump) {
@@ -437,7 +444,7 @@
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
- ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+ ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(1, patchCount.deltaFromSnapshot());
}
@@ -446,7 +453,7 @@
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
- ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+ ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(1, patchCount.deltaFromSnapshot());
}
@@ -455,11 +462,11 @@
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
- ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+ ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(1, patchCount.deltaFromSnapshot());
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
- ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+ ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(1, patchCount.deltaFromSnapshot());
}
@@ -481,7 +488,7 @@
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
nullptr /*output*/, &portId);
- ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+ ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(1, patchCount.deltaFromSnapshot());
mManager->releaseOutput(portId);
ASSERT_EQ(1, patchCount.deltaFromSnapshot());
@@ -503,7 +510,7 @@
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
- ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+ ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(0, patchCount.deltaFromSnapshot());
}
}
@@ -668,6 +675,165 @@
ASSERT_EQ(INVALID_OPERATION, ret);
}
+class AudioPolicyManagerTestForHdmi
+ : public AudioPolicyManagerTestWithConfigurationFile {
+protected:
+ void SetUp() override;
+ std::string getConfigFile() override { return sTvConfig; }
+ std::map<audio_format_t, bool> getSurroundFormatsHelper(bool reported);
+ std::unordered_set<audio_format_t> getFormatsFromPorts();
+ AudioPolicyManagerTestClient* getClient() override {
+ return new AudioPolicyManagerTestClientForHdmi;
+ }
+ void TearDown() override;
+
+ static const std::string sTvConfig;
+
+};
+
+const std::string AudioPolicyManagerTestForHdmi::sTvConfig =
+ AudioPolicyManagerTestForHdmi::sExecutableDir +
+ "test_settop_box_surround_configuration.xml";
+
+void AudioPolicyManagerTestForHdmi::SetUp() {
+ AudioPolicyManagerTest::SetUp();
+ mClient->addSupportedFormat(AUDIO_FORMAT_E_AC3);
+ mManager->setDeviceConnectionState(
+ AUDIO_DEVICE_OUT_HDMI, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ "" /*address*/, "" /*name*/, AUDIO_FORMAT_DEFAULT);
+}
+
+void AudioPolicyManagerTestForHdmi::TearDown() {
+ mManager->setDeviceConnectionState(
+ AUDIO_DEVICE_OUT_HDMI, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ "" /*address*/, "" /*name*/, AUDIO_FORMAT_DEFAULT);
+ AudioPolicyManagerTest::TearDown();
+}
+
+std::map<audio_format_t, bool>
+ AudioPolicyManagerTestForHdmi::getSurroundFormatsHelper(bool reported) {
+ unsigned int numSurroundFormats = 0;
+ std::map<audio_format_t, bool> surroundFormatsMap;
+ status_t ret = mManager->getSurroundFormats(
+ &numSurroundFormats, nullptr /* surroundFormats */,
+ nullptr /* surroundFormatsEnabled */, reported);
+ EXPECT_EQ(NO_ERROR, ret);
+ if (ret != NO_ERROR) {
+ return surroundFormatsMap;
+ }
+ audio_format_t surroundFormats[numSurroundFormats];
+ memset(surroundFormats, 0, sizeof(audio_format_t) * numSurroundFormats);
+ bool surroundFormatsEnabled[numSurroundFormats];
+ memset(surroundFormatsEnabled, 0, sizeof(bool) * numSurroundFormats);
+ ret = mManager->getSurroundFormats(
+ &numSurroundFormats, surroundFormats, surroundFormatsEnabled, reported);
+ EXPECT_EQ(NO_ERROR, ret);
+ if (ret != NO_ERROR) {
+ return surroundFormatsMap;
+ }
+ for (int i = 0; i< numSurroundFormats; i++) {
+ surroundFormatsMap[surroundFormats[i]] = surroundFormatsEnabled[i];
+ }
+ return surroundFormatsMap;
+}
+
+std::unordered_set<audio_format_t>
+ AudioPolicyManagerTestForHdmi::getFormatsFromPorts() {
+ uint32_t numPorts = 0;
+ uint32_t generation1;
+ status_t ret;
+ std::unordered_set<audio_format_t> formats;
+ ret = mManager->listAudioPorts(
+ AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE, &numPorts, nullptr, &generation1);
+ EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
+ if (ret != NO_ERROR) {
+ return formats;
+ }
+ struct audio_port_v7 ports[numPorts];
+ ret = mManager->listAudioPorts(
+ AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE, &numPorts, ports, &generation1);
+ EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
+ if (ret != NO_ERROR) {
+ return formats;
+ }
+ for (const auto &port : ports) {
+ for (size_t i = 0; i < port.num_audio_profiles; ++i) {
+ formats.insert(port.audio_profiles[i].format);
+ }
+ }
+ return formats;
+}
+
+TEST_F(AudioPolicyManagerTestForHdmi, GetSurroundFormatsReturnsSupportedFormats) {
+ mManager->setForceUse(
+ AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND, AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS);
+ auto surroundFormats = getSurroundFormatsHelper(false /*reported*/);
+ ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+}
+
+TEST_F(AudioPolicyManagerTestForHdmi,
+ GetSurroundFormatsReturnsManipulatedFormats) {
+ mManager->setForceUse(
+ AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND, AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL);
+
+ status_t ret =
+ mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, false /*enabled*/);
+ ASSERT_EQ(NO_ERROR, ret);
+ auto surroundFormats = getSurroundFormatsHelper(false /*reported*/);
+ ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+ ASSERT_FALSE(surroundFormats[AUDIO_FORMAT_E_AC3]);
+
+ ret = mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, true /*enabled*/);
+ ASSERT_EQ(NO_ERROR, ret);
+ surroundFormats = getSurroundFormatsHelper(false /*reported*/);
+ ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+ ASSERT_TRUE(surroundFormats[AUDIO_FORMAT_E_AC3]);
+
+ ret = mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, false /*enabled*/);
+ ASSERT_EQ(NO_ERROR, ret);
+ surroundFormats = getSurroundFormatsHelper(false /*reported*/);
+ ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+ ASSERT_FALSE(surroundFormats[AUDIO_FORMAT_E_AC3]);
+}
+
+TEST_F(AudioPolicyManagerTestForHdmi,
+ ListAudioPortsReturnManipulatedHdmiFormats) {
+ mManager->setForceUse(
+ AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND, AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL);
+
+ ASSERT_EQ(NO_ERROR, mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, false /*enabled*/));
+ auto formats = getFormatsFromPorts();
+ ASSERT_EQ(0, formats.count(AUDIO_FORMAT_E_AC3));
+
+ ASSERT_EQ(NO_ERROR, mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, true /*enabled*/));
+ formats = getFormatsFromPorts();
+ ASSERT_EQ(1, formats.count(AUDIO_FORMAT_E_AC3));
+}
+
+TEST_F(AudioPolicyManagerTestForHdmi,
+ GetReportedSurroundFormatsReturnsHdmiReportedFormats) {
+ mManager->setForceUse(
+ AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND, AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS);
+ auto surroundFormats = getSurroundFormatsHelper(true /*reported*/);
+ ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+}
+
+TEST_F(AudioPolicyManagerTestForHdmi,
+ GetReportedSurroundFormatsReturnsNonManipulatedHdmiReportedFormats) {
+ mManager->setForceUse(
+ AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND, AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL);
+
+ status_t ret = mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, false /*enabled*/);
+ ASSERT_EQ(NO_ERROR, ret);
+ auto surroundFormats = getSurroundFormatsHelper(true /*reported*/);
+ ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+
+ ret = mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, true /*enabled*/);
+ ASSERT_EQ(NO_ERROR, ret);
+ surroundFormats = getSurroundFormatsHelper(true /*reported*/);
+ ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+}
+
class AudioPolicyManagerTestDPNoRemoteSubmixModule : public AudioPolicyManagerTestDynamicPolicy {
protected:
std::string getConfigFile() override { return sPrimaryOnlyConfig; }
@@ -714,7 +880,7 @@
{AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT, RULE_MATCH_ATTRIBUTE_USAGE}
};
- struct audio_port mInjectionPort;
+ struct audio_port_v7 mInjectionPort;
audio_port_handle_t mPortId = AUDIO_PORT_HANDLE_NONE;
};
@@ -731,7 +897,7 @@
AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig, mUsageRules);
ASSERT_EQ(NO_ERROR, ret);
- struct audio_port extractionPort;
+ struct audio_port_v7 extractionPort;
ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
mMixAddress, &extractionPort));
@@ -900,7 +1066,7 @@
{AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_VOICE_COMMUNICATION, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}
};
- struct audio_port mExtractionPort;
+ struct audio_port_v7 mExtractionPort;
audio_port_handle_t mPortId = AUDIO_PORT_HANDLE_NONE;
};
@@ -917,7 +1083,7 @@
AUDIO_DEVICE_IN_REMOTE_SUBMIX, mMixAddress, audioConfig, mSourceRules);
ASSERT_EQ(NO_ERROR, ret);
- struct audio_port injectionPort;
+ struct audio_port_v7 injectionPort;
ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
mMixAddress, &injectionPort));
@@ -1023,6 +1189,34 @@
dumpToLog();
}
+TEST_F(AudioPolicyManagerTestDeviceConnection, RoutingUpdate) {
+ mClient->resetRoutingUpdatedCounter();
+ // Connecting a valid output device with valid parameters should trigger a routing update
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ "a", "b", AUDIO_FORMAT_DEFAULT));
+ ASSERT_EQ(1, mClient->getRoutingUpdatedCounter());
+
+ // Disconnecting a connected device should succeed and trigger a routing update
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ "a", "b", AUDIO_FORMAT_DEFAULT));
+ ASSERT_EQ(2, mClient->getRoutingUpdatedCounter());
+
+ // Disconnecting a disconnected device should fail and not trigger a routing update
+ ASSERT_EQ(INVALID_OPERATION, mManager->setDeviceConnectionState(
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ "a", "b", AUDIO_FORMAT_DEFAULT));
+ ASSERT_EQ(2, mClient->getRoutingUpdatedCounter());
+
+ // Changing force use should trigger an update
+ auto config = mManager->getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA);
+ auto newConfig = config == AUDIO_POLICY_FORCE_BT_A2DP ?
+ AUDIO_POLICY_FORCE_NONE : AUDIO_POLICY_FORCE_BT_A2DP;
+ mManager->setForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA, newConfig);
+ ASSERT_EQ(3, mClient->getRoutingUpdatedCounter());
+}
+
TEST_P(AudioPolicyManagerTestDeviceConnection, SetDeviceConnectionState) {
const audio_devices_t type = std::get<0>(GetParam());
const std::string name = std::get<1>(GetParam());
@@ -1068,7 +1262,7 @@
type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
- audio_port devicePort;
+ audio_port_v7 devicePort;
const audio_port_role_t role = audio_is_output_device(type)
? AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
ASSERT_TRUE(findDevicePort(role, type, address, &devicePort));
@@ -1129,7 +1323,7 @@
flags, &output, &portId);
sp<SwAudioOutputDescriptor> outDesc = mManager->getOutputs().valueFor(output);
ASSERT_NE(nullptr, outDesc.get());
- audio_port port = {};
+ audio_port_v7 port = {};
outDesc->toAudioPort(&port);
mManager->releaseOutput(portId);
ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
@@ -1211,7 +1405,7 @@
findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", nullptr));
mClient->swapAllowedModuleNames({"primary", "r_submix"});
mManager->onNewAudioModulesAvailable();
- struct audio_port port;
+ struct audio_port_v7 port;
ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", &port));
}
diff --git a/services/audiopolicy/tests/resources/Android.bp b/services/audiopolicy/tests/resources/Android.bp
index 4f50dad..2f6e925 100644
--- a/services/audiopolicy/tests/resources/Android.bp
+++ b/services/audiopolicy/tests/resources/Android.bp
@@ -5,5 +5,6 @@
"test_audio_policy_primary_only_configuration.xml",
"test_invalid_audio_policy_configuration.xml",
"test_tv_apm_configuration.xml",
+ "test_settop_box_surround_configuration.xml",
],
}
diff --git a/services/audiopolicy/tests/resources/test_settop_box_surround_configuration.xml b/services/audiopolicy/tests/resources/test_settop_box_surround_configuration.xml
new file mode 100644
index 0000000..6f7375e
--- /dev/null
+++ b/services/audiopolicy/tests/resources/test_settop_box_surround_configuration.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ~ 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.
+ -->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <globalConfiguration speaker_drc_enabled="false"/>
+ <modules>
+ <module name="primary" halVersion="2.0">
+ <attachedDevices>
+ <item>Stub</item>
+ </attachedDevices>
+ <defaultOutputDevice>Stub</defaultOutputDevice>
+ <mixPorts>
+ <mixPort name="primary pcm" role="source"
+ flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="multichannel output" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT">
+ <profile name="" />
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="Stub" type="AUDIO_DEVICE_OUT_STUB" role="sink" />
+ <devicePort tagName="HDMI" type="AUDIO_DEVICE_OUT_HDMI" role="sink" />
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="Stub" sources="primary pcm"/>
+ <route type="mix" sink="HDMI" sources="primary pcm,multichannel output"/>
+ </routes>
+ </module>
+ </modules>
+</audioPolicyConfiguration>
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 8400dae..b4c0da3 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -21,6 +21,7 @@
#include <algorithm>
#include <climits>
#include <stdio.h>
+#include <cstdlib>
#include <cstring>
#include <ctime>
#include <string>
@@ -1694,6 +1695,8 @@
// Otherwise, add client to active clients list
finishConnectLocked(client, partial);
}
+
+ client->setImageDumpMask(mImageDumpMask);
} // lock is destroyed, allow further connect calls
// Important: release the mutex here so the client can call back into the service from its
@@ -3880,6 +3883,10 @@
return handleSetRotateAndCrop(args);
} else if (args.size() >= 1 && args[0] == String16("get-rotate-and-crop")) {
return handleGetRotateAndCrop(out);
+ } else if (args.size() >= 2 && args[0] == String16("set-image-dump-mask")) {
+ return handleSetImageDumpMask(args);
+ } else if (args.size() >= 1 && args[0] == String16("get-image-dump-mask")) {
+ return handleGetImageDumpMask(out);
} else if (args.size() == 1 && args[0] == String16("help")) {
printHelp(out);
return NO_ERROR;
@@ -3979,6 +3986,30 @@
return dprintf(out, "rotateAndCrop override: %d\n", mOverrideRotateAndCropMode);
}
+status_t CameraService::handleSetImageDumpMask(const Vector<String16>& args) {
+ char *endPtr;
+ errno = 0;
+ String8 maskString8 = String8(args[1]);
+ long maskValue = strtol(maskString8.c_str(), &endPtr, 10);
+
+ if (errno != 0) return BAD_VALUE;
+ if (endPtr != maskString8.c_str() + maskString8.size()) return BAD_VALUE;
+ if (maskValue < 0 || maskValue > 1) return BAD_VALUE;
+
+ Mutex::Autolock lock(mServiceLock);
+
+ mImageDumpMask = maskValue;
+
+ return OK;
+}
+
+status_t CameraService::handleGetImageDumpMask(int out) {
+ Mutex::Autolock lock(mServiceLock);
+
+ return dprintf(out, "Image dump mask: %d\n", mImageDumpMask);
+}
+
+
status_t CameraService::printHelp(int out) {
return dprintf(out, "Camera service commands:\n"
" get-uid-state <PACKAGE> [--user USER_ID] gets the uid state\n"
@@ -3987,6 +4018,9 @@
" set-rotate-and-crop <ROTATION> overrides the rotate-and-crop value for AUTO backcompat\n"
" Valid values 0=0 deg, 1=90 deg, 2=180 deg, 3=270 deg, 4=No override\n"
" get-rotate-and-crop returns the current override rotate-and-crop value\n"
+ " set-image-dump-mask <MASK> specifies the formats to be saved to disk\n"
+ " Valid values 0=OFF, 1=ON for JPEG\n"
+ " get-image-dump-mask returns the current image-dump-mask value\n"
" help print this message\n");
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d26c62d..43b03e6 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -398,6 +398,8 @@
// Check what API level is used for this client. This is used to determine which
// superclass this can be cast to.
virtual bool canCastToApiClient(apiLevel level) const;
+
+ void setImageDumpMask(int /*mask*/) { }
protected:
// Initialized in constructor
@@ -1036,6 +1038,12 @@
// Get the rotate-and-crop AUTO override behavior
status_t handleGetRotateAndCrop(int out);
+ // Set the mask for image dump to disk
+ status_t handleSetImageDumpMask(const Vector<String16>& args);
+
+ // Get the mask for image dump to disk
+ status_t handleGetImageDumpMask(int out);
+
// Prints the shell command help
status_t printHelp(int out);
@@ -1077,6 +1085,9 @@
// Current override rotate-and-crop mode
uint8_t mOverrideRotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_AUTO;
+
+ // Current image dump mask
+ uint8_t mImageDumpMask = 0;
};
} // namespace android
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 662b58f..2494302 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -76,7 +76,8 @@
bool Camera2Client::isZslEnabledInStillTemplate() {
bool zslEnabled = false;
CameraMetadata stillTemplate;
- status_t res = mDevice->createDefaultRequest(CAMERA2_TEMPLATE_STILL_CAPTURE, &stillTemplate);
+ status_t res = mDevice->createDefaultRequest(
+ camera_request_template_t::CAMERA_TEMPLATE_STILL_CAPTURE, &stillTemplate);
if (res == OK) {
camera_metadata_entry_t enableZsl = stillTemplate.find(ANDROID_CONTROL_ENABLE_ZSL);
if (enableZsl.count == 1) {
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index a71a732..744aaee 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -31,6 +31,8 @@
namespace android {
namespace camera2 {
+using android::camera3::CAMERA_STREAM_ROTATION_0;
+
CallbackProcessor::CallbackProcessor(sp<Camera2Client> client):
Thread(false),
mClient(client),
@@ -154,7 +156,7 @@
callbackFormat, params.previewFormat);
res = device->createStream(mCallbackWindow,
params.previewWidth, params.previewHeight, callbackFormat,
- HAL_DATASPACE_V0_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId,
+ HAL_DATASPACE_V0_JFIF, CAMERA_STREAM_ROTATION_0, &mCallbackStreamId,
String8());
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
index 0c01a91..4c9b7ed 100644
--- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
@@ -706,7 +706,7 @@
if (mCaptureRequest.entryCount() == 0) {
res = client->getCameraDevice()->createDefaultRequest(
- CAMERA2_TEMPLATE_STILL_CAPTURE,
+ camera_request_template_t::CAMERA_TEMPLATE_STILL_CAPTURE,
&mCaptureRequest);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create default still image request:"
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index ddfe5e3..ff2e398 100755
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -35,6 +35,8 @@
namespace android {
namespace camera2 {
+using android::camera3::CAMERA_STREAM_ROTATION_0;
+
JpegProcessor::JpegProcessor(
sp<Camera2Client> client,
wp<CaptureSequencer> sequencer):
@@ -148,7 +150,7 @@
res = device->createStream(mCaptureWindow,
params.pictureWidth, params.pictureHeight,
HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_V0_JFIF,
- CAMERA3_STREAM_ROTATION_0, &mCaptureStreamId,
+ CAMERA_STREAM_ROTATION_0, &mCaptureStreamId,
String8());
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for capture: "
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index d543cab..e062c14 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -37,6 +37,8 @@
namespace android {
namespace camera2 {
+using android::camera3::CAMERA_TEMPLATE_PREVIEW;
+
Parameters::Parameters(int cameraId,
int cameraFacing) :
cameraId(cameraId),
@@ -2468,7 +2470,7 @@
// Use focal length in preview template if it exists
CameraMetadata previewTemplate;
- status_t res = device->createDefaultRequest(CAMERA3_TEMPLATE_PREVIEW, &previewTemplate);
+ status_t res = device->createDefaultRequest(CAMERA_TEMPLATE_PREVIEW, &previewTemplate);
if (res != OK) {
ALOGE("%s: Failed to create default PREVIEW request: %s (%d)",
__FUNCTION__, strerror(-res), res);
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index 0786f53..8b1eb28 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -40,6 +40,10 @@
namespace android {
namespace camera2 {
+using android::camera3::CAMERA_STREAM_ROTATION_0;
+using android::camera3::CAMERA_TEMPLATE_PREVIEW;
+using android::camera3::CAMERA_TEMPLATE_ZERO_SHUTTER_LAG;
+
StreamingProcessor::StreamingProcessor(sp<Camera2Client> client):
mClient(client),
mDevice(client->getCameraDevice()),
@@ -113,12 +117,12 @@
return INVALID_OPERATION;
}
- // Use CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG for ZSL streaming case.
+ // Use CAMERA_TEMPLATE_ZERO_SHUTTER_LAG for ZSL streaming case.
if (params.useZeroShutterLag() && !params.recordingHint) {
res = device->createDefaultRequest(
- CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG, &mPreviewRequest);
+ CAMERA_TEMPLATE_ZERO_SHUTTER_LAG, &mPreviewRequest);
} else {
- res = device->createDefaultRequest(CAMERA3_TEMPLATE_PREVIEW,
+ res = device->createDefaultRequest(CAMERA_TEMPLATE_PREVIEW,
&mPreviewRequest);
}
@@ -194,7 +198,7 @@
res = device->createStream(mPreviewWindow,
params.previewWidth, params.previewHeight,
CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, HAL_DATASPACE_UNKNOWN,
- CAMERA3_STREAM_ROTATION_0, &mPreviewStreamId, String8());
+ CAMERA_STREAM_ROTATION_0, &mPreviewStreamId, String8());
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
@@ -263,7 +267,7 @@
}
if (mRecordingRequest.entryCount() == 0) {
- res = device->createDefaultRequest(CAMERA2_TEMPLATE_VIDEO_RECORD,
+ res = device->createDefaultRequest(camera_request_template_t::CAMERA_TEMPLATE_VIDEO_RECORD,
&mRecordingRequest);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create default recording request:"
@@ -379,7 +383,7 @@
res = device->createStream(mRecordingWindow,
params.videoWidth, params.videoHeight,
params.videoFormat, params.videoDataSpace,
- CAMERA3_STREAM_ROTATION_0, &mRecordingStreamId,
+ CAMERA_STREAM_ROTATION_0, &mRecordingStreamId,
String8());
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for recording: "
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 8753dcf..0701b6f 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -42,6 +42,9 @@
namespace android {
namespace camera2 {
+using android::camera3::CAMERA_STREAM_ROTATION_0;
+using android::camera3::CAMERA_TEMPLATE_STILL_CAPTURE;
+
namespace {
struct TimestampFinder : public RingBufferConsumer::RingBufferComparator {
typedef RingBufferConsumer::BufferInfo BufferInfo;
@@ -257,7 +260,7 @@
res = device->createStream(outSurface, params.fastInfo.maxZslSize.width,
params.fastInfo.maxZslSize.height, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
- HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mZslStreamId,
+ HAL_DATASPACE_UNKNOWN, CAMERA_STREAM_ROTATION_0, &mZslStreamId,
String8());
if (res != OK) {
ALOGE("%s: Camera %d: Can't create ZSL stream: "
@@ -348,7 +351,7 @@
}
CameraMetadata stillTemplate;
- device->createDefaultRequest(CAMERA3_TEMPLATE_STILL_CAPTURE, &stillTemplate);
+ device->createDefaultRequest(CAMERA_TEMPLATE_STILL_CAPTURE, &stillTemplate);
// Find some of the post-processing tags, and assign the value from template to the request.
// Only check the aberration mode and noise reduction mode for now, as they are very important
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 66eda5d..6e1aba9 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -51,6 +51,7 @@
namespace android {
using namespace camera2;
+using camera3::camera_stream_rotation_t::CAMERA_STREAM_ROTATION_0;
CameraDeviceClientBase::CameraDeviceClientBase(
const sp<CameraService>& cameraService,
@@ -170,7 +171,6 @@
const StreamSurfaceId& streamSurfaceId = mStreamMap.valueAt(idx);
if (outSurfaceMap->find(streamSurfaceId.streamId()) == outSurfaceMap->end()) {
- (*outSurfaceMap)[streamSurfaceId.streamId()] = std::vector<size_t>();
outputStreamIds->push_back(streamSurfaceId.streamId());
}
(*outSurfaceMap)[streamSurfaceId.streamId()].push_back(streamSurfaceId.surfaceId());
@@ -807,7 +807,7 @@
err = compositeStream->createStream(surfaces, deferredConsumer, streamInfo.width,
streamInfo.height, streamInfo.format,
- static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
+ static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
&streamId, physicalCameraId, &surfaceIds, outputConfiguration.getSurfaceSetID(),
isShared);
if (err == OK) {
@@ -817,7 +817,7 @@
} else {
err = mDevice->createStream(surfaces, deferredConsumer, streamInfo.width,
streamInfo.height, streamInfo.format, streamInfo.dataSpace,
- static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
+ static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
&streamId, physicalCameraId, &surfaceIds, outputConfiguration.getSurfaceSetID(),
isShared);
}
@@ -885,7 +885,7 @@
String8 physicalCameraId(outputConfiguration.getPhysicalCameraId());
err = mDevice->createStream(noSurface, /*hasDeferredConsumer*/true, width,
height, format, dataSpace,
- static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
+ static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
&streamId, physicalCameraId, &surfaceIds,
outputConfiguration.getSurfaceSetID(), isShared,
consumerUsage);
@@ -1152,9 +1152,12 @@
return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
}
- CameraMetadata metadata;
status_t err;
- if ( (err = mDevice->createDefaultRequest(templateId, &metadata) ) == OK &&
+ camera_request_template_t tempId = camera_request_template_t::CAMERA_TEMPLATE_COUNT;
+ if (!(res = mapRequestTemplate(templateId, &tempId)).isOk()) return res;
+
+ CameraMetadata metadata;
+ if ( (err = mDevice->createDefaultRequest(tempId, &metadata) ) == OK &&
request != NULL) {
request->swap(metadata);
@@ -1886,4 +1889,41 @@
return CameraUtils::getRotationTransform(staticInfo, transform);
}
+binder::Status CameraDeviceClient::mapRequestTemplate(int templateId,
+ camera_request_template_t* tempId /*out*/) {
+ binder::Status ret = binder::Status::ok();
+
+ if (tempId == nullptr) {
+ ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Camera %s: Invalid template argument", mCameraIdStr.string());
+ return ret;
+ }
+ switch(templateId) {
+ case ICameraDeviceUser::TEMPLATE_PREVIEW:
+ *tempId = camera_request_template_t::CAMERA_TEMPLATE_PREVIEW;
+ break;
+ case ICameraDeviceUser::TEMPLATE_RECORD:
+ *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_RECORD;
+ break;
+ case ICameraDeviceUser::TEMPLATE_STILL_CAPTURE:
+ *tempId = camera_request_template_t::CAMERA_TEMPLATE_STILL_CAPTURE;
+ break;
+ case ICameraDeviceUser::TEMPLATE_VIDEO_SNAPSHOT:
+ *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_SNAPSHOT;
+ break;
+ case ICameraDeviceUser::TEMPLATE_ZERO_SHUTTER_LAG:
+ *tempId = camera_request_template_t::CAMERA_TEMPLATE_ZERO_SHUTTER_LAG;
+ break;
+ case ICameraDeviceUser::TEMPLATE_MANUAL:
+ *tempId = camera_request_template_t::CAMERA_TEMPLATE_MANUAL;
+ break;
+ default:
+ ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Camera %s: Template ID %d is invalid or not supported",
+ mCameraIdStr.string(), templateId);
+ return ret;
+ }
+
+ return ret;
+}
} // namespace android
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 5d40b82..57688a0 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -206,6 +206,7 @@
virtual void notifyRequestQueueEmpty();
virtual void notifyRepeatingRequestError(long lastFrameNumber);
+ void setImageDumpMask(int mask) { if (mDevice != nullptr) mDevice->setImageDumpMask(mask); }
/**
* Interface used by independent components of CameraDeviceClient.
*/
@@ -275,6 +276,10 @@
/*out*/SurfaceMap* surfaceMap, /*out*/Vector<int32_t>* streamIds,
/*out*/int32_t* currentStreamId);
+ // Utility method that maps AIDL request templates.
+ binder::Status mapRequestTemplate(int templateId,
+ camera_request_template_t* tempId /*out*/);
+
// IGraphicsBufferProducer binder -> Stream ID + Surface ID for output streams
KeyedVector<sp<IBinder>, StreamSurfaceId> mStreamMap;
diff --git a/services/camera/libcameraservice/api2/CompositeStream.cpp b/services/camera/libcameraservice/api2/CompositeStream.cpp
index a61dac7..2f8ca6b 100644
--- a/services/camera/libcameraservice/api2/CompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/CompositeStream.cpp
@@ -46,7 +46,7 @@
status_t CompositeStream::createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
- camera3_stream_rotation_t rotation, int * id, const String8& physicalCameraId,
+ camera_stream_rotation_t rotation, int * id, const String8& physicalCameraId,
std::vector<int> * surfaceIds, int streamSetId, bool isShared) {
if (hasDeferredConsumer) {
ALOGE("%s: Deferred consumers not supported in case of composite streams!",
diff --git a/services/camera/libcameraservice/api2/CompositeStream.h b/services/camera/libcameraservice/api2/CompositeStream.h
index 5f62d47..2a934df 100644
--- a/services/camera/libcameraservice/api2/CompositeStream.h
+++ b/services/camera/libcameraservice/api2/CompositeStream.h
@@ -43,7 +43,7 @@
status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
- camera3_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+ camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
std::vector<int> *surfaceIds, int streamSetId, bool isShared);
status_t deleteStream();
@@ -54,7 +54,7 @@
// Create and register all internal camera streams.
virtual status_t createInternalStreams(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
- camera3_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+ camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
std::vector<int> *surfaceIds, int streamSetId, bool isShared) = 0;
// Release all internal streams and corresponding resources.
diff --git a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
index c6859be..2c553f3 100644
--- a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
@@ -341,7 +341,7 @@
return res;
}
- size_t finalJpegSize = actualJpegSize + sizeof(struct camera3_jpeg_blob);
+ size_t finalJpegSize = actualJpegSize + sizeof(struct camera_jpeg_blob);
if (finalJpegSize > finalJpegBufferSize) {
ALOGE("%s: Final jpeg buffer not large enough for the jpeg blob header", __FUNCTION__);
outputANW->cancelBuffer(mOutputSurface.get(), anb, /*fence*/ -1);
@@ -357,9 +357,9 @@
ALOGV("%s: Final jpeg size: %zu", __func__, finalJpegSize);
uint8_t* header = static_cast<uint8_t *> (dstBuffer) +
- (gb->getWidth() - sizeof(struct camera3_jpeg_blob));
- struct camera3_jpeg_blob *blob = reinterpret_cast<struct camera3_jpeg_blob*> (header);
- blob->jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
+ (gb->getWidth() - sizeof(struct camera_jpeg_blob));
+ struct camera_jpeg_blob *blob = reinterpret_cast<struct camera_jpeg_blob*> (header);
+ blob->jpeg_blob_id = CAMERA_JPEG_BLOB_ID;
blob->jpeg_size = actualJpegSize;
outputANW->queueBuffer(mOutputSurface.get(), anb, /*fence*/ -1);
@@ -486,7 +486,7 @@
status_t DepthCompositeStream::createInternalStreams(const std::vector<sp<Surface>>& consumers,
bool /*hasDeferredConsumer*/, uint32_t width, uint32_t height, int format,
- camera3_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+ camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
std::vector<int> *surfaceIds, int /*streamSetId*/, bool /*isShared*/) {
if (mSupportedDepthSizes.empty()) {
ALOGE("%s: This camera device doesn't support any depth map streams!", __FUNCTION__);
@@ -666,13 +666,11 @@
status_t DepthCompositeStream::insertGbp(SurfaceMap* /*out*/outSurfaceMap,
Vector<int32_t> * /*out*/outputStreamIds, int32_t* /*out*/currentStreamId) {
if (outSurfaceMap->find(mDepthStreamId) == outSurfaceMap->end()) {
- (*outSurfaceMap)[mDepthStreamId] = std::vector<size_t>();
outputStreamIds->push_back(mDepthStreamId);
}
(*outSurfaceMap)[mDepthStreamId].push_back(mDepthSurfaceId);
if (outSurfaceMap->find(mBlobStreamId) == outSurfaceMap->end()) {
- (*outSurfaceMap)[mBlobStreamId] = std::vector<size_t>();
outputStreamIds->push_back(mBlobStreamId);
}
(*outSurfaceMap)[mBlobStreamId].push_back(mBlobSurfaceId);
diff --git a/services/camera/libcameraservice/api2/DepthCompositeStream.h b/services/camera/libcameraservice/api2/DepthCompositeStream.h
index cab52b6..05bc504 100644
--- a/services/camera/libcameraservice/api2/DepthCompositeStream.h
+++ b/services/camera/libcameraservice/api2/DepthCompositeStream.h
@@ -50,7 +50,7 @@
// CompositeStream overrides
status_t createInternalStreams(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
- camera3_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+ camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
std::vector<int> *surfaceIds, int streamSetId, bool isShared) override;
status_t deleteInternalStreams() override;
status_t configureStream() override;
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index 4fe5adf..7d68485 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -65,7 +65,6 @@
mYuvBufferAcquired(false),
mProducerListener(new ProducerListener()),
mDequeuedOutputBufferCnt(0),
- mLockedAppSegmentBufferCnt(0),
mCodecOutputCounter(0),
mQuality(-1),
mGridTimestampUs(0),
@@ -115,7 +114,7 @@
status_t HeicCompositeStream::createInternalStreams(const std::vector<sp<Surface>>& consumers,
bool /*hasDeferredConsumer*/, uint32_t width, uint32_t height, int format,
- camera3_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+ camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
std::vector<int> *surfaceIds, int /*streamSetId*/, bool /*isShared*/) {
sp<CameraDeviceBase> device = mDevice.promote();
@@ -522,13 +521,11 @@
status_t HeicCompositeStream::insertGbp(SurfaceMap* /*out*/outSurfaceMap,
Vector<int32_t>* /*out*/outputStreamIds, int32_t* /*out*/currentStreamId) {
if (outSurfaceMap->find(mAppSegmentStreamId) == outSurfaceMap->end()) {
- (*outSurfaceMap)[mAppSegmentStreamId] = std::vector<size_t>();
outputStreamIds->push_back(mAppSegmentStreamId);
}
(*outSurfaceMap)[mAppSegmentStreamId].push_back(mAppSegmentSurfaceId);
if (outSurfaceMap->find(mMainImageStreamId) == outSurfaceMap->end()) {
- (*outSurfaceMap)[mMainImageStreamId] = std::vector<size_t>();
outputStreamIds->push_back(mMainImageStreamId);
}
(*outSurfaceMap)[mMainImageStreamId].push_back(mMainImageSurfaceId);
@@ -635,7 +632,6 @@
mAppSegmentConsumer->unlockBuffer(imgBuffer);
} else {
mPendingInputFrames[frameNumber].appSegmentBuffer = imgBuffer;
- mLockedAppSegmentBufferCnt++;
}
mInputAppSegmentBuffers.erase(it);
mAppSegmentFrameNumbers.pop();
@@ -898,10 +894,6 @@
strerror(-res), res);
return res;
}
- } else if (mLockedAppSegmentBufferCnt == kMaxAcquiredAppSegment) {
- ALOGE("%s: Out-of-order app segment buffers reaches limit %u", __FUNCTION__,
- kMaxAcquiredAppSegment);
- return INVALID_OPERATION;
}
}
@@ -1039,7 +1031,6 @@
mAppSegmentConsumer->unlockBuffer(inputFrame.appSegmentBuffer);
inputFrame.appSegmentBuffer.data = nullptr;
inputFrame.exifError = false;
- mLockedAppSegmentBufferCnt--;
return OK;
}
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.h b/services/camera/libcameraservice/api2/HeicCompositeStream.h
index 33ca69a..cbd9d21 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.h
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.h
@@ -45,7 +45,7 @@
status_t createInternalStreams(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
- camera3_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+ camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
std::vector<int> *surfaceIds, int streamSetId, bool isShared) override;
status_t deleteInternalStreams() override;
@@ -253,7 +253,6 @@
// Keep all incoming APP segment Blob buffer pending further processing.
std::vector<int64_t> mInputAppSegmentBuffers;
- int32_t mLockedAppSegmentBufferCnt;
// Keep all incoming HEIC blob buffer pending further processing.
std::vector<CodecOutputBufferInfo> mCodecOutputBuffers;
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index a537ef5..5e46f08 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -28,7 +28,6 @@
#include <utils/List.h>
#include "hardware/camera2.h"
-#include "hardware/camera3.h"
#include "camera/CameraMetadata.h"
#include "camera/CaptureResult.h"
#include "gui/IGraphicBufferProducer.h"
@@ -41,6 +40,41 @@
namespace android {
+namespace camera3 {
+
+typedef enum camera_request_template {
+ CAMERA_TEMPLATE_PREVIEW = 1,
+ CAMERA_TEMPLATE_STILL_CAPTURE = 2,
+ CAMERA_TEMPLATE_VIDEO_RECORD = 3,
+ CAMERA_TEMPLATE_VIDEO_SNAPSHOT = 4,
+ CAMERA_TEMPLATE_ZERO_SHUTTER_LAG = 5,
+ CAMERA_TEMPLATE_MANUAL = 6,
+ CAMERA_TEMPLATE_COUNT,
+ CAMERA_VENDOR_TEMPLATE_START = 0x40000000
+} camera_request_template_t;
+
+typedef enum camera_stream_configuration_mode {
+ CAMERA_STREAM_CONFIGURATION_NORMAL_MODE = 0,
+ CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE = 1,
+ CAMERA_VENDOR_STREAM_CONFIGURATION_MODE_START = 0x8000
+} camera_stream_configuration_mode_t;
+
+typedef struct camera_jpeg_blob {
+ uint16_t jpeg_blob_id;
+ uint32_t jpeg_size;
+} camera_jpeg_blob_t;
+
+enum {
+ CAMERA_JPEG_BLOB_ID = 0x00FF,
+ CAMERA_JPEG_APP_SEGMENTS_BLOB_ID = 0x0100,
+};
+
+} // namespace camera3
+
+using camera3::camera_request_template_t;;
+using camera3::camera_stream_configuration_mode_t;
+using camera3::camera_stream_rotation_t;
+
class CameraProviderManager;
// Mapping of output stream index to surface ids
@@ -128,7 +162,7 @@
*/
virtual status_t createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
@@ -143,7 +177,7 @@
*/
virtual status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
@@ -225,7 +259,8 @@
* - INVALID_OPERATION if the device was in the wrong state
*/
virtual status_t configureStreams(const CameraMetadata& sessionParams,
- int operatingMode = 0) = 0;
+ int operatingMode =
+ camera_stream_configuration_mode_t::CAMERA_STREAM_CONFIGURATION_NORMAL_MODE) = 0;
/**
* Retrieve a list of all stream ids that were advertised as capable of
@@ -241,7 +276,7 @@
* Create a metadata buffer with fields that the HAL device believes are
* best for the given use case
*/
- virtual status_t createDefaultRequest(int templateId,
+ virtual status_t createDefaultRequest(camera_request_template_t templateId,
CameraMetadata *request) = 0;
/**
@@ -367,6 +402,14 @@
* Get the status tracker of the camera device
*/
virtual wp<camera3::StatusTracker> getStatusTracker() = 0;
+
+ /**
+ * Set bitmask for image dump flag
+ */
+ void setImageDumpMask(int mask) { mImageDumpMask = mask; }
+
+protected:
+ bool mImageDumpMask = 0;
};
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/BufferUtils.cpp b/services/camera/libcameraservice/device3/BufferUtils.cpp
index cc29390..f3adf20 100644
--- a/services/camera/libcameraservice/device3/BufferUtils.cpp
+++ b/services/camera/libcameraservice/device3/BufferUtils.cpp
@@ -28,14 +28,14 @@
namespace android {
namespace camera3 {
-camera3_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status) {
+camera_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status) {
using hardware::camera::device::V3_2::BufferStatus;
switch (status) {
- case BufferStatus::OK: return CAMERA3_BUFFER_STATUS_OK;
- case BufferStatus::ERROR: return CAMERA3_BUFFER_STATUS_ERROR;
+ case BufferStatus::OK: return CAMERA_BUFFER_STATUS_OK;
+ case BufferStatus::ERROR: return CAMERA_BUFFER_STATUS_ERROR;
}
- return CAMERA3_BUFFER_STATUS_ERROR;
+ return CAMERA_BUFFER_STATUS_ERROR;
}
void BufferRecords::takeInflightBufferMap(BufferRecords& other) {
diff --git a/services/camera/libcameraservice/device3/BufferUtils.h b/services/camera/libcameraservice/device3/BufferUtils.h
index 452a908..1e1cd60 100644
--- a/services/camera/libcameraservice/device3/BufferUtils.h
+++ b/services/camera/libcameraservice/device3/BufferUtils.h
@@ -25,9 +25,6 @@
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
-// TODO: remove legacy camera3.h references
-#include "hardware/camera3.h"
-
#include <device3/Camera3OutputInterface.h>
namespace android {
@@ -158,7 +155,7 @@
static const uint64_t BUFFER_ID_NO_BUFFER = 0;
- camera3_buffer_status_t mapHidlBufferStatus(
+ camera_buffer_status_t mapHidlBufferStatus(
hardware::camera::device::V3_2::BufferStatus status);
} // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 50ef953..92c8e30 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -547,15 +547,15 @@
return usage;
}
-StreamRotation Camera3Device::mapToStreamRotation(camera3_stream_rotation_t rotation) {
+StreamRotation Camera3Device::mapToStreamRotation(camera_stream_rotation_t rotation) {
switch (rotation) {
- case CAMERA3_STREAM_ROTATION_0:
+ case CAMERA_STREAM_ROTATION_0:
return StreamRotation::ROTATION_0;
- case CAMERA3_STREAM_ROTATION_90:
+ case CAMERA_STREAM_ROTATION_90:
return StreamRotation::ROTATION_90;
- case CAMERA3_STREAM_ROTATION_180:
+ case CAMERA_STREAM_ROTATION_180:
return StreamRotation::ROTATION_180;
- case CAMERA3_STREAM_ROTATION_270:
+ case CAMERA_STREAM_ROTATION_270:
return StreamRotation::ROTATION_270;
}
ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
@@ -563,14 +563,14 @@
}
status_t Camera3Device::mapToStreamConfigurationMode(
- camera3_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
+ camera_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
if (mode == nullptr) return BAD_VALUE;
- if (operationMode < CAMERA3_VENDOR_STREAM_CONFIGURATION_MODE_START) {
+ if (operationMode < CAMERA_VENDOR_STREAM_CONFIGURATION_MODE_START) {
switch(operationMode) {
- case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE:
+ case CAMERA_STREAM_CONFIGURATION_NORMAL_MODE:
*mode = StreamConfigurationMode::NORMAL_MODE;
break;
- case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
+ case CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
*mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
break;
default:
@@ -779,7 +779,7 @@
}
if (dumpTemplates) {
- const char *templateNames[CAMERA3_TEMPLATE_COUNT] = {
+ const char *templateNames[CAMERA_TEMPLATE_COUNT] = {
"TEMPLATE_PREVIEW",
"TEMPLATE_STILL_CAPTURE",
"TEMPLATE_VIDEO_RECORD",
@@ -788,10 +788,10 @@
"TEMPLATE_MANUAL",
};
- for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; i++) {
+ for (int i = 1; i < CAMERA_TEMPLATE_COUNT; i++) {
camera_metadata_t *templateRequest = nullptr;
mInterface->constructDefaultRequestSettings(
- (camera3_request_template_t) i, &templateRequest);
+ (camera_request_template_t) i, &templateRequest);
lines = String8::format(" HAL Request %s:\n", templateNames[i-1]);
if (templateRequest == nullptr) {
lines.append(" Not supported\n");
@@ -1203,7 +1203,7 @@
// This point should only be reached via API1 (API2 must explicitly call configureStreams)
// so unilaterally select normal operating mode.
res = filterParamsAndConfigureLocked(request.begin()->metadata,
- CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
+ CAMERA_STREAM_CONFIGURATION_NORMAL_MODE);
// Stream configuration failed. Client might try other configuraitons.
if (res != OK) {
CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
@@ -1322,7 +1322,7 @@
status_t Camera3Device::createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId,
std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
ATRACE_CALL();
@@ -1342,7 +1342,7 @@
status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId,
std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
ATRACE_CALL();
@@ -1456,6 +1456,8 @@
newStream->setBufferManager(mBufferManager);
+ newStream->setImageDumpMask(mImageDumpMask);
+
res = mOutputStreams.add(mNextStreamId, newStream);
if (res < 0) {
SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
@@ -1619,7 +1621,7 @@
// speculative configuration using the values from the last cached
// default request.
if (sessionParams.isEmpty() &&
- ((mLastTemplateId > 0) && (mLastTemplateId < CAMERA3_TEMPLATE_COUNT)) &&
+ ((mLastTemplateId > 0) && (mLastTemplateId < CAMERA_TEMPLATE_COUNT)) &&
(!mRequestTemplateCache[mLastTemplateId].isEmpty())) {
ALOGV("%s: Speculative session param configuration with template id: %d", __func__,
mLastTemplateId);
@@ -1669,12 +1671,12 @@
return mInputStream->getInputBufferProducer(producer);
}
-status_t Camera3Device::createDefaultRequest(int templateId,
+status_t Camera3Device::createDefaultRequest(camera_request_template_t templateId,
CameraMetadata *request) {
ATRACE_CALL();
ALOGV("%s: for template %d", __FUNCTION__, templateId);
- if (templateId <= 0 || templateId >= CAMERA3_TEMPLATE_COUNT) {
+ if (templateId <= 0 || templateId >= CAMERA_TEMPLATE_COUNT) {
android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26866110",
CameraThreadState::getCallingUid(), nullptr, 0);
return BAD_VALUE;
@@ -1710,7 +1712,7 @@
camera_metadata_t *rawRequest;
status_t res = mInterface->constructDefaultRequestSettings(
- (camera3_request_template_t) templateId, &rawRequest);
+ (camera_request_template_t) templateId, &rawRequest);
{
Mutex::Autolock l(mLock);
@@ -2519,7 +2521,7 @@
// any pending requests.
if (mInputStream != NULL && notifyRequestThread) {
while (true) {
- camera3_stream_buffer_t inputBuffer;
+ camera_stream_buffer_t inputBuffer;
status_t res = mInputStream->getInputBuffer(&inputBuffer,
/*respectHalLimit*/ false);
if (res != OK) {
@@ -2527,7 +2529,7 @@
break;
}
- inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+ inputBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
res = mInputStream->returnInputBuffer(inputBuffer);
if (res != OK) {
ALOGE("%s: %d: couldn't return input buffer while clearing input queue: "
@@ -2555,17 +2557,17 @@
mPreparerThread->pause();
- camera3_stream_configuration config;
+ camera_stream_configuration config;
config.operation_mode = mOperatingMode;
config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
- Vector<camera3_stream_t*> streams;
+ Vector<camera3::camera_stream_t*> streams;
streams.setCapacity(config.num_streams);
std::vector<uint32_t> bufferSizes(config.num_streams, 0);
if (mInputStream != NULL) {
- camera3_stream_t *inputStream;
+ camera3::camera_stream_t *inputStream;
inputStream = mInputStream->startConfiguration();
if (inputStream == NULL) {
CLOGE("Can't start input stream configuration");
@@ -2585,7 +2587,7 @@
continue;
}
- camera3_stream_t *outputStream;
+ camera3::camera_stream_t *outputStream;
outputStream = mOutputStreams[i]->startConfiguration();
if (outputStream == NULL) {
CLOGE("Can't start output stream configuration");
@@ -3011,7 +3013,7 @@
}
status_t Camera3Device::HalInterface::constructDefaultRequestSettings(
- camera3_request_template_t templateId,
+ camera_request_template_t templateId,
/*out*/ camera_metadata_t **requestTemplate) {
ATRACE_NAME("CameraHal::constructDefaultRequestSettings");
if (!valid()) return INVALID_OPERATION;
@@ -3043,22 +3045,22 @@
hardware::Return<void> err;
RequestTemplate id;
switch (templateId) {
- case CAMERA3_TEMPLATE_PREVIEW:
+ case CAMERA_TEMPLATE_PREVIEW:
id = RequestTemplate::PREVIEW;
break;
- case CAMERA3_TEMPLATE_STILL_CAPTURE:
+ case CAMERA_TEMPLATE_STILL_CAPTURE:
id = RequestTemplate::STILL_CAPTURE;
break;
- case CAMERA3_TEMPLATE_VIDEO_RECORD:
+ case CAMERA_TEMPLATE_VIDEO_RECORD:
id = RequestTemplate::VIDEO_RECORD;
break;
- case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
+ case CAMERA_TEMPLATE_VIDEO_SNAPSHOT:
id = RequestTemplate::VIDEO_SNAPSHOT;
break;
- case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
+ case CAMERA_TEMPLATE_ZERO_SHUTTER_LAG:
id = RequestTemplate::ZERO_SHUTTER_LAG;
break;
- case CAMERA3_TEMPLATE_MANUAL:
+ case CAMERA_TEMPLATE_MANUAL:
id = RequestTemplate::MANUAL;
break;
default:
@@ -3124,7 +3126,7 @@
}
status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
- camera3_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
+ camera_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
ATRACE_NAME("CameraHal::configureStreams");
if (!valid()) return INVALID_OPERATION;
status_t res = OK;
@@ -3138,17 +3140,17 @@
for (size_t i = 0; i < config->num_streams; i++) {
device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
- camera3_stream_t *src = config->streams[i];
+ camera3::camera_stream_t *src = config->streams[i];
Camera3Stream* cam3stream = Camera3Stream::cast(src);
cam3stream->setBufferFreedListener(this);
int streamId = cam3stream->getId();
StreamType streamType;
switch (src->stream_type) {
- case CAMERA3_STREAM_OUTPUT:
+ case CAMERA_STREAM_OUTPUT:
streamType = StreamType::OUTPUT;
break;
- case CAMERA3_STREAM_INPUT:
+ case CAMERA_STREAM_INPUT:
streamType = StreamType::INPUT;
break;
default:
@@ -3161,7 +3163,7 @@
dst3_2.width = src->width;
dst3_2.height = src->height;
dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
- dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
+ dst3_2.rotation = mapToStreamRotation((camera_stream_rotation_t) src->rotation);
// For HidlSession version 3.5 or newer, the format and dataSpace sent
// to HAL are original, not the overriden ones.
if (mHidlSession_3_5 != nullptr) {
@@ -3188,7 +3190,7 @@
StreamConfigurationMode operationMode;
res = mapToStreamConfigurationMode(
- (camera3_stream_configuration_mode_t) config->operation_mode,
+ (camera_stream_configuration_mode_t) config->operation_mode,
/*out*/ &operationMode);
if (res != OK) {
return res;
@@ -3317,7 +3319,7 @@
// And convert output stream configuration from HIDL
for (size_t i = 0; i < config->num_streams; i++) {
- camera3_stream_t *dst = config->streams[i];
+ camera3::camera_stream_t *dst = config->streams[i];
int streamId = Camera3Stream::cast(dst)->getId();
// Start scan at i, with the assumption that the stream order matches
@@ -3370,7 +3372,7 @@
dst->data_space = overrideDataSpace;
}
- if (dst->stream_type == CAMERA3_STREAM_INPUT) {
+ if (dst->stream_type == CAMERA_STREAM_INPUT) {
if (src.v3_2.producerUsage != 0) {
ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
__FUNCTION__, streamId);
@@ -3394,7 +3396,7 @@
return res;
}
-status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera3_capture_request_t* request,
+status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera_capture_request_t* request,
/*out*/device::V3_2::CaptureRequest* captureRequest,
/*out*/std::vector<native_handle_t*>* handlesCreated,
/*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
@@ -3439,7 +3441,7 @@
captureRequest->outputBuffers.resize(request->num_output_buffers);
for (size_t i = 0; i < request->num_output_buffers; i++) {
- const camera3_stream_buffer_t *src = request->output_buffers + i;
+ const camera_stream_buffer_t *src = request->output_buffers + i;
StreamBuffer &dst = captureRequest->outputBuffers[i];
int32_t streamId = Camera3Stream::cast(src->stream)->getId();
if (src->buffer != nullptr) {
@@ -3497,7 +3499,7 @@
}
status_t Camera3Device::HalInterface::processBatchCaptureRequests(
- std::vector<camera3_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
+ std::vector<camera_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
ATRACE_NAME("CameraHal::processBatchCaptureRequests");
if (!valid()) return INVALID_OPERATION;
@@ -3551,7 +3553,7 @@
// Write metadata to FMQ.
for (size_t i = 0; i < batchSize; i++) {
- camera3_capture_request_t* request = requests[i];
+ camera_capture_request_t* request = requests[i];
device::V3_2::CaptureRequest* captureRequest;
if (hidlSession_3_4 != nullptr) {
captureRequest = &captureRequests_3_4[i].v3_2;
@@ -4023,14 +4025,14 @@
it != mRequestQueue.end(); ++it) {
// Abort the input buffers for reprocess requests.
if ((*it)->mInputStream != NULL) {
- camera3_stream_buffer_t inputBuffer;
+ camera_stream_buffer_t inputBuffer;
status_t res = (*it)->mInputStream->getInputBuffer(&inputBuffer,
/*respectHalLimit*/ false);
if (res != OK) {
ALOGW("%s: %d: couldn't get input buffer while clearing the request "
"list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
} else {
- inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+ inputBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
res = (*it)->mInputStream->returnInputBuffer(inputBuffer);
if (res != OK) {
ALOGE("%s: %d: couldn't return input buffer while clearing the request "
@@ -4134,7 +4136,7 @@
ATRACE_CALL();
status_t res;
size_t batchSize = mNextRequests.size();
- std::vector<camera3_capture_request_t*> requests(batchSize);
+ std::vector<camera_capture_request_t*> requests(batchSize);
uint32_t numRequestProcessed = 0;
for (size_t i = 0; i < batchSize; i++) {
requests[i] = &mNextRequests.editItemAt(i).halRequest;
@@ -4453,8 +4455,8 @@
for (size_t i = 0; i < mNextRequests.size(); i++) {
auto& nextRequest = mNextRequests.editItemAt(i);
sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
- camera3_capture_request_t* halRequest = &nextRequest.halRequest;
- Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
+ camera_capture_request_t* halRequest = &nextRequest.halRequest;
+ Vector<camera_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
// Prepare a request to HAL
halRequest->frame_number = captureRequest->mResultExtras.frameNumber;
@@ -4622,7 +4624,7 @@
halRequest->input_buffer = NULL;
}
- outputBuffers->insertAt(camera3_stream_buffer_t(), 0,
+ outputBuffers->insertAt(camera_stream_buffer_t(), 0,
captureRequest->mOutputStreams.size());
halRequest->output_buffers = outputBuffers->array();
std::set<String8> requestedPhysicalCameras;
@@ -4678,10 +4680,10 @@
return TIMED_OUT;
}
// HAL will request buffer through requestStreamBuffer API
- camera3_stream_buffer_t& buffer = outputBuffers->editItemAt(j);
+ camera_stream_buffer_t& buffer = outputBuffers->editItemAt(j);
buffer.stream = outputStream->asHalStream();
buffer.buffer = nullptr;
- buffer.status = CAMERA3_BUFFER_STATUS_OK;
+ buffer.status = CAMERA_BUFFER_STATUS_OK;
buffer.acquire_fence = -1;
buffer.release_fence = -1;
} else {
@@ -4934,7 +4936,7 @@
}
void Camera3Device::RequestThread::cleanupPhysicalSettings(sp<CaptureRequest> request,
- camera3_capture_request_t *halRequest) {
+ camera_capture_request_t *halRequest) {
if ((request == nullptr) || (halRequest == nullptr)) {
ALOGE("%s: Invalid request!", __FUNCTION__);
return;
@@ -4969,8 +4971,8 @@
}
sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
- camera3_capture_request_t* halRequest = &nextRequest.halRequest;
- Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
+ camera_capture_request_t* halRequest = &nextRequest.halRequest;
+ Vector<camera_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
if (halRequest->settings != NULL) {
captureRequest->mSettingsList.begin()->metadata.unlock(halRequest->settings);
@@ -4979,7 +4981,7 @@
cleanupPhysicalSettings(captureRequest, halRequest);
if (captureRequest->mInputStream != NULL) {
- captureRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+ captureRequest->mInputBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
captureRequest->mInputStream->returnInputBuffer(captureRequest->mInputBuffer);
}
@@ -4993,7 +4995,7 @@
close(acquireFence);
outputBuffers->editItemAt(i).acquire_fence = -1;
}
- outputBuffers->editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
+ outputBuffers->editItemAt(i).status = CAMERA_BUFFER_STATUS_ERROR;
captureRequest->mOutputStreams.editItemAt(i)->returnBuffer((*outputBuffers)[i], 0,
/*timestampIncreasing*/true, std::vector<size_t> (),
captureRequest->mResultExtras.frameNumber);
@@ -5043,7 +5045,7 @@
return;
}
- nextRequest.halRequest = camera3_capture_request_t();
+ nextRequest.halRequest = camera_capture_request_t();
nextRequest.submitted = false;
mNextRequests.add(nextRequest);
@@ -5057,7 +5059,7 @@
break;
}
- additionalRequest.halRequest = camera3_capture_request_t();
+ additionalRequest.halRequest = camera_capture_request_t();
additionalRequest.submitted = false;
mNextRequests.add(additionalRequest);
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index de7df81..b06ce45 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -56,6 +56,13 @@
#include "utils/LatencyHistogram.h"
#include <camera_metadata_hidden.h>
+using android::camera3::camera_capture_request_t;
+using android::camera3::camera_jpeg_blob_t;
+using android::camera3::camera_request_template;
+using android::camera3::camera_stream_buffer_t;
+using android::camera3::camera_stream_configuration_t;
+using android::camera3::camera_stream_configuration_mode_t;
+using android::camera3::CAMERA_TEMPLATE_COUNT;
using android::camera3::OutputStreamInfo;
namespace android {
@@ -122,14 +129,14 @@
// and finish the stream configuration before starting output streaming.
status_t createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, uint64_t consumerUsage = 0) override;
status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
@@ -146,14 +153,14 @@
status_t configureStreams(const CameraMetadata& sessionParams,
int operatingMode =
- static_cast<int>(hardware::camera::device::V3_2::StreamConfigurationMode::NORMAL_MODE))
- override;
+ camera_stream_configuration_mode_t::CAMERA_STREAM_CONFIGURATION_NORMAL_MODE) override;
status_t getInputBufferProducer(
sp<IGraphicBufferProducer> *producer) override;
void getOfflineStreamIds(std::vector<int> *offlineStreamIds) override;
- status_t createDefaultRequest(int templateId, CameraMetadata *request) override;
+ status_t createDefaultRequest(camera_request_template_t templateId,
+ CameraMetadata *request) override;
// Transitions to the idle state on success
status_t waitUntilDrained() override;
@@ -242,9 +249,9 @@
android_dataspace dataSpace);
static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint64_t usage);
static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
- camera3_stream_rotation_t rotation);
+ camera_stream_rotation_t rotation);
// Returns a negative error code if the passed-in operation mode is not valid.
- static status_t mapToStreamConfigurationMode(camera3_stream_configuration_mode_t operationMode,
+ static status_t mapToStreamConfigurationMode(camera_stream_configuration_mode_t operationMode,
/*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
static android_dataspace mapToFrameworkDataspace(
@@ -255,7 +262,6 @@
hardware::camera::device::V3_2::BufferUsageFlags usage);
private:
-
status_t disconnectImpl();
// internal typedefs
@@ -275,7 +281,7 @@
struct RequestTrigger;
// minimal jpeg buffer size: 256KB + blob header
- static const ssize_t kMinJpegBufferSize = 256 * 1024 + sizeof(camera3_jpeg_blob);
+ static const ssize_t kMinJpegBufferSize = 256 * 1024 + sizeof(camera_jpeg_blob_t);
// Constant to use for stream ID when one doesn't exist
static const int NO_STREAM = -1;
@@ -330,10 +336,10 @@
// Calls into the HAL interface
// Caller takes ownership of requestTemplate
- status_t constructDefaultRequestSettings(camera3_request_template_t templateId,
+ status_t constructDefaultRequestSettings(camera_request_template templateId,
/*out*/ camera_metadata_t **requestTemplate);
status_t configureStreams(const camera_metadata_t *sessionParams,
- /*inout*/ camera3_stream_configuration *config,
+ /*inout*/ camera_stream_configuration_t *config,
const std::vector<uint32_t>& bufferSizes);
// When the call succeeds, the ownership of acquire fences in requests is transferred to
@@ -341,7 +347,7 @@
// HAL process and close the FD in cameraserver process. When the call fails, the ownership
// of the acquire fence still belongs to the caller.
status_t processBatchCaptureRequests(
- std::vector<camera3_capture_request_t*>& requests,
+ std::vector<camera_capture_request_t*>& requests,
/*out*/uint32_t* numRequestProcessed);
status_t flush();
status_t dump(int fd);
@@ -400,9 +406,9 @@
std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
- // The output HIDL request still depends on input camera3_capture_request_t
- // Do not free input camera3_capture_request_t before output HIDL request
- status_t wrapAsHidlRequest(camera3_capture_request_t* in,
+ // The output HIDL request still depends on input camera_capture_request_t
+ // Do not free input camera_capture_request_t before output HIDL request
+ status_t wrapAsHidlRequest(camera_capture_request_t* in,
/*out*/hardware::camera::device::V3_2::CaptureRequest* out,
/*out*/std::vector<native_handle_t*>* handlesCreated,
/*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers);
@@ -442,7 +448,7 @@
bool mSupportNativeZoomRatio;
std::unordered_map<std::string, CameraMetadata> mPhysicalDeviceInfoMap;
- CameraMetadata mRequestTemplateCache[CAMERA3_TEMPLATE_COUNT];
+ CameraMetadata mRequestTemplateCache[CAMERA_TEMPLATE_COUNT];
struct Size {
uint32_t width;
@@ -503,7 +509,7 @@
public:
PhysicalCameraSettingsList mSettingsList;
sp<camera3::Camera3Stream> mInputStream;
- camera3_stream_buffer_t mInputBuffer;
+ camera_stream_buffer_t mInputBuffer;
Vector<sp<camera3::Camera3OutputStreamInterface> >
mOutputStreams;
SurfaceMap mOutputSurfaces;
@@ -891,8 +897,8 @@
// Used to prepare a batch of requests.
struct NextRequest {
sp<CaptureRequest> captureRequest;
- camera3_capture_request_t halRequest;
- Vector<camera3_stream_buffer_t> outputBuffers;
+ camera_capture_request_t halRequest;
+ Vector<camera_stream_buffer_t> outputBuffers;
bool submitted;
};
@@ -918,7 +924,7 @@
// Release physical camera settings and camera id resources.
void cleanupPhysicalSettings(sp<CaptureRequest> request,
- /*out*/camera3_capture_request_t *halRequest);
+ /*out*/camera_capture_request_t *halRequest);
// Pause handling
bool waitIfPaused();
diff --git a/services/camera/libcameraservice/device3/Camera3FakeStream.cpp b/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
index 230512a..ab5084e 100644
--- a/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
@@ -29,7 +29,7 @@
const String8 Camera3FakeStream::FAKE_ID;
Camera3FakeStream::Camera3FakeStream(int id) :
- Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, FAKE_WIDTH, FAKE_HEIGHT,
+ Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, FAKE_WIDTH, FAKE_HEIGHT,
/*maxSize*/0, FAKE_FORMAT, FAKE_DATASPACE, FAKE_ROTATION,
FAKE_ID) {
@@ -39,7 +39,7 @@
}
-status_t Camera3FakeStream::getBufferLocked(camera3_stream_buffer *,
+status_t Camera3FakeStream::getBufferLocked(camera_stream_buffer *,
const std::vector<size_t>&) {
ATRACE_CALL();
ALOGE("%s: Stream %d: Fake stream cannot produce buffers!", __FUNCTION__, mId);
@@ -47,7 +47,7 @@
}
status_t Camera3FakeStream::returnBufferLocked(
- const camera3_stream_buffer &,
+ const camera_stream_buffer &,
nsecs_t, const std::vector<size_t>&) {
ATRACE_CALL();
ALOGE("%s: Stream %d: Fake stream cannot return buffers!", __FUNCTION__, mId);
@@ -55,7 +55,7 @@
}
status_t Camera3FakeStream::returnBufferCheckedLocked(
- const camera3_stream_buffer &,
+ const camera_stream_buffer &,
nsecs_t,
bool,
const std::vector<size_t>&,
diff --git a/services/camera/libcameraservice/device3/Camera3FakeStream.h b/services/camera/libcameraservice/device3/Camera3FakeStream.h
index fbf37e6..4a99079 100644
--- a/services/camera/libcameraservice/device3/Camera3FakeStream.h
+++ b/services/camera/libcameraservice/device3/Camera3FakeStream.h
@@ -104,7 +104,7 @@
* Note that we release the lock briefly in this function
*/
virtual status_t returnBufferCheckedLocked(
- const camera3_stream_buffer &buffer,
+ const camera_stream_buffer &buffer,
nsecs_t timestamp,
bool output,
const std::vector<size_t>& surface_ids,
@@ -121,17 +121,17 @@
static const int FAKE_HEIGHT = 240;
static const int FAKE_FORMAT = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
static const android_dataspace FAKE_DATASPACE = HAL_DATASPACE_UNKNOWN;
- static const camera3_stream_rotation_t FAKE_ROTATION = CAMERA3_STREAM_ROTATION_0;
+ static const camera_stream_rotation_t FAKE_ROTATION = CAMERA_STREAM_ROTATION_0;
static const uint64_t FAKE_USAGE = GRALLOC_USAGE_HW_COMPOSER;
static const String8 FAKE_ID;
/**
* Internal Camera3Stream interface
*/
- virtual status_t getBufferLocked(camera3_stream_buffer *buffer,
+ virtual status_t getBufferLocked(camera_stream_buffer *buffer,
const std::vector<size_t>& surface_ids = std::vector<size_t>());
virtual status_t returnBufferLocked(
- const camera3_stream_buffer &buffer,
+ const camera_stream_buffer &buffer,
nsecs_t timestamp, const std::vector<size_t>& surface_ids);
virtual status_t configureQueueLocked();
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index bda2961..f6acda8 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -29,9 +29,9 @@
namespace camera3 {
-Camera3IOStreamBase::Camera3IOStreamBase(int id, camera3_stream_type_t type,
+Camera3IOStreamBase::Camera3IOStreamBase(int id, camera_stream_type_t type,
uint32_t width, uint32_t height, size_t maxSize, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId, int setId) :
Camera3Stream(id, type,
width, height, maxSize, format, dataSpace, rotation,
@@ -77,13 +77,13 @@
lines.appendFormat(" State: %d\n", mState);
lines.appendFormat(" Dims: %d x %d, format 0x%x, dataspace 0x%x\n",
- camera3_stream::width, camera3_stream::height,
- camera3_stream::format, camera3_stream::data_space);
+ camera_stream::width, camera_stream::height,
+ camera_stream::format, camera_stream::data_space);
lines.appendFormat(" Max size: %zu\n", mMaxSize);
lines.appendFormat(" Combined usage: %" PRIu64 ", max HAL buffers: %d\n",
- mUsage | consumerUsage, camera3_stream::max_buffers);
- if (strlen(camera3_stream::physical_camera_id) > 0) {
- lines.appendFormat(" Physical camera id: %s\n", camera3_stream::physical_camera_id);
+ mUsage | consumerUsage, camera_stream::max_buffers);
+ if (strlen(camera_stream::physical_camera_id) > 0) {
+ lines.appendFormat(" Physical camera id: %s\n", camera_stream::physical_camera_id);
}
lines.appendFormat(" Frames produced: %d, last timestamp: %" PRId64 " ns\n",
mFrameCount, mLastTimestamp);
@@ -150,11 +150,11 @@
return OK;
}
-void Camera3IOStreamBase::handoutBufferLocked(camera3_stream_buffer &buffer,
+void Camera3IOStreamBase::handoutBufferLocked(camera_stream_buffer &buffer,
buffer_handle_t *handle,
int acquireFence,
int releaseFence,
- camera3_buffer_status_t status,
+ camera_buffer_status_t status,
bool output) {
/**
* Note that all fences are now owned by HAL.
@@ -220,7 +220,7 @@
}
status_t Camera3IOStreamBase::returnAnyBufferLocked(
- const camera3_stream_buffer &buffer,
+ const camera_stream_buffer &buffer,
nsecs_t timestamp,
bool output,
const std::vector<size_t>& surface_ids) {
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index ca62239..719fa14 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -32,9 +32,9 @@
class Camera3IOStreamBase :
public Camera3Stream {
protected:
- Camera3IOStreamBase(int id, camera3_stream_type_t type,
+ Camera3IOStreamBase(int id, camera_stream_type_t type,
uint32_t width, uint32_t height, size_t maxSize, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
int setId = CAMERA3_STREAM_SET_ID_INVALID);
@@ -64,13 +64,13 @@
sp<Fence> mCombinedFence;
status_t returnAnyBufferLocked(
- const camera3_stream_buffer &buffer,
+ const camera_stream_buffer &buffer,
nsecs_t timestamp,
bool output,
const std::vector<size_t>& surface_ids = std::vector<size_t>());
virtual status_t returnBufferCheckedLocked(
- const camera3_stream_buffer &buffer,
+ const camera_stream_buffer &buffer,
nsecs_t timestamp,
bool output,
const std::vector<size_t>& surface_ids,
@@ -100,11 +100,11 @@
// Hand out the buffer to a native location,
// incrementing the internal refcount and dequeued buffer count
- void handoutBufferLocked(camera3_stream_buffer &buffer,
+ void handoutBufferLocked(camera_stream_buffer &buffer,
buffer_handle_t *handle,
int acquire_fence,
int release_fence,
- camera3_buffer_status_t status,
+ camera_buffer_status_t status,
bool output);
}; // class Camera3IOStreamBase
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index ebd33e9..ad70a3a 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -31,8 +31,8 @@
Camera3InputStream::Camera3InputStream(int id,
uint32_t width, uint32_t height, int format) :
- Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height, /*maxSize*/0,
- format, HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0,
+ Camera3IOStreamBase(id, CAMERA_STREAM_INPUT, width, height, /*maxSize*/0,
+ format, HAL_DATASPACE_UNKNOWN, CAMERA_STREAM_ROTATION_0,
FAKE_ID) {
if (format == HAL_PIXEL_FORMAT_BLOB) {
@@ -46,7 +46,7 @@
}
status_t Camera3InputStream::getInputBufferLocked(
- camera3_stream_buffer *buffer) {
+ camera_stream_buffer *buffer) {
ATRACE_CALL();
status_t res;
@@ -86,7 +86,7 @@
* in which case we reassign it to acquire_fence
*/
handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
- /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/false);
+ /*releaseFence*/-1, CAMERA_BUFFER_STATUS_OK, /*output*/false);
mBuffersInFlight.push_back(bufferItem);
mFrameCount++;
@@ -96,7 +96,7 @@
}
status_t Camera3InputStream::returnBufferCheckedLocked(
- const camera3_stream_buffer &buffer,
+ const camera_stream_buffer &buffer,
nsecs_t timestamp,
bool output,
const std::vector<size_t>&,
@@ -134,7 +134,7 @@
return INVALID_OPERATION;
}
- if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
+ if (buffer.status == CAMERA_BUFFER_STATUS_ERROR) {
if (buffer.release_fence != -1) {
ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when "
"there is an error", __FUNCTION__, mId, buffer.release_fence);
@@ -144,7 +144,7 @@
/**
* Reassign release fence as the acquire fence incase of error
*/
- const_cast<camera3_stream_buffer*>(&buffer)->release_fence =
+ const_cast<camera_stream_buffer*>(&buffer)->release_fence =
buffer.acquire_fence;
}
@@ -165,7 +165,7 @@
}
status_t Camera3InputStream::returnInputBufferLocked(
- const camera3_stream_buffer &buffer) {
+ const camera_stream_buffer &buffer) {
ATRACE_CALL();
return returnAnyBufferLocked(buffer, /*timestamp*/0, /*output*/false);
@@ -224,7 +224,7 @@
}
assert(mMaxSize == 0);
- assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB);
+ assert(camera_stream::format != HAL_PIXEL_FORMAT_BLOB);
mHandoutTotalBufferCount = 0;
mFrameCount = 0;
@@ -244,14 +244,14 @@
}
size_t minBufs = static_cast<size_t>(minUndequeuedBuffers);
- if (camera3_stream::max_buffers == 0) {
+ if (camera_stream::max_buffers == 0) {
ALOGE("%s: %d: HAL sets max_buffer to 0. Must be at least 1.",
__FUNCTION__, __LINE__);
return INVALID_OPERATION;
}
/*
- * We promise never to 'acquire' more than camera3_stream::max_buffers
+ * We promise never to 'acquire' more than camera_stream::max_buffers
* at any one time.
*
* Boost the number up to meet the minimum required buffer count.
@@ -259,8 +259,8 @@
* (Note that this sets consumer-side buffer count only,
* and not the sum of producer+consumer side as in other camera streams).
*/
- mTotalBufferCount = camera3_stream::max_buffers > minBufs ?
- camera3_stream::max_buffers : minBufs;
+ mTotalBufferCount = camera_stream::max_buffers > minBufs ?
+ camera_stream::max_buffers : minBufs;
// TODO: somehow set the total buffer count when producer connects?
mConsumer = new BufferItemConsumer(consumer, mUsage,
@@ -272,17 +272,17 @@
mConsumer->setBufferFreedListener(this);
}
- res = mConsumer->setDefaultBufferSize(camera3_stream::width,
- camera3_stream::height);
+ res = mConsumer->setDefaultBufferSize(camera_stream::width,
+ camera_stream::height);
if (res != OK) {
ALOGE("%s: Stream %d: Could not set buffer dimensions %dx%d",
- __FUNCTION__, mId, camera3_stream::width, camera3_stream::height);
+ __FUNCTION__, mId, camera_stream::width, camera_stream::height);
return res;
}
- res = mConsumer->setDefaultBufferFormat(camera3_stream::format);
+ res = mConsumer->setDefaultBufferFormat(camera_stream::format);
if (res != OK) {
ALOGE("%s: Stream %d: Could not set buffer format %d",
- __FUNCTION__, mId, camera3_stream::format);
+ __FUNCTION__, mId, camera_stream::format);
return res;
}
@@ -298,8 +298,8 @@
void Camera3InputStream::onBufferFreed(const wp<GraphicBuffer>& gb) {
const sp<GraphicBuffer> buffer = gb.promote();
if (buffer != nullptr) {
- camera3_stream_buffer streamBuffer =
- {nullptr, &buffer->handle, 0, -1, -1};
+ camera_stream_buffer streamBuffer =
+ {nullptr, &buffer->handle, CAMERA_BUFFER_STATUS_OK, -1, -1};
// Check if this buffer is outstanding.
if (isOutstandingBuffer(streamBuffer)) {
ALOGV("%s: Stream %d: Trying to free a buffer that is still being "
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index 22697b7..03afa17 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -59,7 +59,7 @@
* Camera3IOStreamBase
*/
virtual status_t returnBufferCheckedLocked(
- const camera3_stream_buffer &buffer,
+ const camera_stream_buffer &buffer,
nsecs_t timestamp,
bool output,
const std::vector<size_t>& surface_ids,
@@ -70,9 +70,9 @@
* Camera3Stream interface
*/
- virtual status_t getInputBufferLocked(camera3_stream_buffer *buffer);
+ virtual status_t getInputBufferLocked(camera_stream_buffer *buffer);
virtual status_t returnInputBufferLocked(
- const camera3_stream_buffer &buffer);
+ const camera_stream_buffer &buffer);
virtual status_t getInputBufferProducerLocked(
sp<IGraphicBufferProducer> *producer);
virtual status_t disconnectLocked();
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 7b812f2..4b5889c 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -18,8 +18,15 @@
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0
+#include <ctime>
+#include <fstream>
+
+#include <android-base/unique_fd.h>
+#include <ui/GraphicBuffer.h>
#include <utils/Log.h>
#include <utils/Trace.h>
+
+#include "api1/client2/JpegProcessor.h"
#include "Camera3OutputStream.h"
#include "utils/TraceHFR.h"
@@ -35,10 +42,10 @@
Camera3OutputStream::Camera3OutputStream(int id,
sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
int setId) :
- Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
+ Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
/*maxSize*/0, format, dataSpace, rotation,
physicalCameraId, setId),
mConsumer(consumer),
@@ -62,9 +69,9 @@
Camera3OutputStream::Camera3OutputStream(int id,
sp<Surface> consumer,
uint32_t width, uint32_t height, size_t maxSize, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId, int setId) :
- Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, maxSize,
+ Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height, maxSize,
format, dataSpace, rotation, physicalCameraId, setId),
mConsumer(consumer),
mTransform(0),
@@ -94,9 +101,9 @@
Camera3OutputStream::Camera3OutputStream(int id,
uint32_t width, uint32_t height, int format,
uint64_t consumerUsage, android_dataspace dataSpace,
- camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
+ camera_stream_rotation_t rotation, nsecs_t timestampOffset,
const String8& physicalCameraId, int setId) :
- Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
+ Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
/*maxSize*/0, format, dataSpace, rotation,
physicalCameraId, setId),
mConsumer(nullptr),
@@ -127,11 +134,11 @@
mBufferProducerListener = new BufferProducerListener(this, needsReleaseNotify);
}
-Camera3OutputStream::Camera3OutputStream(int id, camera3_stream_type_t type,
+Camera3OutputStream::Camera3OutputStream(int id, camera_stream_type_t type,
uint32_t width, uint32_t height,
int format,
android_dataspace dataSpace,
- camera3_stream_rotation_t rotation,
+ camera_stream_rotation_t rotation,
const String8& physicalCameraId,
uint64_t consumerUsage, nsecs_t timestampOffset,
int setId) :
@@ -159,7 +166,7 @@
disconnectLocked();
}
-status_t Camera3OutputStream::getBufferLocked(camera3_stream_buffer *buffer,
+status_t Camera3OutputStream::getBufferLocked(camera_stream_buffer *buffer,
const std::vector<size_t>&) {
ATRACE_HFR_CALL();
@@ -177,7 +184,7 @@
* in which case we reassign it to acquire_fence
*/
handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
- /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/true);
+ /*releaseFence*/-1, CAMERA_BUFFER_STATUS_OK, /*output*/true);
return OK;
}
@@ -189,7 +196,7 @@
}
status_t Camera3OutputStream::returnBufferLocked(
- const camera3_stream_buffer &buffer,
+ const camera_stream_buffer &buffer,
nsecs_t timestamp, const std::vector<size_t>& surface_ids) {
ATRACE_HFR_CALL();
@@ -206,7 +213,7 @@
}
status_t Camera3OutputStream::returnBufferCheckedLocked(
- const camera3_stream_buffer &buffer,
+ const camera_stream_buffer &buffer,
nsecs_t timestamp,
bool output,
const std::vector<size_t>& surface_ids,
@@ -236,11 +243,11 @@
/**
* Return buffer back to ANativeWindow
*/
- if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR || mDropBuffers || timestamp == 0) {
+ if (buffer.status == CAMERA_BUFFER_STATUS_ERROR || mDropBuffers || timestamp == 0) {
// Cancel buffer
if (mDropBuffers) {
ALOGV("%s: Dropping a frame for stream %d.", __FUNCTION__, mId);
- } else if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
+ } else if (buffer.status == CAMERA_BUFFER_STATUS_ERROR) {
ALOGV("%s: A frame is dropped for stream %d due to buffer error.", __FUNCTION__, mId);
} else {
ALOGE("%s: Stream %d: timestamp shouldn't be 0", __FUNCTION__, mId);
@@ -260,7 +267,7 @@
mBufferProducerListener->onBufferReleased();
}
} else {
- if (mTraceFirstBuffer && (stream_type == CAMERA3_STREAM_OUTPUT)) {
+ if (mTraceFirstBuffer && (stream_type == CAMERA_STREAM_OUTPUT)) {
{
char traceLog[48];
snprintf(traceLog, sizeof(traceLog), "Stream %d: first full buffer\n", mId);
@@ -279,6 +286,12 @@
__FUNCTION__, mId, strerror(-res), res);
return res;
}
+ // If this is a JPEG output, and image dump mask is set, save image to
+ // disk.
+ if (getFormat() == HAL_PIXEL_FORMAT_BLOB && getDataSpace() == HAL_DATASPACE_V0_JFIF &&
+ mImageDumpMask) {
+ dumpImageToDisk(timestamp, anwBuffer, anwReleaseFence);
+ }
res = queueBufferToConsumer(currentConsumer, anwBuffer, anwReleaseFence, surface_ids);
if (shouldLogError(res, state)) {
@@ -290,7 +303,7 @@
// Once a valid buffer has been returned to the queue, can no longer
// dequeue all buffers for preallocation.
- if (buffer.status != CAMERA3_BUFFER_STATUS_ERROR) {
+ if (buffer.status != CAMERA_BUFFER_STATUS_ERROR) {
mStreamUnpreparable = true;
}
@@ -411,7 +424,7 @@
if (mMaxSize == 0) {
// For buffers of known size
res = native_window_set_buffers_dimensions(mConsumer.get(),
- camera3_stream::width, camera3_stream::height);
+ camera_stream::width, camera_stream::height);
} else {
// For buffers with bounded size
res = native_window_set_buffers_dimensions(mConsumer.get(),
@@ -420,23 +433,23 @@
if (res != OK) {
ALOGE("%s: Unable to configure stream buffer dimensions"
" %d x %d (maxSize %zu) for stream %d",
- __FUNCTION__, camera3_stream::width, camera3_stream::height,
+ __FUNCTION__, camera_stream::width, camera_stream::height,
mMaxSize, mId);
return res;
}
res = native_window_set_buffers_format(mConsumer.get(),
- camera3_stream::format);
+ camera_stream::format);
if (res != OK) {
ALOGE("%s: Unable to configure stream buffer format %#x for stream %d",
- __FUNCTION__, camera3_stream::format, mId);
+ __FUNCTION__, camera_stream::format, mId);
return res;
}
res = native_window_set_buffers_data_space(mConsumer.get(),
- camera3_stream::data_space);
+ camera_stream::data_space);
if (res != OK) {
ALOGE("%s: Unable to configure stream dataspace %#x for stream %d",
- __FUNCTION__, camera3_stream::data_space, mId);
+ __FUNCTION__, camera_stream::data_space, mId);
return res;
}
@@ -451,14 +464,14 @@
}
ALOGV("%s: Consumer wants %d buffers, HAL wants %d", __FUNCTION__,
- maxConsumerBuffers, camera3_stream::max_buffers);
- if (camera3_stream::max_buffers == 0) {
+ maxConsumerBuffers, camera_stream::max_buffers);
+ if (camera_stream::max_buffers == 0) {
ALOGE("%s: Camera HAL requested max_buffer count: %d, requires at least 1",
- __FUNCTION__, camera3_stream::max_buffers);
+ __FUNCTION__, camera_stream::max_buffers);
return INVALID_OPERATION;
}
- mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers;
+ mTotalBufferCount = maxConsumerBuffers + camera_stream::max_buffers;
mHandoutTotalBufferCount = 0;
mFrameCount = 0;
mLastTimestamp = 0;
@@ -750,7 +763,7 @@
uint64_t u = 0;
res = native_window_get_consumer_usage(static_cast<ANativeWindow*>(surface.get()), &u);
- applyZSLUsageQuirk(camera3_stream::format, &u);
+ applyZSLUsageQuirk(camera_stream::format, &u);
*usage = u;
return res;
}
@@ -957,6 +970,49 @@
return (usage & GRALLOC_USAGE_HW_TEXTURE) != 0;
}
+void Camera3OutputStream::dumpImageToDisk(nsecs_t timestamp,
+ ANativeWindowBuffer* anwBuffer, int fence) {
+ // Deriver output file name
+ std::string fileExtension = "jpg";
+ char imageFileName[64];
+ time_t now = time(0);
+ tm *localTime = localtime(&now);
+ snprintf(imageFileName, sizeof(imageFileName), "IMG_%4d%02d%02d_%02d%02d%02d_%" PRId64 ".%s",
+ 1900 + localTime->tm_year, localTime->tm_mon, localTime->tm_mday,
+ localTime->tm_hour, localTime->tm_min, localTime->tm_sec,
+ timestamp, fileExtension.c_str());
+
+ // Lock the image for CPU read
+ sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(anwBuffer);
+ void* mapped = nullptr;
+ base::unique_fd fenceFd(dup(fence));
+ status_t res = graphicBuffer->lockAsync(GraphicBuffer::USAGE_SW_READ_OFTEN, &mapped,
+ fenceFd.get());
+ if (res != OK) {
+ ALOGE("%s: Failed to lock the buffer: %s (%d)", __FUNCTION__, strerror(-res), res);
+ return;
+ }
+
+ // Figure out actual file size
+ auto actualJpegSize = android::camera2::JpegProcessor::findJpegSize((uint8_t*)mapped, mMaxSize);
+ if (actualJpegSize == 0) {
+ actualJpegSize = mMaxSize;
+ }
+
+ // Output image data to file
+ std::string filePath = "/data/misc/cameraserver/";
+ filePath += imageFileName;
+ std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
+ if (!imageFile.is_open()) {
+ ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
+ graphicBuffer->unlock();
+ return;
+ }
+ imageFile.write((const char*)mapped, actualJpegSize);
+
+ graphicBuffer->unlock();
+}
+
}; // namespace camera3
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index b4e49f9..f504171 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -81,7 +81,7 @@
*/
Camera3OutputStream(int id, sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
int setId = CAMERA3_STREAM_SET_ID_INVALID);
@@ -93,7 +93,7 @@
*/
Camera3OutputStream(int id, sp<Surface> consumer,
uint32_t width, uint32_t height, size_t maxSize, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
int setId = CAMERA3_STREAM_SET_ID_INVALID);
@@ -104,7 +104,7 @@
*/
Camera3OutputStream(int id, uint32_t width, uint32_t height, int format,
uint64_t consumerUsage, android_dataspace dataSpace,
- camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
+ camera_stream_rotation_t rotation, nsecs_t timestampOffset,
const String8& physicalCameraId,
int setId = CAMERA3_STREAM_SET_ID_INVALID);
@@ -210,10 +210,12 @@
*/
static void applyZSLUsageQuirk(int format, uint64_t *consumerUsage /*inout*/);
+ void setImageDumpMask(int mask) { mImageDumpMask = mask; }
+
protected:
- Camera3OutputStream(int id, camera3_stream_type_t type,
+ Camera3OutputStream(int id, camera_stream_type_t type,
uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
uint64_t consumerUsage = 0, nsecs_t timestampOffset = 0,
int setId = CAMERA3_STREAM_SET_ID_INVALID);
@@ -222,7 +224,7 @@
* Note that we release the lock briefly in this function
*/
virtual status_t returnBufferCheckedLocked(
- const camera3_stream_buffer &buffer,
+ const camera_stream_buffer &buffer,
nsecs_t timestamp,
bool output,
const std::vector<size_t>& surface_ids,
@@ -293,11 +295,11 @@
/**
* Internal Camera3Stream interface
*/
- virtual status_t getBufferLocked(camera3_stream_buffer *buffer,
+ virtual status_t getBufferLocked(camera_stream_buffer *buffer,
const std::vector<size_t>& surface_ids);
virtual status_t returnBufferLocked(
- const camera3_stream_buffer &buffer,
+ const camera_stream_buffer &buffer,
nsecs_t timestamp, const std::vector<size_t>& surface_ids);
virtual status_t queueBufferToConsumer(sp<ANativeWindow>& consumer,
@@ -325,9 +327,14 @@
// STATE_ABANDONED
static bool shouldLogError(status_t res, StreamState state);
+ // Dump images to disk before returning to consumer
+ void dumpImageToDisk(nsecs_t timestamp, ANativeWindowBuffer* anwBuffer, int fence);
+
static const int32_t kDequeueLatencyBinSize = 5; // in ms
CameraLatencyHistogram mDequeueBufferLatency;
+ int mImageDumpMask = 0;
+
}; // class Camera3OutputStream
} // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index f88b062..384c2c6 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -484,7 +484,7 @@
states.inflightIntf.checkInflightMapLengthLocked();
}
-void processCaptureResult(CaptureOutputStates& states, const camera3_capture_result *result) {
+void processCaptureResult(CaptureOutputStates& states, const camera_capture_result *result) {
ATRACE_CALL();
status_t res;
@@ -688,7 +688,7 @@
using hardware::camera::device::V3_2::BufferStatus;
std::unique_ptr<ResultMetadataQueue>& fmq = states.fmq;
BufferRecordsInterface& bufferRecords = states.bufferRecordsIntf;
- camera3_capture_result r;
+ camera_capture_result r;
status_t res;
r.frame_number = result.frameNumber;
@@ -727,7 +727,7 @@
r.physcam_ids = physCamIds.data();
r.physcam_metadata = phyCamMetadatas.data();
- std::vector<camera3_stream_buffer_t> outputBuffers(result.outputBuffers.size());
+ std::vector<camera_stream_buffer_t> outputBuffers(result.outputBuffers.size());
std::vector<buffer_handle_t> outputBufferHandles(result.outputBuffers.size());
for (size_t i = 0; i < result.outputBuffers.size(); i++) {
auto& bDst = outputBuffers[i];
@@ -788,7 +788,7 @@
r.num_output_buffers = outputBuffers.size();
r.output_buffers = outputBuffers.data();
- camera3_stream_buffer_t inputBuffer;
+ camera_stream_buffer_t inputBuffer;
if (result.inputBuffer.streamId == -1) {
r.input_buffer = nullptr;
} else {
@@ -829,7 +829,7 @@
void returnOutputBuffers(
bool useHalBufManager,
sp<NotificationListener> listener,
- const camera3_stream_buffer_t *outputBuffers, size_t numBuffers,
+ const camera_stream_buffer_t *outputBuffers, size_t numBuffers,
nsecs_t timestamp, bool requested, nsecs_t requestTimeNs,
SessionStatsBuilder& sessionStatsBuilder, bool timestampIncreasing,
const SurfaceMap& outputSurfaces,
@@ -842,7 +842,7 @@
int streamId = stream->getId();
// Call notify(ERROR_BUFFER) if necessary.
- if (outputBuffers[i].status == CAMERA3_BUFFER_STATUS_ERROR &&
+ if (outputBuffers[i].status == CAMERA_BUFFER_STATUS_ERROR &&
errorBufStrategy == ERROR_BUF_RETURN_NOTIFY) {
if (listener != nullptr) {
CaptureResultExtras extras = inResultExtras;
@@ -872,7 +872,7 @@
// Do not return the buffer if the buffer status is error, and the error
// buffer strategy is CACHE.
- if (outputBuffers[i].status != CAMERA3_BUFFER_STATUS_ERROR ||
+ if (outputBuffers[i].status != CAMERA_BUFFER_STATUS_ERROR ||
errorBufStrategy != ERROR_BUF_CACHE) {
if (it != outputSurfaces.end()) {
res = stream->returnBuffer(
@@ -894,7 +894,7 @@
ALOGE("Can't return buffer to its stream: %s (%d)", strerror(-res), res);
dropped = true;
} else {
- if (outputBuffers[i].status == CAMERA3_BUFFER_STATUS_ERROR || timestamp == 0) {
+ if (outputBuffers[i].status == CAMERA_BUFFER_STATUS_ERROR || timestamp == 0) {
dropped = true;
}
}
@@ -907,10 +907,10 @@
// Long processing consumers can cause returnBuffer timeout for shared stream
// If that happens, cancel the buffer and send a buffer error to client
if (it != outputSurfaces.end() && res == TIMED_OUT &&
- outputBuffers[i].status == CAMERA3_BUFFER_STATUS_OK) {
+ outputBuffers[i].status == CAMERA_BUFFER_STATUS_OK) {
// cancel the buffer
- camera3_stream_buffer_t sb = outputBuffers[i];
- sb.status = CAMERA3_BUFFER_STATUS_ERROR;
+ camera_stream_buffer_t sb = outputBuffers[i];
+ sb.status = CAMERA_BUFFER_STATUS_ERROR;
stream->returnBuffer(sb, /*timestamp*/0,
timestampIncreasing, std::vector<size_t> (),
inResultExtras.frameNumber);
@@ -942,7 +942,7 @@
for (auto iter = request.pendingOutputBuffers.begin();
iter != request.pendingOutputBuffers.end(); ) {
if (request.errorBufStrategy != ERROR_BUF_CACHE ||
- iter->status != CAMERA3_BUFFER_STATUS_ERROR) {
+ iter->status != CAMERA_BUFFER_STATUS_ERROR) {
iter = request.pendingOutputBuffers.erase(iter);
} else {
iter++;
@@ -950,7 +950,7 @@
}
}
-void notifyShutter(CaptureOutputStates& states, const camera3_shutter_msg_t &msg) {
+void notifyShutter(CaptureOutputStates& states, const camera_shutter_msg_t &msg) {
ATRACE_CALL();
ssize_t idx;
@@ -1028,26 +1028,26 @@
}
}
-void notifyError(CaptureOutputStates& states, const camera3_error_msg_t &msg) {
+void notifyError(CaptureOutputStates& states, const camera_error_msg_t &msg) {
ATRACE_CALL();
// Map camera HAL error codes to ICameraDeviceCallback error codes
// Index into this with the HAL error code
- static const int32_t halErrorMap[CAMERA3_MSG_NUM_ERRORS] = {
+ static const int32_t halErrorMap[CAMERA_MSG_NUM_ERRORS] = {
// 0 = Unused error code
hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR,
- // 1 = CAMERA3_MSG_ERROR_DEVICE
+ // 1 = CAMERA_MSG_ERROR_DEVICE
hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
- // 2 = CAMERA3_MSG_ERROR_REQUEST
+ // 2 = CAMERA_MSG_ERROR_REQUEST
hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
- // 3 = CAMERA3_MSG_ERROR_RESULT
+ // 3 = CAMERA_MSG_ERROR_RESULT
hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT,
- // 4 = CAMERA3_MSG_ERROR_BUFFER
+ // 4 = CAMERA_MSG_ERROR_BUFFER
hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER
};
int32_t errorCode =
((msg.error_code >= 0) &&
- (msg.error_code < CAMERA3_MSG_NUM_ERRORS)) ?
+ (msg.error_code < CAMERA_MSG_NUM_ERRORS)) ?
halErrorMap[msg.error_code] :
hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR;
@@ -1136,13 +1136,13 @@
}
}
-void notify(CaptureOutputStates& states, const camera3_notify_msg *msg) {
+void notify(CaptureOutputStates& states, const camera_notify_msg *msg) {
switch (msg->type) {
- case CAMERA3_MSG_ERROR: {
+ case CAMERA_MSG_ERROR: {
notifyError(states, msg->message.error);
break;
}
- case CAMERA3_MSG_SHUTTER: {
+ case CAMERA_MSG_SHUTTER: {
notifyShutter(states, msg->message.shutter);
break;
}
@@ -1158,10 +1158,10 @@
using android::hardware::camera::device::V3_2::ErrorCode;
ATRACE_CALL();
- camera3_notify_msg m;
+ camera_notify_msg m;
switch (msg.type) {
case MsgType::ERROR:
- m.type = CAMERA3_MSG_ERROR;
+ m.type = CAMERA_MSG_ERROR;
m.message.error.frame_number = msg.msg.error.frameNumber;
if (msg.msg.error.errorStreamId >= 0) {
sp<Camera3StreamInterface> stream =
@@ -1177,21 +1177,21 @@
}
switch (msg.msg.error.errorCode) {
case ErrorCode::ERROR_DEVICE:
- m.message.error.error_code = CAMERA3_MSG_ERROR_DEVICE;
+ m.message.error.error_code = CAMERA_MSG_ERROR_DEVICE;
break;
case ErrorCode::ERROR_REQUEST:
- m.message.error.error_code = CAMERA3_MSG_ERROR_REQUEST;
+ m.message.error.error_code = CAMERA_MSG_ERROR_REQUEST;
break;
case ErrorCode::ERROR_RESULT:
- m.message.error.error_code = CAMERA3_MSG_ERROR_RESULT;
+ m.message.error.error_code = CAMERA_MSG_ERROR_RESULT;
break;
case ErrorCode::ERROR_BUFFER:
- m.message.error.error_code = CAMERA3_MSG_ERROR_BUFFER;
+ m.message.error.error_code = CAMERA_MSG_ERROR_BUFFER;
break;
}
break;
case MsgType::SHUTTER:
- m.type = CAMERA3_MSG_SHUTTER;
+ m.type = CAMERA_MSG_SHUTTER;
m.message.shutter.frame_number = msg.msg.shutter.frameNumber;
m.message.shutter.timestamp = msg.msg.shutter.timestamp;
break;
@@ -1292,11 +1292,11 @@
hardware::hidl_vec<StreamBuffer> tmpRetBuffers(numBuffersRequested);
bool currentReqSucceeds = true;
- std::vector<camera3_stream_buffer_t> streamBuffers(numBuffersRequested);
+ std::vector<camera_stream_buffer_t> streamBuffers(numBuffersRequested);
size_t numAllocatedBuffers = 0;
size_t numPushedInflightBuffers = 0;
for (size_t b = 0; b < numBuffersRequested; b++) {
- camera3_stream_buffer_t& sb = streamBuffers[b];
+ camera_stream_buffer_t& sb = streamBuffers[b];
// Since this method can run concurrently with request thread
// We need to update the wait duration everytime we call getbuffer
nsecs_t waitDuration = states.reqBufferIntf.getWaitDuration();
@@ -1367,9 +1367,9 @@
}
}
for (size_t b = 0; b < numAllocatedBuffers; b++) {
- camera3_stream_buffer_t& sb = streamBuffers[b];
+ camera_stream_buffer_t& sb = streamBuffers[b];
sb.acquire_fence = -1;
- sb.status = CAMERA3_BUFFER_STATUS_ERROR;
+ sb.status = CAMERA_BUFFER_STATUS_ERROR;
}
returnOutputBuffers(states.useHalBufManager, /*listener*/nullptr,
streamBuffers.data(), numAllocatedBuffers, 0, /*requested*/false,
@@ -1407,9 +1407,9 @@
continue;
}
- camera3_stream_buffer_t streamBuffer;
+ camera_stream_buffer_t streamBuffer;
streamBuffer.buffer = buffer;
- streamBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+ streamBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
streamBuffer.acquire_fence = -1;
streamBuffer.release_fence = -1;
@@ -1504,19 +1504,19 @@
int32_t frameNumber = std::get<1>(tuple);
buffer_handle_t* buffer = std::get<2>(tuple);
- camera3_stream_buffer_t streamBuffer;
+ camera_stream_buffer_t streamBuffer;
streamBuffer.buffer = buffer;
- streamBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+ streamBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
streamBuffer.acquire_fence = -1;
streamBuffer.release_fence = -1;
for (auto& stream : streams) {
if (streamId == stream->getId()) {
// Return buffer to deleted stream
- camera3_stream* halStream = stream->asHalStream();
+ camera_stream* halStream = stream->asHalStream();
streamBuffer.stream = halStream;
switch (halStream->stream_type) {
- case CAMERA3_STREAM_OUTPUT:
+ case CAMERA_STREAM_OUTPUT:
res = stream->returnBuffer(streamBuffer, /*timestamp*/ 0,
/*timestampIncreasing*/true,
std::vector<size_t> (), frameNumber);
@@ -1526,7 +1526,7 @@
frameNumber, streamId, strerror(-res), res);
}
break;
- case CAMERA3_STREAM_INPUT:
+ case CAMERA_STREAM_INPUT:
res = stream->returnInputBuffer(streamBuffer);
if (res != OK) {
ALOGE("%s: Can't return input buffer for frame %d to"
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.h b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
index 45c8a43..772fe6e 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
@@ -42,6 +42,63 @@
namespace camera3 {
+ typedef struct camera_stream_configuration {
+ uint32_t num_streams;
+ camera_stream_t **streams;
+ uint32_t operation_mode;
+ } camera_stream_configuration_t;
+
+ typedef struct camera_capture_request {
+ uint32_t frame_number;
+ const camera_metadata_t *settings;
+ camera_stream_buffer_t *input_buffer;
+ uint32_t num_output_buffers;
+ const camera_stream_buffer_t *output_buffers;
+ uint32_t num_physcam_settings;
+ const char **physcam_id;
+ const camera_metadata_t **physcam_settings;
+ } camera_capture_request_t;
+
+ typedef struct camera_capture_result {
+ uint32_t frame_number;
+ const camera_metadata_t *result;
+ uint32_t num_output_buffers;
+ const camera_stream_buffer_t *output_buffers;
+ const camera_stream_buffer_t *input_buffer;
+ uint32_t partial_result;
+ uint32_t num_physcam_metadata;
+ const char **physcam_ids;
+ const camera_metadata_t **physcam_metadata;
+ } camera_capture_result_t;
+
+ typedef struct camera_shutter_msg {
+ uint32_t frame_number;
+ uint64_t timestamp;
+ } camera_shutter_msg_t;
+
+ typedef struct camera_error_msg {
+ uint32_t frame_number;
+ camera_stream_t *error_stream;
+ int error_code;
+ } camera_error_msg_t;
+
+ typedef enum camera_error_msg_code {
+ CAMERA_MSG_ERROR_DEVICE = 1,
+ CAMERA_MSG_ERROR_REQUEST = 2,
+ CAMERA_MSG_ERROR_RESULT = 3,
+ CAMERA_MSG_ERROR_BUFFER = 4,
+ CAMERA_MSG_NUM_ERRORS
+ } camera_error_msg_code_t;
+
+ typedef struct camera_notify_msg {
+ int type;
+
+ union {
+ camera_error_msg_t error;
+ camera_shutter_msg_t shutter;
+ } message;
+ } camera_notify_msg_t;
+
/**
* Helper methods shared between Camera3Device/Camera3OfflineSession for HAL callbacks
*/
@@ -51,7 +108,7 @@
void returnOutputBuffers(
bool useHalBufManager,
sp<NotificationListener> listener, // Only needed when outputSurfaces is not empty
- const camera3_stream_buffer_t *outputBuffers,
+ const camera_stream_buffer_t *outputBuffers,
size_t numBuffers, nsecs_t timestamp, bool requested, nsecs_t requestTimeNs,
SessionStatsBuilder& sessionStatsBuilder, bool timestampIncreasing = true,
// The following arguments are only meant for surface sharing use case
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index 86b45cb..8aa5f1a 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -30,10 +30,10 @@
const std::vector<sp<Surface>>& surfaces,
uint32_t width, uint32_t height, int format,
uint64_t consumerUsage, android_dataspace dataSpace,
- camera3_stream_rotation_t rotation,
+ camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
int setId, bool useHalBufManager) :
- Camera3OutputStream(id, CAMERA3_STREAM_OUTPUT, width, height,
+ Camera3OutputStream(id, CAMERA_STREAM_OUTPUT, width, height,
format, dataSpace, rotation, physicalCameraId,
consumerUsage, timestampOffset, setId),
mUseHalBufManager(useHalBufManager) {
@@ -65,7 +65,7 @@
}
}
- res = mStreamSplitter->connect(initialSurfaces, usage, mUsage, camera3_stream::max_buffers,
+ res = mStreamSplitter->connect(initialSurfaces, usage, mUsage, camera_stream::max_buffers,
getWidth(), getHeight(), getFormat(), &mConsumer);
if (res != OK) {
ALOGE("%s: Failed to connect to stream splitter: %s(%d)",
@@ -157,7 +157,7 @@
return ret;
}
-status_t Camera3SharedOutputStream::getBufferLocked(camera3_stream_buffer *buffer,
+status_t Camera3SharedOutputStream::getBufferLocked(camera_stream_buffer *buffer,
const std::vector<size_t>& surfaceIds) {
ANativeWindowBuffer* anb;
int fenceFd = -1;
@@ -180,7 +180,7 @@
* in which case we reassign it to acquire_fence
*/
handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
- /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/true);
+ /*releaseFence*/-1, CAMERA_BUFFER_STATUS_OK, /*output*/true);
return OK;
}
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index e645e05..a61316c 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -36,7 +36,7 @@
Camera3SharedOutputStream(int id, const std::vector<sp<Surface>>& surfaces,
uint32_t width, uint32_t height, int format,
uint64_t consumerUsage, android_dataspace dataSpace,
- camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
+ camera_stream_rotation_t rotation, nsecs_t timestampOffset,
const String8& physicalCameraId,
int setId = CAMERA3_STREAM_SET_ID_INVALID,
bool useHalBufManager = false);
@@ -116,7 +116,7 @@
/**
* Internal Camera3Stream interface
*/
- virtual status_t getBufferLocked(camera3_stream_buffer *buffer,
+ virtual status_t getBufferLocked(camera_stream_buffer *buffer,
const std::vector<size_t>& surface_ids);
virtual status_t queueBufferToConsumer(sp<ANativeWindow>& consumer,
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 9a8f6fe..8d72b4c 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -37,20 +37,20 @@
}
}
-Camera3Stream* Camera3Stream::cast(camera3_stream *stream) {
+Camera3Stream* Camera3Stream::cast(camera_stream *stream) {
return static_cast<Camera3Stream*>(stream);
}
-const Camera3Stream* Camera3Stream::cast(const camera3_stream *stream) {
+const Camera3Stream* Camera3Stream::cast(const camera_stream *stream) {
return static_cast<const Camera3Stream*>(stream);
}
Camera3Stream::Camera3Stream(int id,
- camera3_stream_type type,
+ camera_stream_type type,
uint32_t width, uint32_t height, size_t maxSize, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId, int setId) :
- camera3_stream(),
+ camera_stream(),
mId(id),
mSetId(setId),
mName(String8::format("Camera3Stream[%d]", id)),
@@ -75,15 +75,14 @@
mPhysicalCameraId(physicalCameraId),
mLastTimestamp(0) {
- camera3_stream::stream_type = type;
- camera3_stream::width = width;
- camera3_stream::height = height;
- camera3_stream::format = format;
- camera3_stream::data_space = dataSpace;
- camera3_stream::rotation = rotation;
- camera3_stream::max_buffers = 0;
- camera3_stream::priv = NULL;
- camera3_stream::physical_camera_id = mPhysicalCameraId.string();
+ camera_stream::stream_type = type;
+ camera_stream::width = width;
+ camera_stream::height = height;
+ camera_stream::format = format;
+ camera_stream::data_space = dataSpace;
+ camera_stream::rotation = rotation;
+ camera_stream::max_buffers = 0;
+ camera_stream::physical_camera_id = mPhysicalCameraId.string();
if ((format == HAL_PIXEL_FORMAT_BLOB || format == HAL_PIXEL_FORMAT_RAW_OPAQUE) &&
maxSize == 0) {
@@ -101,19 +100,19 @@
}
uint32_t Camera3Stream::getWidth() const {
- return camera3_stream::width;
+ return camera_stream::width;
}
uint32_t Camera3Stream::getHeight() const {
- return camera3_stream::height;
+ return camera_stream::height;
}
int Camera3Stream::getFormat() const {
- return camera3_stream::format;
+ return camera_stream::format;
}
android_dataspace Camera3Stream::getDataSpace() const {
- return camera3_stream::data_space;
+ return camera_stream::data_space;
}
uint64_t Camera3Stream::getUsage() const {
@@ -153,7 +152,7 @@
}
int Camera3Stream::getMaxHalBuffers() const {
- return camera3_stream::max_buffers;
+ return camera_stream::max_buffers;
}
void Camera3Stream::setOfflineProcessingSupport(bool support) {
@@ -233,7 +232,7 @@
return res;
}
-camera3_stream* Camera3Stream::startConfiguration() {
+camera_stream* Camera3Stream::startConfiguration() {
ATRACE_CALL();
Mutex::Autolock l(mLock);
status_t res;
@@ -264,9 +263,9 @@
}
mOldUsage = mUsage;
- mOldMaxBuffers = camera3_stream::max_buffers;
- mOldFormat = camera3_stream::format;
- mOldDataSpace = camera3_stream::data_space;
+ mOldMaxBuffers = camera_stream::max_buffers;
+ mOldFormat = camera_stream::format;
+ mOldDataSpace = camera_stream::data_space;
res = getEndpointUsage(&mUsage);
if (res != OK) {
@@ -339,12 +338,12 @@
}
// Check if the stream configuration is unchanged, and skip reallocation if
- // so. As documented in hardware/camera3.h:configure_streams().
+ // so.
if (mState == STATE_IN_RECONFIG &&
mOldUsage == mUsage &&
- mOldMaxBuffers == camera3_stream::max_buffers &&
- mOldDataSpace == camera3_stream::data_space &&
- mOldFormat == camera3_stream::format) {
+ mOldMaxBuffers == camera_stream::max_buffers &&
+ mOldDataSpace == camera_stream::data_space &&
+ mOldFormat == camera_stream::format) {
mState = STATE_CONFIGURED;
return OK;
}
@@ -403,7 +402,7 @@
}
mUsage = mOldUsage;
- camera3_stream::max_buffers = mOldMaxBuffers;
+ camera_stream::max_buffers = mOldMaxBuffers;
mState = ((mState == STATE_IN_RECONFIG) || (mState == STATE_IN_IDLE)) ? STATE_CONFIGURED :
STATE_CONSTRUCTED;
@@ -463,7 +462,7 @@
mLastMaxCount = bufferCount;
- mPreparedBuffers.insertAt(camera3_stream_buffer_t(), /*index*/0, bufferCount);
+ mPreparedBuffers.insertAt(camera_stream_buffer_t(), /*index*/0, bufferCount);
mPreparedBufferIdx = 0;
mState = STATE_PREPARING;
@@ -538,7 +537,7 @@
// they weren't filled.
for (size_t i = 0; i < mPreparedBufferIdx; i++) {
mPreparedBuffers.editItemAt(i).release_fence = -1;
- mPreparedBuffers.editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
+ mPreparedBuffers.editItemAt(i).status = CAMERA_BUFFER_STATUS_ERROR;
returnBufferLocked(mPreparedBuffers[i], 0);
}
mPreparedBuffers.clear();
@@ -604,7 +603,7 @@
return OK;
}
-status_t Camera3Stream::getBuffer(camera3_stream_buffer *buffer,
+status_t Camera3Stream::getBuffer(camera_stream_buffer *buffer,
nsecs_t waitBufferTimeout,
const std::vector<size_t>& surface_ids) {
ATRACE_HFR_CALL();
@@ -623,9 +622,9 @@
}
// Wait for new buffer returned back if we are running into the limit.
- if (getHandoutOutputBufferCountLocked() == camera3_stream::max_buffers) {
+ if (getHandoutOutputBufferCountLocked() == camera_stream::max_buffers) {
ALOGV("%s: Already dequeued max output buffers (%d), wait for next returned one.",
- __FUNCTION__, camera3_stream::max_buffers);
+ __FUNCTION__, camera_stream::max_buffers);
nsecs_t waitStart = systemTime(SYSTEM_TIME_MONOTONIC);
if (waitBufferTimeout < kWaitForBufferDuration) {
waitBufferTimeout = kWaitForBufferDuration;
@@ -637,7 +636,7 @@
if (res == TIMED_OUT) {
ALOGE("%s: wait for output buffer return timed out after %lldms (max_buffers %d)",
__FUNCTION__, waitBufferTimeout / 1000000LL,
- camera3_stream::max_buffers);
+ camera_stream::max_buffers);
}
return res;
}
@@ -655,7 +654,7 @@
return res;
}
-bool Camera3Stream::isOutstandingBuffer(const camera3_stream_buffer &buffer) const{
+bool Camera3Stream::isOutstandingBuffer(const camera_stream_buffer &buffer) const{
if (buffer.buffer == nullptr) {
return false;
}
@@ -670,7 +669,7 @@
return false;
}
-void Camera3Stream::removeOutstandingBuffer(const camera3_stream_buffer &buffer) {
+void Camera3Stream::removeOutstandingBuffer(const camera_stream_buffer &buffer) {
if (buffer.buffer == nullptr) {
return;
}
@@ -685,7 +684,7 @@
}
}
-status_t Camera3Stream::returnBuffer(const camera3_stream_buffer &buffer,
+status_t Camera3Stream::returnBuffer(const camera_stream_buffer &buffer,
nsecs_t timestamp, bool timestampIncreasing,
const std::vector<size_t>& surface_ids, uint64_t frameNumber) {
ATRACE_HFR_CALL();
@@ -700,11 +699,11 @@
removeOutstandingBuffer(buffer);
// Buffer status may be changed, so make a copy of the stream_buffer struct.
- camera3_stream_buffer b = buffer;
+ camera_stream_buffer b = buffer;
if (timestampIncreasing && timestamp != 0 && timestamp <= mLastTimestamp) {
ALOGE("%s: Stream %d: timestamp %" PRId64 " is not increasing. Prev timestamp %" PRId64,
__FUNCTION__, mId, timestamp, mLastTimestamp);
- b.status = CAMERA3_BUFFER_STATUS_ERROR;
+ b.status = CAMERA_BUFFER_STATUS_ERROR;
}
mLastTimestamp = timestamp;
@@ -728,7 +727,7 @@
return res;
}
-status_t Camera3Stream::getInputBuffer(camera3_stream_buffer *buffer, bool respectHalLimit) {
+status_t Camera3Stream::getInputBuffer(camera_stream_buffer *buffer, bool respectHalLimit) {
ATRACE_CALL();
Mutex::Autolock l(mLock);
status_t res = OK;
@@ -741,9 +740,9 @@
}
// Wait for new buffer returned back if we are running into the limit.
- if (getHandoutInputBufferCountLocked() == camera3_stream::max_buffers && respectHalLimit) {
+ if (getHandoutInputBufferCountLocked() == camera_stream::max_buffers && respectHalLimit) {
ALOGV("%s: Already dequeued max input buffers (%d), wait for next returned one.",
- __FUNCTION__, camera3_stream::max_buffers);
+ __FUNCTION__, camera_stream::max_buffers);
res = mInputBufferReturnedSignal.waitRelative(mLock, kWaitForBufferDuration);
if (res != OK) {
if (res == TIMED_OUT) {
@@ -766,7 +765,7 @@
return res;
}
-status_t Camera3Stream::returnInputBuffer(const camera3_stream_buffer &buffer) {
+status_t Camera3Stream::returnInputBuffer(const camera_stream_buffer &buffer) {
ATRACE_CALL();
Mutex::Autolock l(mLock);
@@ -808,7 +807,7 @@
}
void Camera3Stream::fireBufferListenersLocked(
- const camera3_stream_buffer& buffer, bool acquired, bool output, nsecs_t timestamp,
+ const camera_stream_buffer& buffer, bool acquired, bool output, nsecs_t timestamp,
uint64_t frameNumber) {
List<wp<Camera3StreamBufferListener> >::iterator it, end;
@@ -817,7 +816,7 @@
Camera3StreamBufferListener::BufferInfo info =
Camera3StreamBufferListener::BufferInfo();
info.mOutput = output;
- info.mError = (buffer.status == CAMERA3_BUFFER_STATUS_ERROR);
+ info.mError = (buffer.status == CAMERA_BUFFER_STATUS_ERROR);
info.mFrameNumber = frameNumber;
info.mTimestamp = timestamp;
info.mStreamId = getId();
@@ -887,22 +886,22 @@
" Latency histogram for wait on max_buffers");
}
-status_t Camera3Stream::getBufferLocked(camera3_stream_buffer *,
+status_t Camera3Stream::getBufferLocked(camera_stream_buffer *,
const std::vector<size_t>&) {
ALOGE("%s: This type of stream does not support output", __FUNCTION__);
return INVALID_OPERATION;
}
-status_t Camera3Stream::returnBufferLocked(const camera3_stream_buffer &,
+status_t Camera3Stream::returnBufferLocked(const camera_stream_buffer &,
nsecs_t, const std::vector<size_t>&) {
ALOGE("%s: This type of stream does not support output", __FUNCTION__);
return INVALID_OPERATION;
}
-status_t Camera3Stream::getInputBufferLocked(camera3_stream_buffer *) {
+status_t Camera3Stream::getInputBufferLocked(camera_stream_buffer *) {
ALOGE("%s: This type of stream does not support input", __FUNCTION__);
return INVALID_OPERATION;
}
status_t Camera3Stream::returnInputBufferLocked(
- const camera3_stream_buffer &) {
+ const camera_stream_buffer &) {
ALOGE("%s: This type of stream does not support input", __FUNCTION__);
return INVALID_OPERATION;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 3654f89..47dc252 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -23,8 +23,6 @@
#include <utils/String16.h>
#include <utils/List.h>
-#include "hardware/camera3.h"
-
#include "utils/LatencyHistogram.h"
#include "Camera3StreamBufferListener.h"
#include "Camera3StreamInterface.h"
@@ -50,7 +48,7 @@
* with the HAL.
*
* STATE_IN_CONFIG: Configuration has started, but not yet concluded. During this
- * time, the usage, max_buffers, and priv fields of camera3_stream returned by
+ * time, the usage, max_buffers, and priv fields of camera_stream returned by
* startConfiguration() may be modified.
*
* STATE_IN_RE_CONFIG: Configuration has started, and the stream has been
@@ -130,15 +128,15 @@
*
*/
class Camera3Stream :
- protected camera3_stream,
+ protected camera_stream,
public virtual Camera3StreamInterface,
public virtual RefBase {
public:
virtual ~Camera3Stream();
- static Camera3Stream* cast(camera3_stream *stream);
- static const Camera3Stream* cast(const camera3_stream *stream);
+ static Camera3Stream* cast(camera_stream *stream);
+ static const Camera3Stream* cast(const camera_stream *stream);
/**
* Get the stream's ID
@@ -171,7 +169,7 @@
void setOfflineProcessingSupport(bool) override;
bool getOfflineProcessingSupport() const override;
- camera3_stream* asHalStream() override {
+ camera_stream* asHalStream() override {
return this;
}
@@ -180,14 +178,12 @@
* information to be passed into the HAL device's configure_streams call.
*
* Until finishConfiguration() is called, no other methods on the stream may be
- * called. The usage and max_buffers fields of camera3_stream may be modified
+ * called. The usage and max_buffers fields of camera_stream may be modified
* between start/finishConfiguration, but may not be changed after that.
- * The priv field of camera3_stream may be modified at any time after
- * startConfiguration.
*
* Returns NULL in case of error starting configuration.
*/
- camera3_stream* startConfiguration();
+ camera_stream* startConfiguration();
/**
* Check if the stream is mid-configuration (start has been called, but not
@@ -308,7 +304,7 @@
status_t tearDown();
/**
- * Fill in the camera3_stream_buffer with the next valid buffer for this
+ * Fill in the camera_stream_buffer with the next valid buffer for this
* stream, to hand over to the HAL.
*
* Multiple surfaces could share the same HAL stream, but a request may
@@ -321,7 +317,7 @@
* buffers.
*
*/
- status_t getBuffer(camera3_stream_buffer *buffer,
+ status_t getBuffer(camera_stream_buffer *buffer,
nsecs_t waitBufferTimeout,
const std::vector<size_t>& surface_ids = std::vector<size_t>());
@@ -336,13 +332,13 @@
* This method may only be called for buffers provided by getBuffer().
* For bidirectional streams, this method applies to the output-side buffers
*/
- status_t returnBuffer(const camera3_stream_buffer &buffer,
+ status_t returnBuffer(const camera_stream_buffer &buffer,
nsecs_t timestamp, bool timestampIncreasing,
const std::vector<size_t>& surface_ids = std::vector<size_t>(),
uint64_t frameNumber = 0);
/**
- * Fill in the camera3_stream_buffer with the next valid buffer for this
+ * Fill in the camera_stream_buffer with the next valid buffer for this
* stream, to hand over to the HAL.
*
* This method may only be called once finishConfiguration has been called.
@@ -352,7 +348,7 @@
* Normally this call will block until the handed out buffer count is less than the stream
* max buffer count; if respectHalLimit is set to false, this is ignored.
*/
- status_t getInputBuffer(camera3_stream_buffer *buffer, bool respectHalLimit = true);
+ status_t getInputBuffer(camera_stream_buffer *buffer, bool respectHalLimit = true);
/**
* Return a buffer to the stream after use by the HAL.
@@ -360,7 +356,7 @@
* This method may only be called for buffers provided by getBuffer().
* For bidirectional streams, this method applies to the input-side buffers
*/
- status_t returnInputBuffer(const camera3_stream_buffer &buffer);
+ status_t returnInputBuffer(const camera_stream_buffer &buffer);
// get the buffer producer of the input buffer queue.
// only apply to input streams.
@@ -477,9 +473,9 @@
mutable Mutex mLock;
- Camera3Stream(int id, camera3_stream_type type,
+ Camera3Stream(int id, camera_stream_type type,
uint32_t width, uint32_t height, size_t maxSize, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId, int setId);
wp<Camera3StreamBufferFreedListener> mBufferFreedListener;
@@ -490,18 +486,18 @@
// getBuffer / returnBuffer implementations
- // Since camera3_stream_buffer includes a raw pointer to the stream,
- // cast to camera3_stream*, implementations must increment the
+ // Since camera_stream_buffer includes a raw pointer to the stream,
+ // cast to camera_stream*, implementations must increment the
// refcount of the stream manually in getBufferLocked, and decrement it in
// returnBufferLocked.
- virtual status_t getBufferLocked(camera3_stream_buffer *buffer,
+ virtual status_t getBufferLocked(camera_stream_buffer *buffer,
const std::vector<size_t>& surface_ids = std::vector<size_t>());
- virtual status_t returnBufferLocked(const camera3_stream_buffer &buffer,
+ virtual status_t returnBufferLocked(const camera_stream_buffer &buffer,
nsecs_t timestamp,
const std::vector<size_t>& surface_ids = std::vector<size_t>());
- virtual status_t getInputBufferLocked(camera3_stream_buffer *buffer);
+ virtual status_t getInputBufferLocked(camera_stream_buffer *buffer);
virtual status_t returnInputBufferLocked(
- const camera3_stream_buffer &buffer);
+ const camera_stream_buffer &buffer);
virtual bool hasOutstandingBuffersLocked() const = 0;
// Get the buffer producer of the input buffer queue. Only apply to input streams.
virtual status_t getInputBufferProducerLocked(sp<IGraphicBufferProducer> *producer);
@@ -530,7 +526,7 @@
virtual status_t getEndpointUsage(uint64_t *usage) const = 0;
// Return whether the buffer is in the list of outstanding buffers.
- bool isOutstandingBuffer(const camera3_stream_buffer& buffer) const;
+ bool isOutstandingBuffer(const camera_stream_buffer& buffer) const;
// Tracking for idle state
wp<StatusTracker> mStatusTracker;
@@ -554,14 +550,14 @@
Condition mInputBufferReturnedSignal;
static const nsecs_t kWaitForBufferDuration = 3000000000LL; // 3000 ms
- void fireBufferListenersLocked(const camera3_stream_buffer& buffer,
+ void fireBufferListenersLocked(const camera_stream_buffer& buffer,
bool acquired, bool output, nsecs_t timestamp = 0, uint64_t frameNumber = 0);
List<wp<Camera3StreamBufferListener> > mBufferListenerList;
status_t cancelPrepareLocked();
// Remove the buffer from the list of outstanding buffers.
- void removeOutstandingBuffer(const camera3_stream_buffer& buffer);
+ void removeOutstandingBuffer(const camera_stream_buffer& buffer);
// Tracking for PREPARING state
@@ -571,7 +567,7 @@
bool mPrepared;
bool mPrepareBlockRequest;
- Vector<camera3_stream_buffer_t> mPreparedBuffers;
+ Vector<camera_stream_buffer_t> mPreparedBuffers;
size_t mPreparedBufferIdx;
// Number of buffers allocated on last prepare call.
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index a053262..b48636e 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -23,13 +23,55 @@
#include "Camera3StreamBufferListener.h"
#include "Camera3StreamBufferFreedListener.h"
-struct camera3_stream;
-struct camera3_stream_buffer;
-
namespace android {
namespace camera3 {
+typedef enum camera_buffer_status {
+ CAMERA_BUFFER_STATUS_OK = 0,
+ CAMERA_BUFFER_STATUS_ERROR = 1
+} camera_buffer_status_t;
+
+typedef enum camera_stream_type {
+ CAMERA_STREAM_OUTPUT = 0,
+ CAMERA_STREAM_INPUT = 1,
+ CAMERA_NUM_STREAM_TYPES
+} camera_stream_type_t;
+
+typedef enum camera_stream_rotation {
+ /* No rotation */
+ CAMERA_STREAM_ROTATION_0 = 0,
+
+ /* Rotate by 90 degree counterclockwise */
+ CAMERA_STREAM_ROTATION_90 = 1,
+
+ /* Rotate by 180 degree counterclockwise */
+ CAMERA_STREAM_ROTATION_180 = 2,
+
+ /* Rotate by 270 degree counterclockwise */
+ CAMERA_STREAM_ROTATION_270 = 3
+} camera_stream_rotation_t;
+
+typedef struct camera_stream {
+ camera_stream_type_t stream_type;
+ uint32_t width;
+ uint32_t height;
+ int format;
+ uint32_t usage;
+ uint32_t max_buffers;
+ android_dataspace_t data_space;
+ camera_stream_rotation_t rotation;
+ const char* physical_camera_id;
+} camera_stream_t;
+
+typedef struct camera_stream_buffer {
+ camera_stream_t *stream;
+ buffer_handle_t *buffer;
+ camera_buffer_status_t status;
+ int acquire_fence;
+ int release_fence;
+} camera_stream_buffer_t;
+
enum {
/**
* This stream set ID indicates that the set ID is invalid, and this stream doesn't intend to
@@ -109,23 +151,23 @@
virtual bool getOfflineProcessingSupport() const = 0;
/**
- * Get a HAL3 handle for the stream, without starting stream configuration.
+ * Get a handle for the stream, without starting stream configuration.
*/
- virtual camera3_stream* asHalStream() = 0;
+ virtual camera_stream* asHalStream() = 0;
/**
* Start the stream configuration process. Returns a handle to the stream's
- * information to be passed into the HAL device's configure_streams call.
+ * information to be passed into the device's configure_streams call.
*
* Until finishConfiguration() is called, no other methods on the stream may
- * be called. The usage and max_buffers fields of camera3_stream may be
+ * be called. The usage and max_buffers fields of camera_stream may be
* modified between start/finishConfiguration, but may not be changed after
- * that. The priv field of camera3_stream may be modified at any time after
+ * that. The priv field of camera_stream may be modified at any time after
* startConfiguration.
*
* Returns NULL in case of error starting configuration.
*/
- virtual camera3_stream* startConfiguration() = 0;
+ virtual camera_stream* startConfiguration() = 0;
/**
* Check if the stream is mid-configuration (start has been called, but not
@@ -241,7 +283,7 @@
virtual status_t tearDown() = 0;
/**
- * Fill in the camera3_stream_buffer with the next valid buffer for this
+ * Fill in the camera_stream_buffer with the next valid buffer for this
* stream, to hand over to the HAL.
*
* Multiple surfaces could share the same HAL stream, but a request may
@@ -255,7 +297,7 @@
* buffers.
*
*/
- virtual status_t getBuffer(camera3_stream_buffer *buffer,
+ virtual status_t getBuffer(camera_stream_buffer *buffer,
nsecs_t waitBufferTimeout,
const std::vector<size_t>& surface_ids = std::vector<size_t>()) = 0;
@@ -271,13 +313,13 @@
* This method may only be called for buffers provided by getBuffer().
* For bidirectional streams, this method applies to the output-side buffers
*/
- virtual status_t returnBuffer(const camera3_stream_buffer &buffer,
+ virtual status_t returnBuffer(const camera_stream_buffer &buffer,
nsecs_t timestamp, bool timestampIncreasing = true,
const std::vector<size_t>& surface_ids = std::vector<size_t>(),
uint64_t frameNumber = 0) = 0;
/**
- * Fill in the camera3_stream_buffer with the next valid buffer for this
+ * Fill in the camera_stream_buffer with the next valid buffer for this
* stream, to hand over to the HAL.
*
* This method may only be called once finishConfiguration has been called.
@@ -287,7 +329,7 @@
* Normally this call will block until the handed out buffer count is less than the stream
* max buffer count; if respectHalLimit is set to false, this is ignored.
*/
- virtual status_t getInputBuffer(camera3_stream_buffer *buffer, bool respectHalLimit = true) = 0;
+ virtual status_t getInputBuffer(camera_stream_buffer *buffer, bool respectHalLimit = true) = 0;
/**
* Return a buffer to the stream after use by the HAL.
@@ -295,7 +337,7 @@
* This method may only be called for buffers provided by getBuffer().
* For bidirectional streams, this method applies to the input-side buffers
*/
- virtual status_t returnInputBuffer(const camera3_stream_buffer &buffer) = 0;
+ virtual status_t returnInputBuffer(const camera_stream_buffer &buffer) = 0;
/**
* Get the buffer producer of the input buffer queue.
diff --git a/services/camera/libcameraservice/device3/InFlightRequest.h b/services/camera/libcameraservice/device3/InFlightRequest.h
index c7b7475..e3aaf44 100644
--- a/services/camera/libcameraservice/device3/InFlightRequest.h
+++ b/services/camera/libcameraservice/device3/InFlightRequest.h
@@ -24,8 +24,6 @@
#include <utils/String8.h>
#include <utils/Timers.h>
-#include "hardware/camera3.h"
-
#include "common/CameraDeviceBase.h"
namespace android {
@@ -75,7 +73,7 @@
// return from HAL but framework has not yet received the shutter
// event. They will be returned to the streams when framework receives
// the shutter event.
- Vector<camera3_stream_buffer_t> pendingOutputBuffers;
+ Vector<camera_stream_buffer_t> pendingOutputBuffers;
// Whether this inflight request's shutter and result callback are to be
// called. The policy is that if the request is the last one in the constrained
diff --git a/services/camera/libcameraservice/device3/StatusTracker.h b/services/camera/libcameraservice/device3/StatusTracker.h
index 3741cce..069bff6 100644
--- a/services/camera/libcameraservice/device3/StatusTracker.h
+++ b/services/camera/libcameraservice/device3/StatusTracker.h
@@ -24,7 +24,6 @@
#include <utils/Mutex.h>
#include <utils/Thread.h>
#include <utils/KeyedVector.h>
-#include <hardware/camera3.h>
#include "common/CameraDeviceBase.h"
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
index 81d7bf9..1bc2081 100644
--- a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
@@ -168,6 +168,19 @@
entry = request->find(ANDROID_CONTROL_ZOOM_RATIO);
if (entry.count == 1 && entry.data.f[0] != 1.0f) {
zoomRatioIs1 = false;
+
+ // If cropRegion is windowboxing, override it with activeArray
+ camera_metadata_entry_t cropRegionEntry = request->find(ANDROID_SCALER_CROP_REGION);
+ if (cropRegionEntry.count == 4) {
+ int cropWidth = cropRegionEntry.data.i32[2];
+ int cropHeight = cropRegionEntry.data.i32[3];
+ if (cropWidth < mArrayWidth && cropHeight < mArrayHeight) {
+ cropRegionEntry.data.i32[0] = 0;
+ cropRegionEntry.data.i32[1] = 0;
+ cropRegionEntry.data.i32[2] = mArrayWidth;
+ cropRegionEntry.data.i32[3] = mArrayHeight;
+ }
+ }
}
if (mHalSupportsZoomRatio && zoomRatioIs1) {
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index ba68a63..c28f427 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -261,7 +261,7 @@
void SessionConfigurationUtils::mapStreamInfo(const OutputStreamInfo &streamInfo,
- camera3_stream_rotation_t rotation, String8 physicalId,
+ camera3::camera_stream_rotation_t rotation, String8 physicalId,
hardware::camera::device::V3_4::Stream *stream /*out*/) {
if (stream == nullptr) {
return;
@@ -373,7 +373,7 @@
}
*earlyExit = false;
auto ret = Camera3Device::mapToStreamConfigurationMode(
- static_cast<camera3_stream_configuration_mode_t> (operatingMode),
+ static_cast<camera_stream_configuration_mode_t> (operatingMode),
/*out*/ &streamConfiguration.operationMode);
if (ret != OK) {
String8 msg = String8::format(
@@ -432,7 +432,7 @@
if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
streamInfo.consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
}
- mapStreamInfo(streamInfo, CAMERA3_STREAM_ROTATION_0, physicalCameraId,
+ mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId,
&streamConfiguration.streams[streamIdx++]);
isStreamInfoValid = true;
@@ -487,12 +487,12 @@
for (const auto& compositeStream : compositeStreams) {
mapStreamInfo(compositeStream,
- static_cast<camera3_stream_rotation_t> (it.getRotation()),
+ static_cast<camera_stream_rotation_t> (it.getRotation()),
physicalCameraId, &streamConfiguration.streams[streamIdx++]);
}
} else {
mapStreamInfo(streamInfo,
- static_cast<camera3_stream_rotation_t> (it.getRotation()),
+ static_cast<camera_stream_rotation_t> (it.getRotation()),
physicalCameraId, &streamConfiguration.streams[streamIdx++]);
}
isStreamInfoValid = true;
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index 6ce2cd7..6ac7ab4 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -23,7 +23,6 @@
#include <camera/camera2/SubmitInfo.h>
#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
-#include <hardware/camera3.h>
#include <device3/Camera3StreamInterface.h>
#include <stdint.h>
@@ -54,7 +53,7 @@
const String8 &cameraId, const CameraMetadata &physicalCameraMetadata);
static void mapStreamInfo(const camera3::OutputStreamInfo &streamInfo,
- camera3_stream_rotation_t rotation, String8 physicalId,
+ camera3::camera_stream_rotation_t rotation, String8 physicalId,
hardware::camera::device::V3_4::Stream *stream /*out*/);
// Check that the physicalCameraId passed in is spported by the camera
diff --git a/services/mediacodec/seccomp_policy/mediacodec-x86.policy b/services/mediacodec/seccomp_policy/mediacodec-x86.policy
index a9d32d6..4bcc077 100644
--- a/services/mediacodec/seccomp_policy/mediacodec-x86.policy
+++ b/services/mediacodec/seccomp_policy/mediacodec-x86.policy
@@ -27,6 +27,7 @@
mmap: 1
fstat64: 1
fstat: 1
+stat: 1
stat64: 1
statfs64: 1
madvise: 1
diff --git a/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy b/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy
index a9d32d6..4bcc077 100644
--- a/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy
+++ b/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy
@@ -27,6 +27,7 @@
mmap: 1
fstat64: 1
fstat: 1
+stat: 1
stat64: 1
statfs64: 1
madvise: 1
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy b/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy
index eb71e28..9bafe7b 100644
--- a/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy
@@ -27,6 +27,7 @@
mmap: 1
fstat64: 1
fstat: 1
+stat: 1
stat64: 1
statfs64: 1
madvise: 1
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy b/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy
index e72d4db..b0ed040 100644
--- a/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy
@@ -27,6 +27,7 @@
mmap: 1
fstat64: 1
fstat: 1
+stat: 1
stat64: 1
statfs64: 1
madvise: 1
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
new file mode 100644
index 0000000..df4c867
--- /dev/null
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_fuzz {
+ name: "mediametrics_service_fuzzer",
+
+ srcs: [
+ "mediametrics_service_fuzzer.cpp",
+ ],
+
+ static_libs: [
+ "libmediametrics",
+ "libmediametricsservice",
+ "libplatformprotos",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "libmedia_helper",
+ "libmediautils",
+ "libmemunreachable",
+ "libprotobuf-cpp-lite",
+ "libstagefright",
+ "libstatslog",
+ "libutils",
+ ],
+
+ include_dirs: [
+ "frameworks/av/services/mediametrics",
+ "system/media/audio_utils/include",
+ ],
+
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
diff --git a/services/mediametrics/fuzzer/README.md b/services/mediametrics/fuzzer/README.md
new file mode 100644
index 0000000..a13830e
--- /dev/null
+++ b/services/mediametrics/fuzzer/README.md
@@ -0,0 +1,54 @@
+# Fuzzer for libmediametricsservice
+
+## Plugin Design Considerations
+The fuzzer plugin for libmediametricsservice is designed based on the
+understanding of the service and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+Media Metrics Service contains the following modules:
+1. Media Metrics Item Manipulation (module name: `Item`)
+2. Media Metrics Time Machine Storage (module name: `TimeMachineStorage`)
+3. Media Metrics Transaction Log (module name: `TransactionLog`)
+4. Media Metrics Analytics Action (module name: `AnalyticsAction`)
+5. Media Metrics Audio Analytics (module name: `AudioAnalytics`)
+6. Media Metrics Timed Action (module name: `TimedAction`)
+
+| Module| Valid Input Values| Configured Value|
+|------------- |-------------| ----- |
+| `Item` | Key: `std::string`. Values: `INT32_MIN` to `INT32_MAX`, `INT64_MIN` to `INT64_MAX`, `std::string`, `double`, `pair<INT32_MIN to INT32_MAX, INT32_MIN to INT32_MAX>` | Value obtained from FuzzedDataProvider |
+| `TimeMachineStorage` | Key: `std::string`. Values: `INT32_MIN` to `INT32_MAX`, `INT64_MIN` to `INT64_MAX`, `std::string`, `double`, `pair<INT32_MIN to INT32_MAX, INT32_MIN to INT32_MAX>` | Value obtained from FuzzedDataProvider |
+| `TranscationLog` | `mediametrics::Item` | `mediametrics::Item` created by obtaining values from FuzzedDataProvider|
+| `AnalyticsAction` | URL: `std::string` ending with .event, Value: `std::string`, action: A function | URL and Values obtained from FuzzedDataProvider, a placeholder function was passed as action|
+| `AudioAnalytics` | `mediametrics::Item` | `mediametrics::Item` created by obtaining values from FuzzedDataProvider|
+| `TimedAction` | time: `std::chrono::seconds`, function: `std::function` | `std::chrono::seconds` : value obtained from FuzzedDataProvider, `std::function`: a placeholder function was used. |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+## Build
+
+This describes steps to build mediametrics_service_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) mediametrics_service_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some files to that folder
+Push this directory to device.
+
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mediametrics_service_fuzzer/mediametrics_service_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp
new file mode 100644
index 0000000..0cb2594
--- /dev/null
+++ b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp
@@ -0,0 +1,372 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <fuzzer/FuzzedDataProvider.h>
+#include <media/MediaMetricsItem.h>
+#include <stdio.h>
+#include <string.h>
+#include <utils/Log.h>
+#include <algorithm>
+
+#include "AudioTypes.h"
+#include "MediaMetricsService.h"
+#include "StringUtils.h"
+
+using namespace android;
+
+// low water mark
+constexpr size_t kLogItemsLowWater = 1;
+// high water mark
+constexpr size_t kLogItemsHighWater = 2;
+
+class MediaMetricsServiceFuzzer {
+ public:
+ void invokeStartsWith(const uint8_t *data, size_t size);
+ void invokeInstantiate(const uint8_t *data, size_t size);
+ void invokePackageInstallerCheck(const uint8_t *data, size_t size);
+ void invokeItemManipulation(const uint8_t *data, size_t size);
+ void invokeItemExpansion(const uint8_t *data, size_t size);
+ void invokeTimeMachineStorage(const uint8_t *data, size_t size);
+ void invokeTransactionLog(const uint8_t *data, size_t size);
+ void invokeAnalyticsAction(const uint8_t *data, size_t size);
+ void invokeAudioAnalytics(const uint8_t *data, size_t size);
+ void invokeTimedAction(const uint8_t *data, size_t size);
+ void process(const uint8_t *data, size_t size);
+};
+
+void MediaMetricsServiceFuzzer::invokeStartsWith(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ while (fdp.remaining_bytes()) {
+ android::mediametrics::startsWith(fdp.ConsumeRandomLengthString(),
+ fdp.ConsumeRandomLengthString());
+ }
+}
+
+void MediaMetricsServiceFuzzer::invokeInstantiate(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ sp mediaMetricsService = new MediaMetricsService();
+
+ while (fdp.remaining_bytes()) {
+ std::unique_ptr<mediametrics::Item> random_key(
+ mediametrics::Item::create(fdp.ConsumeRandomLengthString()));
+ mediaMetricsService->submit(random_key.get());
+ random_key->setInt32(fdp.ConsumeRandomLengthString().c_str(),
+ fdp.ConsumeIntegral<int32_t>());
+ mediaMetricsService->submit(random_key.get());
+
+ std::unique_ptr<mediametrics::Item> audiotrack_key(
+ mediametrics::Item::create("audiotrack"));
+ mediaMetricsService->submit(audiotrack_key.get());
+ audiotrack_key->addInt32(fdp.ConsumeRandomLengthString().c_str(),
+ fdp.ConsumeIntegral<int32_t>());
+ mediaMetricsService->submit(audiotrack_key.get());
+ }
+}
+
+void MediaMetricsServiceFuzzer::invokePackageInstallerCheck(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ while (fdp.remaining_bytes()) {
+ MediaMetricsService::useUidForPackage(fdp.ConsumeRandomLengthString().c_str(),
+ fdp.ConsumeRandomLengthString().c_str());
+ }
+}
+
+void MediaMetricsServiceFuzzer::invokeItemManipulation(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+ mediametrics::Item item(fdp.ConsumeRandomLengthString().c_str());
+ while (fdp.remaining_bytes()) {
+ const uint8_t action = fdp.ConsumeIntegralInRange<uint8_t>(0, 16);
+ const std::string key = fdp.ConsumeRandomLengthString();
+ if (fdp.remaining_bytes() < 1 || key.length() < 1) {
+ break;
+ }
+ switch (action) {
+ case 0: {
+ item.setInt32(key.c_str(), fdp.ConsumeIntegral<int32_t>());
+ break;
+ }
+ case 1: {
+ item.addInt32(key.c_str(), fdp.ConsumeIntegral<int32_t>());
+ break;
+ }
+ case 2: {
+ int32_t i32 = 0;
+ item.getInt32(key.c_str(), &i32);
+ break;
+ }
+ case 3: {
+ item.setInt64(key.c_str(), fdp.ConsumeIntegral<int64_t>());
+ break;
+ }
+ case 4: {
+ item.addInt64(key.c_str(), fdp.ConsumeIntegral<int64_t>());
+ break;
+ }
+ case 5: {
+ int64_t i64 = 0;
+ item.getInt64(key.c_str(), &i64);
+ break;
+ }
+ case 6: {
+ item.setDouble(key.c_str(), fdp.ConsumeFloatingPoint<double>());
+ break;
+ }
+ case 7: {
+ item.addDouble(key.c_str(), fdp.ConsumeFloatingPoint<double>());
+ break;
+ }
+ case 8: {
+ double d = 0;
+ item.getDouble(key.c_str(), &d);
+ break;
+ }
+ case 9: {
+ item.setCString(key.c_str(), fdp.ConsumeRandomLengthString().c_str());
+ break;
+ }
+ case 10: {
+ char *s = nullptr;
+ item.getCString(key.c_str(), &s);
+ if (s) free(s);
+ break;
+ }
+ case 11: {
+ std::string s;
+ item.getString(key.c_str(), &s);
+ break;
+ }
+ case 12: {
+ item.setRate(key.c_str(), fdp.ConsumeIntegral<int64_t>(),
+ fdp.ConsumeIntegral<int64_t>());
+ break;
+ }
+ case 13: {
+ int64_t b = 0, h = 0;
+ double d = 0;
+ item.getRate(key.c_str(), &b, &h, &d);
+ break;
+ }
+ case 14: {
+ (void)item.filter(key.c_str());
+ break;
+ }
+ case 15: {
+ const char *arr[1] = {""};
+ arr[0] = const_cast<char *>(key.c_str());
+ (void)item.filterNot(1, arr);
+ break;
+ }
+ case 16: {
+ (void)item.toString().c_str();
+ break;
+ }
+ }
+ }
+
+ Parcel p;
+ mediametrics::Item item2;
+
+ (void)item.writeToParcel(&p);
+ p.setDataPosition(0); // rewind for reading
+ (void)item2.readFromParcel(p);
+
+ char *byteData = nullptr;
+ size_t length = 0;
+ (void)item.writeToByteString(&byteData, &length);
+ (void)item2.readFromByteString(byteData, length);
+ if (byteData) {
+ free(byteData);
+ }
+
+ sp mediaMetricsService = new MediaMetricsService();
+ mediaMetricsService->submit(&item2);
+}
+
+void MediaMetricsServiceFuzzer::invokeItemExpansion(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+ mediametrics::LogItem<1> item("FuzzItem");
+ item.setPid(fdp.ConsumeIntegral<int16_t>()).setUid(fdp.ConsumeIntegral<int16_t>());
+
+ while (fdp.remaining_bytes()) {
+ int32_t i = fdp.ConsumeIntegral<int32_t>();
+ item.set(std::to_string(i).c_str(), (int32_t)i);
+ }
+ item.updateHeader();
+
+ mediametrics::Item item2;
+ (void)item2.readFromByteString(item.getBuffer(), item.getLength());
+
+ sp mediaMetricsService = new MediaMetricsService();
+ mediaMetricsService->submit(&item2);
+}
+
+void MediaMetricsServiceFuzzer::invokeTimeMachineStorage(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+ auto item = std::make_shared<mediametrics::Item>("FuzzKey");
+ int32_t i32 = fdp.ConsumeIntegral<int32_t>();
+ int64_t i64 = fdp.ConsumeIntegral<int64_t>();
+ double d = fdp.ConsumeFloatingPoint<double>();
+ std::string str = fdp.ConsumeRandomLengthString();
+ std::pair<int64_t, int64_t> pair(fdp.ConsumeIntegral<int64_t>(),
+ fdp.ConsumeIntegral<int64_t>());
+ (*item).set("i32", i32).set("i64", i64).set("double", d).set("string", str).set("rate", pair);
+
+ android::mediametrics::TimeMachine timeMachine;
+ timeMachine.put(item, true);
+
+ timeMachine.get("Key", "i32", &i32, -1);
+
+ timeMachine.get("Key", "i64", &i64, -1);
+
+ timeMachine.get("Key", "double", &d, -1);
+
+ timeMachine.get("Key", "string", &str, -1);
+
+ timeMachine.get("Key.i32", &i32, -1);
+
+ timeMachine.get("Key.i64", &i64, -1);
+
+ timeMachine.get("Key.double", &d, -1);
+
+ str.clear();
+ timeMachine.get("Key.string", &str, -1);
+}
+
+void MediaMetricsServiceFuzzer::invokeTransactionLog(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+ auto item = std::make_shared<mediametrics::Item>("Key1");
+ (*item)
+ .set("one", fdp.ConsumeIntegral<int32_t>())
+ .set("two", fdp.ConsumeIntegral<int32_t>())
+ .setTimestamp(fdp.ConsumeIntegral<int32_t>());
+
+ android::mediametrics::TransactionLog transactionLog(
+ kLogItemsLowWater, kLogItemsHighWater); // keep at most 2 items
+ transactionLog.size();
+
+ transactionLog.put(item);
+ transactionLog.size();
+
+ auto item2 = std::make_shared<mediametrics::Item>("Key2");
+ (*item2)
+ .set("three", fdp.ConsumeIntegral<int32_t>())
+ .set("[Key1]three", fdp.ConsumeIntegral<int32_t>())
+ .setTimestamp(fdp.ConsumeIntegral<int32_t>());
+
+ transactionLog.put(item2);
+ transactionLog.size();
+
+ auto item3 = std::make_shared<mediametrics::Item>("Key3");
+ (*item3)
+ .set("six", fdp.ConsumeIntegral<int32_t>())
+ .set("[Key1]four", fdp.ConsumeIntegral<int32_t>()) // affects Key1
+ .set("[Key1]five", fdp.ConsumeIntegral<int32_t>()) // affects key1
+ .setTimestamp(fdp.ConsumeIntegral<int32_t>());
+
+ transactionLog.put(item3);
+ transactionLog.size();
+}
+
+void MediaMetricsServiceFuzzer::invokeAnalyticsAction(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+ mediametrics::AnalyticsActions analyticsActions;
+ bool action = false;
+
+ while (fdp.remaining_bytes()) {
+ analyticsActions.addAction(
+ (fdp.ConsumeRandomLengthString() + std::string(".event")).c_str(),
+ fdp.ConsumeRandomLengthString(),
+ std::make_shared<mediametrics::AnalyticsActions::Function>(
+ [&](const std::shared_ptr<const android::mediametrics::Item> &) {
+ action = true;
+ }));
+ }
+
+ FuzzedDataProvider fdp2 = FuzzedDataProvider(data, size);
+
+ while (fdp2.remaining_bytes()) {
+ // make a test item
+ auto item = std::make_shared<mediametrics::Item>(fdp2.ConsumeRandomLengthString().c_str());
+ (*item).set("event", fdp2.ConsumeRandomLengthString().c_str());
+
+ // get the actions and execute them
+ auto actions = analyticsActions.getActionsForItem(item);
+ for (const auto &action : actions) {
+ action->operator()(item);
+ }
+ }
+}
+
+void MediaMetricsServiceFuzzer::invokeAudioAnalytics(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ android::mediametrics::AudioAnalytics audioAnalytics;
+
+ while (fdp.remaining_bytes()) {
+ auto item = std::make_shared<mediametrics::Item>(fdp.ConsumeRandomLengthString().c_str());
+ int32_t transactionUid = fdp.ConsumeIntegral<int32_t>(); // arbitrary
+ (*item)
+ .set(fdp.ConsumeRandomLengthString().c_str(), fdp.ConsumeIntegral<int32_t>())
+ .set(fdp.ConsumeRandomLengthString().c_str(), fdp.ConsumeIntegral<int32_t>())
+ .set(AMEDIAMETRICS_PROP_ALLOWUID, transactionUid)
+ .setUid(transactionUid)
+ .setTimestamp(fdp.ConsumeIntegral<int32_t>());
+ audioAnalytics.submit(item, fdp.ConsumeBool());
+ }
+
+ audioAnalytics.dump(1000);
+}
+
+void MediaMetricsServiceFuzzer::invokeTimedAction(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ android::mediametrics::TimedAction timedAction;
+ std::atomic_int value = 0;
+
+ while (fdp.remaining_bytes()) {
+ timedAction.postIn(std::chrono::seconds(fdp.ConsumeIntegral<int32_t>()),
+ [&value] { ++value; });
+ timedAction.size();
+ }
+}
+
+void MediaMetricsServiceFuzzer::process(const uint8_t *data, size_t size) {
+ invokeStartsWith(data, size);
+ invokeInstantiate(data, size);
+ invokePackageInstallerCheck(data, size);
+ invokeItemManipulation(data, size);
+ invokeItemExpansion(data, size);
+ invokeTimeMachineStorage(data, size);
+ invokeTransactionLog(data, size);
+ invokeAnalyticsAction(data, size);
+ invokeAudioAnalytics(data, size);
+ invokeTimedAction(data, size);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < 1) {
+ return 0;
+ }
+ MediaMetricsServiceFuzzer mediaMetricsServiceFuzzer;
+ mediaMetricsServiceFuzzer.process(data, size);
+ return 0;
+}
diff --git a/services/mediametrics/statsd_extractor.cpp b/services/mediametrics/statsd_extractor.cpp
index 16814d9..4180e0c 100644
--- a/services/mediametrics/statsd_extractor.cpp
+++ b/services/mediametrics/statsd_extractor.cpp
@@ -71,6 +71,22 @@
metrics_proto.set_tracks(ntrk);
}
+ // android.media.mediaextractor.entry string
+ std::string entry_point_string;
+ if (item->getString("android.media.mediaextractor.entry", &entry_point_string)) {
+ stats::mediametrics::ExtractorData::EntryPoint entry_point;
+ if (entry_point_string == "sdk") {
+ entry_point = stats::mediametrics::ExtractorData_EntryPoint_SDK;
+ } else if (entry_point_string == "ndk-with-jvm") {
+ entry_point = stats::mediametrics::ExtractorData_EntryPoint_NDK_WITH_JVM;
+ } else if (entry_point_string == "ndk-no-jvm") {
+ entry_point = stats::mediametrics::ExtractorData_EntryPoint_NDK_NO_JVM;
+ } else {
+ entry_point = stats::mediametrics::ExtractorData_EntryPoint_OTHER;
+ }
+ metrics_proto.set_entry_point(entry_point);
+ }
+
std::string serialized;
if (!metrics_proto.SerializeToString(&serialized)) {
ALOGE("Failed to serialize extractor metrics");
diff --git a/services/mediaresourcemanager/Android.bp b/services/mediaresourcemanager/Android.bp
index cdf5a4e..83a139b 100644
--- a/services/mediaresourcemanager/Android.bp
+++ b/services/mediaresourcemanager/Android.bp
@@ -35,11 +35,27 @@
aidl_interface {
name: "resourceobserver_aidl_interface",
- unstable: true,
local_include_dir: "aidl",
srcs: [
":resourceobserver_aidl",
],
+ backend: {
+ java: {
+ enabled: false,
+ },
+ cpp: {
+ enabled: false,
+ },
+ ndk: {
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media",
+ "test_com.android.media",
+ ],
+ min_sdk_version: "29",
+ enabled: true,
+ },
+ },
}
cc_library {
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 32ac583..289cffd 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -22,6 +22,7 @@
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <binder/IMediaResourceMonitor.h>
+#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <cutils/sched_policy.h>
#include <dirent.h>
@@ -96,7 +97,7 @@
service->overridePid(mPid, -1);
// thiz is freed in the call below, so it must be last call referring thiz
- service->removeResource(mPid, mClientId, false);
+ service->removeResource(mPid, mClientId, false /*checkValid*/);
}
class OverrideProcessInfoDeathNotifier : public DeathNotifier {
@@ -422,8 +423,12 @@
Mutex::Autolock lock(mLock);
if (!mProcessInfo->isValidPid(pid)) {
- ALOGE("Rejected addResource call with invalid pid.");
- return Status::fromServiceSpecificError(BAD_VALUE);
+ pid_t callingPid = IPCThreadState::self()->getCallingPid();
+ uid_t callingUid = IPCThreadState::self()->getCallingUid();
+ ALOGW("%s called with untrusted pid %d, using calling pid %d, uid %d", __FUNCTION__,
+ pid, callingPid, callingUid);
+ pid = callingPid;
+ uid = callingUid;
}
ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
ResourceInfo& info = getResourceInfoForEdit(uid, clientId, client, infos);
@@ -477,8 +482,10 @@
Mutex::Autolock lock(mLock);
if (!mProcessInfo->isValidPid(pid)) {
- ALOGE("Rejected removeResource call with invalid pid.");
- return Status::fromServiceSpecificError(BAD_VALUE);
+ pid_t callingPid = IPCThreadState::self()->getCallingPid();
+ ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
+ pid, callingPid);
+ pid = callingPid;
}
ssize_t index = mMap.indexOfKey(pid);
if (index < 0) {
@@ -531,7 +538,7 @@
}
Status ResourceManagerService::removeClient(int32_t pid, int64_t clientId) {
- removeResource(pid, clientId, true);
+ removeResource(pid, clientId, true /*checkValid*/);
return Status::ok();
}
@@ -543,8 +550,10 @@
Mutex::Autolock lock(mLock);
if (checkValid && !mProcessInfo->isValidPid(pid)) {
- ALOGE("Rejected removeResource call with invalid pid.");
- return Status::fromServiceSpecificError(BAD_VALUE);
+ pid_t callingPid = IPCThreadState::self()->getCallingPid();
+ ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
+ pid, callingPid);
+ pid = callingPid;
}
ssize_t index = mMap.indexOfKey(pid);
if (index < 0) {
@@ -599,8 +608,10 @@
{
Mutex::Autolock lock(mLock);
if (!mProcessInfo->isValidPid(callingPid)) {
- ALOGE("Rejected reclaimResource call with invalid callingPid.");
- return Status::fromServiceSpecificError(BAD_VALUE);
+ pid_t actualCallingPid = IPCThreadState::self()->getCallingPid();
+ ALOGW("%s called with untrusted pid %d, using actual calling pid %d", __FUNCTION__,
+ callingPid, actualCallingPid);
+ callingPid = actualCallingPid;
}
const MediaResourceParcel *secureCodec = NULL;
const MediaResourceParcel *nonSecureCodec = NULL;
@@ -836,8 +847,10 @@
Mutex::Autolock lock(mLock);
if (!mProcessInfo->isValidPid(pid)) {
- ALOGE("Rejected markClientForPendingRemoval call with invalid pid.");
- return Status::fromServiceSpecificError(BAD_VALUE);
+ pid_t callingPid = IPCThreadState::self()->getCallingPid();
+ ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
+ pid, callingPid);
+ pid = callingPid;
}
ssize_t index = mMap.indexOfKey(pid);
if (index < 0) {
@@ -866,8 +879,10 @@
{
Mutex::Autolock lock(mLock);
if (!mProcessInfo->isValidPid(pid)) {
- ALOGE("Rejected reclaimResourcesFromClientsPendingRemoval call with invalid pid.");
- return Status::fromServiceSpecificError(BAD_VALUE);
+ pid_t callingPid = IPCThreadState::self()->getCallingPid();
+ ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
+ pid, callingPid);
+ pid = callingPid;
}
for (MediaResource::Type type : {MediaResource::Type::kSecureCodec,
diff --git a/services/mediaresourcemanager/ResourceObserverService.cpp b/services/mediaresourcemanager/ResourceObserverService.cpp
index 44fe72d..9cc6fe4 100644
--- a/services/mediaresourcemanager/ResourceObserverService.cpp
+++ b/services/mediaresourcemanager/ResourceObserverService.cpp
@@ -27,14 +27,6 @@
#include "ResourceObserverService.h"
-namespace aidl {
-namespace android {
-namespace media {
-bool operator<(const MediaObservableFilter& lhs, const MediaObservableFilter &rhs) {
- return lhs.type < rhs.type || (lhs.type == rhs.type && lhs.eventFilter < rhs.eventFilter);
-}
-}}} // namespace ::aidl::android::media
-
namespace android {
using ::aidl::android::media::MediaResourceParcel;
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/IResourceObserver.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/IResourceObserver.aidl
new file mode 100644
index 0000000..402704b
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/IResourceObserver.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+interface IResourceObserver {
+ oneway void onStatusChanged(android.media.MediaObservableEvent event, int uid, int pid, in android.media.MediaObservableParcel[] observables);
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/IResourceObserverService.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/IResourceObserverService.aidl
new file mode 100644
index 0000000..a0ef761
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/IResourceObserverService.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+interface IResourceObserverService {
+ void registerObserver(android.media.IResourceObserver observer, in android.media.MediaObservableFilter[] filters);
+ void unregisterObserver(android.media.IResourceObserver observer);
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableEvent.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableEvent.aidl
new file mode 100644
index 0000000..fd60bea
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableEvent.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+@Backing(type="long")
+enum MediaObservableEvent {
+ kBusy = 1,
+ kIdle = 2,
+ kAll = -1,
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableFilter.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableFilter.aidl
new file mode 100644
index 0000000..4045ae0
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableFilter.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+parcelable MediaObservableFilter {
+ android.media.MediaObservableType type;
+ android.media.MediaObservableEvent eventFilter;
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableParcel.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableParcel.aidl
new file mode 100644
index 0000000..ff5a8e8
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableParcel.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+parcelable MediaObservableParcel {
+ android.media.MediaObservableType type;
+ long value = 0;
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableType.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableType.aidl
new file mode 100644
index 0000000..ebb8d8e
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableType.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+@Backing(type="int")
+enum MediaObservableType {
+ kInvalid = 0,
+ kVideoSecureCodec = 1000,
+ kVideoNonSecureCodec = 1001,
+}
diff --git a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
index 4cf5f0a..8e29312 100644
--- a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
+++ b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
@@ -23,15 +23,6 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/ProcessInfoInterface.h>
-namespace aidl {
-namespace android {
-namespace media {
-bool operator== (const MediaResourceParcel& lhs, const MediaResourceParcel& rhs) {
- return lhs.type == rhs.type && lhs.subType == rhs.subType &&
- lhs.id == rhs.id && lhs.value == rhs.value;
-}
-}}}
-
namespace android {
using Status = ::ndk::ScopedAStatus;
diff --git a/services/mediaresourcemanager/test/ResourceObserverService_test.cpp b/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
index 4c26246..e3d3e78 100644
--- a/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
@@ -25,14 +25,6 @@
#include "ResourceObserverService.h"
#include "ResourceManagerServiceTestUtils.h"
-namespace aidl {
-namespace android {
-namespace media {
-bool operator==(const MediaObservableParcel& lhs, const MediaObservableParcel& rhs) {
- return lhs.type == rhs.type && lhs.value == rhs.value;
-}
-}}} // namespace ::aidl::android::media
-
namespace android {
using ::aidl::android::media::BnResourceObserver;
diff --git a/services/mediatranscoding/Android.bp b/services/mediatranscoding/Android.bp
index 3d6821b..48c2584 100644
--- a/services/mediatranscoding/Android.bp
+++ b/services/mediatranscoding/Android.bp
@@ -7,8 +7,14 @@
"SimulatedTranscoder.cpp",
],
+ min_sdk_version: "29",
+ apex_available: [
+ "com.android.media",
+ "test_com.android.media",
+ ],
+
shared_libs: [
- "libandroid",
+ "libandroid#31",
"libbase",
"libbinder_ndk",
"libcutils",
@@ -48,12 +54,16 @@
"libmediatranscodingservice",
],
+ min_sdk_version: "29",
+ apex_available: [
+ "com.android.media",
+ "test_com.android.media",
+ ],
+
static_libs: [
"mediatranscoding_aidl_interface-ndk_platform",
],
- init_rc: ["mediatranscoding.rc"],
-
cflags: [
"-Werror",
"-Wall",
diff --git a/services/mediatranscoding/mediatranscoding.rc b/services/mediatranscoding/mediatranscoding.rc
deleted file mode 100644
index 5bfef59..0000000
--- a/services/mediatranscoding/mediatranscoding.rc
+++ /dev/null
@@ -1,6 +0,0 @@
-service media.transcoding /system/bin/mediatranscoding
- class main
- user media
- group media
- ioprio rt 4
- task_profiles ProcessCapacityHigh HighPerformance
diff --git a/services/oboeservice/Android.bp b/services/oboeservice/Android.bp
index 80f17f4..9da4867 100644
--- a/services/oboeservice/Android.bp
+++ b/services/oboeservice/Android.bp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library_shared {
+cc_library {
name: "libaaudioservice",
diff --git a/services/tuner/Android.bp b/services/tuner/Android.bp
index 65d8d41..5327289 100644
--- a/services/tuner/Android.bp
+++ b/services/tuner/Android.bp
@@ -40,6 +40,21 @@
srcs: [
":tv_tuner_aidl",
],
+ imports: [
+ "android.hardware.common.fmq",
+ ],
+
+ backend: {
+ java: {
+ enabled: false,
+ },
+ cpp: {
+ enabled: false,
+ },
+ ndk: {
+ enabled: true,
+ },
+ },
}
cc_library {
@@ -52,8 +67,10 @@
shared_libs: [
"android.hardware.tv.tuner@1.0",
- "libbinder",
+ "libbase",
"libbinder_ndk",
+ "libcutils",
+ "libfmq",
"libhidlbase",
"liblog",
"libmedia",
@@ -61,7 +78,13 @@
"tv_tuner_aidl_interface-ndk_platform",
],
- include_dirs: ["frameworks/av/include"],
+ static_libs: [
+ "android.hardware.common.fmq-unstable-ndk_platform",
+ ],
+
+ include_dirs: [
+ "frameworks/av/include"
+ ],
cflags: [
"-Werror",
@@ -83,6 +106,7 @@
"android.hardware.tv.tuner@1.0",
"libbase",
"libbinder",
+ "libfmq",
"liblog",
"libtunerservice",
"libutils",
diff --git a/services/tuner/TunerService.cpp b/services/tuner/TunerService.cpp
index 2b3de17..56cb34c 100644
--- a/services/tuner/TunerService.cpp
+++ b/services/tuner/TunerService.cpp
@@ -32,14 +32,17 @@
using ::aidl::android::media::tv::tuner::TunerFrontendIsdbsCapabilities;
using ::aidl::android::media::tv::tuner::TunerFrontendIsdbtCapabilities;
using ::android::hardware::hidl_vec;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
using ::android::hardware::tv::tuner::V1_0::FrontendId;
using ::android::hardware::tv::tuner::V1_0::FrontendType;
using ::android::hardware::tv::tuner::V1_0::Result;
namespace android {
-sp<ITuner> TunerService::mTuner;
-
TunerService::TunerService() {}
TunerService::~TunerService() {}
@@ -47,17 +50,160 @@
std::shared_ptr<TunerService> service =
::ndk::SharedRefBase::make<TunerService>();
AServiceManager_addService(service->asBinder().get(), getServiceName());
+}
+
+template <typename HidlPayload, typename AidlPayload, typename AidlFlavor>
+bool TunerService::unsafeHidlToAidlMQDescriptor(
+ const hardware::MQDescriptor<HidlPayload, FlavorTypeToValue<AidlFlavor>::value>& hidlDesc,
+ MQDescriptor<AidlPayload, AidlFlavor>* aidlDesc) {
+ // TODO: use the builtin coversion method when it's merged.
+ ALOGD("unsafeHidlToAidlMQDescriptor");
+ static_assert(sizeof(HidlPayload) == sizeof(AidlPayload), "Payload types are incompatible");
+ static_assert(
+ has_typedef_fixed_size<AidlPayload>::value == true ||
+ std::is_fundamental<AidlPayload>::value ||
+ std::is_enum<AidlPayload>::value,
+ "Only fundamental types, enums, and AIDL parcelables annotated with @FixedSize "
+ "and built for the NDK backend are supported as AIDL payload types.");
+ aidlDesc->fileDescriptor = ndk::ScopedFileDescriptor(dup(hidlDesc.handle()->data[0]));
+ for (const auto& grantor : hidlDesc.grantors()) {
+ if (static_cast<int32_t>(grantor.offset) < 0 || static_cast<int64_t>(grantor.extent) < 0) {
+ ALOGD("Unsafe static_cast of grantor fields. offset=%d, extend=%ld",
+ static_cast<int32_t>(grantor.offset), static_cast<long>(grantor.extent));
+ logError(
+ "Unsafe static_cast of grantor fields. Either the hardware::MQDescriptor is "
+ "invalid, or the MessageQueue is too large to be described by AIDL.");
+ return false;
+ }
+ aidlDesc->grantors.push_back(
+ GrantorDescriptor {
+ .offset = static_cast<int32_t>(grantor.offset),
+ .extent = static_cast<int64_t>(grantor.extent)
+ });
+ }
+ if (static_cast<int32_t>(hidlDesc.getQuantum()) < 0 ||
+ static_cast<int32_t>(hidlDesc.getFlags()) < 0) {
+ ALOGD("Unsafe static_cast of quantum or flags. Quantum=%d, flags=%d",
+ static_cast<int32_t>(hidlDesc.getQuantum()),
+ static_cast<int32_t>(hidlDesc.getFlags()));
+ logError(
+ "Unsafe static_cast of quantum or flags. Either the hardware::MQDescriptor is "
+ "invalid, or the MessageQueue is too large to be described by AIDL.");
+ return false;
+ }
+ aidlDesc->quantum = static_cast<int32_t>(hidlDesc.getQuantum());
+ aidlDesc->flags = static_cast<int32_t>(hidlDesc.getFlags());
+ return true;
+}
+
+bool TunerService::getITuner() {
+ ALOGD("getITuner");
+ if (mTuner != nullptr) {
+ return true;
+ }
mTuner = ITuner::getService();
if (mTuner == nullptr) {
- ALOGE("Failed to get ITuner service.");
+ ALOGE("Failed to get ITuner service");
+ return false;
}
+ return true;
+}
+
+Result TunerService::openDemux() {
+ ALOGD("openDemux");
+ if (!getITuner()) {
+ return Result::NOT_INITIALIZED;
+ }
+ if (mDemux != nullptr) {
+ return Result::SUCCESS;
+ }
+ Result res;
+ uint32_t id;
+ sp<IDemux> demuxSp;
+ mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
+ demuxSp = demux;
+ id = demuxId;
+ res = r;
+ ALOGD("open demux, id = %d", demuxId);
+ });
+ if (res == Result::SUCCESS) {
+ mDemux = demuxSp;
+ } else {
+ ALOGD("open demux failed, res = %d", res);
+ }
+ return res;
+}
+
+Result TunerService::openFilter() {
+ ALOGD("openFilter");
+ if (!getITuner()) {
+ return Result::NOT_INITIALIZED;
+ }
+ DemuxFilterMainType mainType = DemuxFilterMainType::TS;
+ DemuxFilterType filterType {
+ .mainType = mainType,
+ };
+ filterType.subType.tsFilterType(DemuxTsFilterType::VIDEO);
+
+ sp<FilterCallback> callback = new FilterCallback();
+ Result res;
+ mDemux->openFilter(filterType, 16000000, callback,
+ [&](Result r, const sp<IFilter>& filter) {
+ mFilter = filter;
+ res = r;
+ });
+ if (res != Result::SUCCESS || mFilter == NULL) {
+ ALOGD("Failed to open filter, type = %d", filterType.mainType);
+ return res;
+ }
+
+ return Result::SUCCESS;
+}
+
+Result TunerService::configFilter() {
+ ALOGD("configFilter");
+ if (mFilter == NULL) {
+ ALOGD("Failed to configure filter: filter not found");
+ return Result::NOT_INITIALIZED;
+ }
+ DemuxFilterSettings filterSettings;
+ DemuxTsFilterSettings tsFilterSettings {
+ .tpid = 256,
+ };
+ DemuxFilterAvSettings filterAvSettings {
+ .isPassthrough = false,
+ };
+ tsFilterSettings.filterSettings.av(filterAvSettings);
+ filterSettings.ts(tsFilterSettings);
+ Result res = mFilter->configure(filterSettings);
+
+ if (res != Result::SUCCESS) {
+ ALOGD("config filter failed, res = %d", res);
+ return res;
+ }
+
+ Result getQueueDescResult = Result::UNKNOWN_ERROR;
+ mFilter->getQueueDesc(
+ [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
+ mFilterMQDesc = desc;
+ getQueueDescResult = r;
+ ALOGD("getFilterQueueDesc");
+ });
+ if (getQueueDescResult == Result::SUCCESS) {
+ unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(
+ mFilterMQDesc, &mAidlMQDesc);
+ mAidlMq = new (std::nothrow) AidlMessageQueue(mAidlMQDesc);
+ EventFlag::createEventFlag(mAidlMq->getEventFlagWord(), &mEventFlag);
+ } else {
+ ALOGD("get MQDesc failed, res = %d", getQueueDescResult);
+ }
+ return getQueueDescResult;
}
Status TunerService::getFrontendIds(std::vector<int32_t>* ids, int32_t* /* _aidl_return */) {
- if (mTuner == nullptr) {
- ALOGE("ITuner service is not init.");
+ if (!getITuner()) {
return ::ndk::ScopedAStatus::fromServiceSpecificError(
- static_cast<int32_t>(Result::UNAVAILABLE));
+ static_cast<int32_t>(Result::NOT_INITIALIZED));
}
hidl_vec<FrontendId> feIds;
Result res;
@@ -221,4 +367,24 @@
info.caps = caps;
return info;
}
+
+Status TunerService::getFmqSyncReadWrite(
+ MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) {
+ ALOGD("getFmqSyncReadWrite");
+ // TODO: put the following methods AIDL, and should be called from clients.
+ openDemux();
+ openFilter();
+ configFilter();
+ mFilter->start();
+ if (mqDesc == nullptr) {
+ ALOGD("getFmqSyncReadWrite null MQDescriptor.");
+ *_aidl_return = false;
+ } else {
+ ALOGD("getFmqSyncReadWrite true");
+ *_aidl_return = true;
+ *mqDesc = std::move(mAidlMQDesc);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace android
diff --git a/services/tuner/TunerService.h b/services/tuner/TunerService.h
index 36ccd3e..26591ab 100644
--- a/services/tuner/TunerService.h
+++ b/services/tuner/TunerService.h
@@ -20,17 +20,59 @@
#include <aidl/android/media/tv/tuner/BnTunerService.h>
#include <aidl/android/media/tv/tuner/TunerServiceFrontendInfo.h>
#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <fmq/AidlMessageQueue.h>
+#include <fmq/EventFlag.h>
+#include <fmq/MessageQueue.h>
-using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::hardware::common::fmq::GrantorDescriptor;
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
using ::aidl::android::media::tv::tuner::BnTunerService;
using ::aidl::android::media::tv::tuner::ITunerFrontend;
using ::aidl::android::media::tv::tuner::TunerServiceFrontendInfo;
+
+using ::android::hardware::details::logError;
+using ::android::hardware::EventFlag;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using ::android::hardware::tv::tuner::V1_0::FrontendId;
using ::android::hardware::tv::tuner::V1_0::FrontendInfo;
+using ::android::hardware::tv::tuner::V1_0::IDemux;
+using ::android::hardware::tv::tuner::V1_0::IFilter;
+using ::android::hardware::tv::tuner::V1_0::IFilterCallback;
using ::android::hardware::tv::tuner::V1_0::ITuner;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+using Status = ::ndk::ScopedAStatus;
namespace android {
+
+struct FilterCallback : public IFilterCallback {
+ ~FilterCallback() {}
+ Return<void> onFilterEvent(const DemuxFilterEvent&) {
+ return Void();
+ }
+ Return<void> onFilterStatus(const DemuxFilterStatus) {
+ return Void();
+ }
+};
+
class TunerService : public BnTunerService {
+ typedef AidlMessageQueue<int8_t, SynchronizedReadWrite> AidlMessageQueue;
+ typedef MessageQueue<uint8_t, kSynchronizedReadWrite> HidlMessageQueue;
+ typedef MQDescriptor<int8_t, SynchronizedReadWrite> AidlMQDesc;
public:
static char const *getServiceName() { return "media.tuner"; }
@@ -46,10 +88,27 @@
Status getFrontendInfo(int32_t frontendHandle, TunerServiceFrontendInfo* _aidl_return) override;
Status openFrontend(
int32_t frontendHandle, std::shared_ptr<ITunerFrontend>* _aidl_return) override;
+ Status getFmqSyncReadWrite(
+ MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) override;
private:
- static sp<ITuner> mTuner;
+ template <typename HidlPayload, typename AidlPayload, typename AidlFlavor>
+ bool unsafeHidlToAidlMQDescriptor(
+ const hardware::MQDescriptor<HidlPayload, FlavorTypeToValue<AidlFlavor>::value>& hidl,
+ MQDescriptor<AidlPayload, AidlFlavor>* aidl);
+ bool getITuner();
+ Result openFilter();
+ Result openDemux();
+ Result configFilter();
+
+ sp<ITuner> mTuner;
+ sp<IDemux> mDemux;
+ sp<IFilter> mFilter;
+ AidlMessageQueue* mAidlMq;
+ MQDescriptorSync<uint8_t> mFilterMQDesc;
+ AidlMQDesc mAidlMQDesc;
+ EventFlag* mEventFlag;
TunerServiceFrontendInfo convertToAidlFrontendInfo(int feId, FrontendInfo halInfo);
};
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
index 5a0b47d..5c1bce7 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
@@ -16,6 +16,9 @@
package android.media.tv.tuner;
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+import android.hardware.common.fmq.UnsynchronizedWrite;
import android.media.tv.tuner.ITunerFrontend;
import android.media.tv.tuner.TunerServiceFrontendInfo;
@@ -24,6 +27,7 @@
*
* {@hide}
*/
+//@VintfStability
interface ITunerService {
/**
@@ -48,4 +52,11 @@
* @return the aidl interface of the frontend.
*/
ITunerFrontend openFrontend(in int frontendHandle);
+
+ /*
+ * Gets synchronized fast message queue.
+ *
+ * @return true if succeeds, false otherwise.
+ */
+ boolean getFmqSyncReadWrite(out MQDescriptor<byte, SynchronizedReadWrite> mqDesc);
}