Merge "Revert "Added device info playback config for native players""
diff --git a/apex/Android.bp b/apex/Android.bp
index 6ba9cb9..b314e5d 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -89,6 +89,9 @@
binaries: [
"mediaswcodec",
],
+ native_shared_libs: [
+ "libstagefright_foundation",
+ ],
prebuilts: [
"com.android.media.swcodec-mediaswcodec.rc",
"com.android.media.swcodec-ld.config.txt",
@@ -97,7 +100,6 @@
"crash_dump.policy",
"mediaswcodec.xml",
],
- use_vendor: true,
key: "com.android.media.swcodec.key",
certificate: ":com.android.media.swcodec.certificate",
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/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/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/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/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 7e5eba3..31c071e 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -2187,4 +2187,14 @@
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 64ec145..81394cb 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,6 +58,7 @@
"audioflinger-aidl-unstable-cpp",
"capture_state_listener-aidl-cpp",
],
+ header_libs: ["libaudioclient_headers"],
}
cc_library_shared {
@@ -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",
],
@@ -373,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/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 09fcc66..84a75dd 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1792,20 +1792,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();
}
// ----------------------------------------------------------------------------
@@ -1839,20 +1841,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);
@@ -1860,19 +1868,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);
@@ -1880,9 +1889,29 @@
}
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();
}
void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused)
@@ -1904,4 +1933,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/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 2828bcb..0849e61 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -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());
@@ -2304,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/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/aidl/android/media/IAudioPolicyServiceClient.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl
new file mode 100644
index 0000000..a8d79b5
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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);
+}
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/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index e3858b9..56afe93 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -51,6 +51,7 @@
#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>
@@ -353,4 +354,9 @@
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/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 7a3692b..17ce56e 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,
@@ -580,7 +598,7 @@
};
class AudioPolicyServiceClient: public IBinder::DeathRecipient,
- public BnAudioPolicyServiceClient
+ public media::BnAudioPolicyServiceClient
{
public:
AudioPolicyServiceClient() {
@@ -598,18 +616,20 @@
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;
private:
Mutex mLock;
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index df792e3..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 {
@@ -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/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/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/tests/build_and_run_all_unit_tests.sh b/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
index a97acc9..e96263c 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
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..86b21ae 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"
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/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..93e03ee 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;
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/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/transcoder/VideoTrackTranscoder.cpp b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
index ec62775..0695bdb 100644
--- a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
@@ -40,8 +40,10 @@
// Default key frame interval in seconds.
static constexpr float kDefaultKeyFrameIntervalSeconds = 1.0f;
// Default codec operating rate.
-static int32_t kDefaultCodecOperatingRate =
- base::GetIntProperty("debug.media.transcoding.codec_max_operating_rate", /*default*/ 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.
@@ -183,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) {
@@ -213,8 +234,13 @@
SetDefaultFormatValueFloat(AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, encoderFormat,
kDefaultKeyFrameIntervalSeconds);
- SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_OPERATING_RATE, encoderFormat,
- kDefaultCodecOperatingRate);
+
+ 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);
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index fbaa38e..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 },
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/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/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/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/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/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/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..237b66e 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
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index e428e49..7d7433a 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -164,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(
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 0a82af6..276b471 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -84,6 +84,7 @@
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();
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/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index eccde7b..159ca08 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;
@@ -537,30 +472,30 @@
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;
-
+ }
+ 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_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC,
+ AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_USB_HEADSET});
+ break;
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.
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_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
+ AUDIO_DEVICE_IN_USB_DEVICE, 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;
@@ -573,7 +508,7 @@
LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
availableDevices = availablePrimaryDevices;
}
- 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;
@@ -623,6 +558,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 +576,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 +612,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 86f4539..69f9a69 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -792,16 +792,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)
@@ -3164,6 +3155,7 @@
return res;
}
+
status_t AudioPolicyManager::setDevicesRoleForStrategy(product_strategy_t strategy,
device_role_t role,
const AudioDeviceTypeAddrVector &devices) {
@@ -3181,7 +3173,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;
}
@@ -3212,6 +3214,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)
{
@@ -3219,12 +3233,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;
}
@@ -3264,6 +3289,7 @@
"Engine could not add preferred devices %s for audio source %d role %d",
dumpAudioDeviceTypeAddrVector(devices).c_str(), audioSource, role);
+ updateInputRouting();
return status;
}
@@ -3282,6 +3308,7 @@
ALOGW_IF(status != NO_ERROR,
"Engine could not remove devices role (%d) for capture preset %d", role, audioSource);
+ updateInputRouting();
return status;
}
@@ -3293,6 +3320,7 @@
ALOGW_IF(status != NO_ERROR,
"Engine could not clear devices role (%d) for capture preset %d", role, audioSource);
+ updateInputRouting();
return status;
}
@@ -3362,7 +3390,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);
@@ -4657,6 +4687,9 @@
// Silence ALOGV statements
property_set("log.tag." LOG_TAG, "D");
+ mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
+ mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
+
updateDevicesAndOutputs();
return status;
}
@@ -5492,6 +5525,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();
@@ -5503,23 +5547,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))) {
@@ -5528,10 +5570,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))) {
@@ -6243,15 +6282,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;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 00c4eab..4e745bd 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -557,6 +557,11 @@
void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0);
/**
+ * @brief updates routing for all inputs.
+ */
+ void updateInputRouting();
+
+ /**
* @brief checkOutputForAttributes checks and if necessary changes outputs used for the
* given audio attributes.
* must be called every time a condition that affects the output choice for a given
@@ -816,6 +821,10 @@
// 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;
+
private:
void onNewAudioModulesAvailableInt(DeviceVector *newDevices);
@@ -971,6 +980,7 @@
std::function<bool(audio_devices_t)> predicate,
const char* context);
+ bool isScoRequestedForComm() const;
};
};
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/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 517d6bf..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;
}
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index a6e8989..d71a317 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__);
@@ -293,10 +294,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 +344,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 +360,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);
}
}
@@ -453,7 +485,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 +499,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 +527,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 +549,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 +571,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 +582,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 +616,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:
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index c032f24..c0e29ee 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -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);
@@ -775,7 +775,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();
@@ -807,12 +807,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/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);
}