Merge "Make libaudiofoundation can be a static library."
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 39b048a..8507729 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -40,9 +40,11 @@
"libcutils",
"libdl",
"liblog",
+ "libmedia",
"libmediadrmmetrics_lite",
"libmediametrics",
"libmediautils",
+ "libresourcemanagerservice",
"libstagefright_foundation",
"libutils",
"android.hardware.drm@1.0",
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 7cfe900..bd4b521 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -293,38 +293,45 @@
}
}
-
Mutex DrmHal::mLock;
-struct DrmSessionClient : public DrmSessionClientInterface {
- explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {}
-
- virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
- sp<DrmHal> drm = mDrm.promote();
- if (drm == NULL) {
- return true;
- }
- status_t err = drm->closeSession(sessionId);
- if (err != OK) {
- return false;
- }
- drm->sendEvent(EventType::SESSION_RECLAIMED,
- toHidlVec(sessionId), hidl_vec<uint8_t>());
+bool DrmHal::DrmSessionClient::reclaimResource() {
+ sp<DrmHal> drm = mDrm.promote();
+ if (drm == NULL) {
return true;
}
+ status_t err = drm->closeSession(mSessionId);
+ if (err != OK) {
+ return false;
+ }
+ drm->sendEvent(EventType::SESSION_RECLAIMED,
+ toHidlVec(mSessionId), hidl_vec<uint8_t>());
+ return true;
+}
-protected:
- virtual ~DrmSessionClient() {}
+String8 DrmHal::DrmSessionClient::getName() {
+ String8 name;
+ sp<DrmHal> drm = mDrm.promote();
+ if (drm == NULL) {
+ name.append("<deleted>");
+ } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK
+ || name.isEmpty()) {
+ name.append("<Get vendor failed or is empty>");
+ }
+ name.append("[");
+ for (size_t i = 0; i < mSessionId.size(); ++i) {
+ name.appendFormat("%02x", mSessionId[i]);
+ }
+ name.append("]");
+ return name;
+}
-private:
- wp<DrmHal> mDrm;
-
- DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
-};
+DrmHal::DrmSessionClient::~DrmSessionClient() {
+ DrmSessionManager::Instance()->removeSession(mSessionId);
+}
DrmHal::DrmHal()
- : mDrmSessionClient(new DrmSessionClient(this)),
- mFactories(makeDrmFactories()),
+ : mFactories(makeDrmFactories()),
mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
}
@@ -333,14 +340,13 @@
auto openSessions = mOpenSessions;
for (size_t i = 0; i < openSessions.size(); i++) {
mLock.unlock();
- closeSession(openSessions[i]);
+ closeSession(openSessions[i]->mSessionId);
mLock.lock();
}
mOpenSessions.clear();
}
DrmHal::~DrmHal() {
- DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
}
void DrmHal::cleanup() {
@@ -746,9 +752,9 @@
} while (retry);
if (err == OK) {
- DrmSessionManager::Instance()->addSession(getCallingPid(),
- mDrmSessionClient, sessionId);
- mOpenSessions.push(sessionId);
+ sp<DrmSessionClient> client(new DrmSessionClient(this, sessionId));
+ DrmSessionManager::Instance()->addSession(getCallingPid(), client, sessionId);
+ mOpenSessions.push(client);
mMetrics.SetSessionStart(sessionId);
}
@@ -765,7 +771,7 @@
if (status == Status::OK) {
DrmSessionManager::Instance()->removeSession(sessionId);
for (size_t i = 0; i < mOpenSessions.size(); i++) {
- if (mOpenSessions[i] == sessionId) {
+ if (isEqualSessionId(mOpenSessions[i]->mSessionId, sessionId)) {
mOpenSessions.removeAt(i);
break;
}
diff --git a/drm/libmediadrm/DrmSessionManager.cpp b/drm/libmediadrm/DrmSessionManager.cpp
index 375644c..0b927ef 100644
--- a/drm/libmediadrm/DrmSessionManager.cpp
+++ b/drm/libmediadrm/DrmSessionManager.cpp
@@ -21,12 +21,17 @@
#include <binder/IPCThreadState.h>
#include <binder/IProcessInfoService.h>
#include <binder/IServiceManager.h>
-#include <media/stagefright/ProcessInfo.h>
-#include <mediadrm/DrmSessionClientInterface.h>
+#include <cutils/properties.h>
+#include <media/IResourceManagerClient.h>
+#include <media/MediaResource.h>
#include <mediadrm/DrmSessionManager.h>
#include <unistd.h>
#include <utils/String8.h>
+#include <vector>
+
+#include "ResourceManagerService.h"
+
namespace android {
static String8 GetSessionIdString(const Vector<uint8_t> &sessionId) {
@@ -37,6 +42,35 @@
return sessionIdStr;
}
+static std::vector<uint8_t> toStdVec(const Vector<uint8_t> &vector) {
+ const uint8_t *v = vector.array();
+ std::vector<uint8_t> vec(v, v + vector.size());
+ return vec;
+}
+
+static uint64_t toClientId(const sp<IResourceManagerClient>& drm) {
+ return reinterpret_cast<int64_t>(drm.get());
+}
+
+static Vector<MediaResource> toResourceVec(const Vector<uint8_t> &sessionId) {
+ Vector<MediaResource> resources;
+ // use UINT64_MAX to decrement through addition overflow
+ resources.push_back(MediaResource(MediaResource::kDrmSession, toStdVec(sessionId), UINT64_MAX));
+ return resources;
+}
+
+static sp<IResourceManagerService> getResourceManagerService() {
+ if (property_get_bool("persist.device_config.media_native.mediadrmserver", 1)) {
+ return new ResourceManagerService();
+ }
+ sp<IServiceManager> sm = defaultServiceManager();
+ if (sm == NULL) {
+ return NULL;
+ }
+ sp<IBinder> binder = sm->getService(String16("media.resource_manager"));
+ return interface_cast<IResourceManagerService>(binder);
+}
+
bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2) {
if (sessionId1.size() != sessionId2.size()) {
return false;
@@ -51,189 +85,114 @@
sp<DrmSessionManager> DrmSessionManager::Instance() {
static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager();
+ drmSessionManager->init();
return drmSessionManager;
}
DrmSessionManager::DrmSessionManager()
- : mProcessInfo(new ProcessInfo()),
- mTime(0) {}
+ : DrmSessionManager(getResourceManagerService()) {
+}
-DrmSessionManager::DrmSessionManager(sp<ProcessInfoInterface> processInfo)
- : mProcessInfo(processInfo),
- mTime(0) {}
+DrmSessionManager::DrmSessionManager(const sp<IResourceManagerService> &service)
+ : mService(service),
+ mInitialized(false) {
+ if (mService == NULL) {
+ ALOGE("Failed to init ResourceManagerService");
+ }
+}
-DrmSessionManager::~DrmSessionManager() {}
+DrmSessionManager::~DrmSessionManager() {
+ if (mService != NULL) {
+ IInterface::asBinder(mService)->unlinkToDeath(this);
+ }
+}
-void DrmSessionManager::addSession(
- int pid, const sp<DrmSessionClientInterface>& drm, const Vector<uint8_t> &sessionId) {
- ALOGV("addSession(pid %d, drm %p, sessionId %s)", pid, drm.get(),
+void DrmSessionManager::init() {
+ Mutex::Autolock lock(mLock);
+ if (mInitialized) {
+ return;
+ }
+ mInitialized = true;
+ if (mService != NULL) {
+ IInterface::asBinder(mService)->linkToDeath(this);
+ }
+}
+
+void DrmSessionManager::addSession(int pid,
+ const sp<IResourceManagerClient>& drm, const Vector<uint8_t> &sessionId) {
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ ALOGV("addSession(pid %d, uid %d, drm %p, sessionId %s)", pid, uid, drm.get(),
GetSessionIdString(sessionId).string());
Mutex::Autolock lock(mLock);
- SessionInfo info;
- info.drm = drm;
- info.sessionId = sessionId;
- info.timeStamp = getTime_l();
- ssize_t index = mSessionMap.indexOfKey(pid);
- if (index < 0) {
- // new pid
- SessionInfos infosForPid;
- infosForPid.push_back(info);
- mSessionMap.add(pid, infosForPid);
- } else {
- mSessionMap.editValueAt(index).push_back(info);
+ if (mService == NULL) {
+ return;
}
+
+ int64_t clientId = toClientId(drm);
+ mSessionMap[toStdVec(sessionId)] = (SessionInfo){pid, uid, clientId};
+ mService->addResource(pid, uid, clientId, drm, toResourceVec(sessionId));
}
void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
ALOGV("useSession(%s)", GetSessionIdString(sessionId).string());
Mutex::Autolock lock(mLock);
- for (size_t i = 0; i < mSessionMap.size(); ++i) {
- SessionInfos& infos = mSessionMap.editValueAt(i);
- for (size_t j = 0; j < infos.size(); ++j) {
- SessionInfo& info = infos.editItemAt(j);
- if (isEqualSessionId(sessionId, info.sessionId)) {
- info.timeStamp = getTime_l();
- return;
- }
- }
+ auto it = mSessionMap.find(toStdVec(sessionId));
+ if (mService == NULL || it == mSessionMap.end()) {
+ return;
}
+
+ auto info = it->second;
+ mService->addResource(info.pid, info.uid, info.clientId, NULL, toResourceVec(sessionId));
}
void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) {
ALOGV("removeSession(%s)", GetSessionIdString(sessionId).string());
Mutex::Autolock lock(mLock);
- for (size_t i = 0; i < mSessionMap.size(); ++i) {
- SessionInfos& infos = mSessionMap.editValueAt(i);
- for (size_t j = 0; j < infos.size(); ++j) {
- if (isEqualSessionId(sessionId, infos[j].sessionId)) {
- infos.removeAt(j);
- return;
- }
- }
+ auto it = mSessionMap.find(toStdVec(sessionId));
+ if (mService == NULL || it == mSessionMap.end()) {
+ return;
}
-}
-void DrmSessionManager::removeDrm(const sp<DrmSessionClientInterface>& drm) {
- ALOGV("removeDrm(%p)", drm.get());
-
- Mutex::Autolock lock(mLock);
- bool found = false;
- for (size_t i = 0; i < mSessionMap.size(); ++i) {
- SessionInfos& infos = mSessionMap.editValueAt(i);
- for (size_t j = 0; j < infos.size();) {
- if (infos[j].drm == drm) {
- ALOGV("removed session (%s)", GetSessionIdString(infos[j].sessionId).string());
- j = infos.removeAt(j);
- found = true;
- } else {
- ++j;
- }
- }
- if (found) {
- break;
- }
- }
+ auto info = it->second;
+ mService->removeResource(info.pid, info.clientId, toResourceVec(sessionId));
+ mSessionMap.erase(it);
}
bool DrmSessionManager::reclaimSession(int callingPid) {
ALOGV("reclaimSession(%d)", callingPid);
- sp<DrmSessionClientInterface> drm;
- Vector<uint8_t> sessionId;
- int lowestPriorityPid;
- int lowestPriority;
- {
- Mutex::Autolock lock(mLock);
- int callingPriority;
- if (!mProcessInfo->getPriority(callingPid, &callingPriority)) {
- return false;
- }
- if (!getLowestPriority_l(&lowestPriorityPid, &lowestPriority)) {
- return false;
- }
- if (lowestPriority <= callingPriority) {
- return false;
- }
+ // unlock early because reclaimResource might callback into removeSession
+ mLock.lock();
+ sp<IResourceManagerService> service(mService);
+ mLock.unlock();
- if (!getLeastUsedSession_l(lowestPriorityPid, &drm, &sessionId)) {
- return false;
- }
- }
-
- if (drm == NULL) {
+ if (service == NULL) {
return false;
}
- ALOGV("reclaim session(%s) opened by pid %d",
- GetSessionIdString(sessionId).string(), lowestPriorityPid);
-
- return drm->reclaimSession(sessionId);
+ // cannot update mSessionMap because we do not know which sessionId is reclaimed;
+ // we rely on IResourceManagerClient to removeSession in reclaimResource
+ Vector<uint8_t> dummy;
+ return service->reclaimResource(callingPid, toResourceVec(dummy));
}
-int64_t DrmSessionManager::getTime_l() {
- return mTime++;
+size_t DrmSessionManager::getSessionCount() const {
+ Mutex::Autolock lock(mLock);
+ return mSessionMap.size();
}
-bool DrmSessionManager::getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority) {
- int pid = -1;
- int priority = -1;
- for (size_t i = 0; i < mSessionMap.size(); ++i) {
- if (mSessionMap.valueAt(i).size() == 0) {
- // no opened session by this process.
- continue;
- }
- int tempPid = mSessionMap.keyAt(i);
- int tempPriority;
- if (!mProcessInfo->getPriority(tempPid, &tempPriority)) {
- // shouldn't happen.
- return false;
- }
- if (pid == -1) {
- pid = tempPid;
- priority = tempPriority;
- } else {
- if (tempPriority > priority) {
- pid = tempPid;
- priority = tempPriority;
- }
- }
- }
- if (pid != -1) {
- *lowestPriorityPid = pid;
- *lowestPriority = priority;
- }
- return (pid != -1);
+bool DrmSessionManager::containsSession(const Vector<uint8_t>& sessionId) const {
+ Mutex::Autolock lock(mLock);
+ return mSessionMap.count(toStdVec(sessionId));
}
-bool DrmSessionManager::getLeastUsedSession_l(
- int pid, sp<DrmSessionClientInterface>* drm, Vector<uint8_t>* sessionId) {
- ssize_t index = mSessionMap.indexOfKey(pid);
- if (index < 0) {
- return false;
- }
-
- int leastUsedIndex = -1;
- int64_t minTs = LLONG_MAX;
- const SessionInfos& infos = mSessionMap.valueAt(index);
- for (size_t j = 0; j < infos.size(); ++j) {
- if (leastUsedIndex == -1) {
- leastUsedIndex = j;
- minTs = infos[j].timeStamp;
- } else {
- if (infos[j].timeStamp < minTs) {
- leastUsedIndex = j;
- minTs = infos[j].timeStamp;
- }
- }
- }
- if (leastUsedIndex != -1) {
- *drm = infos[leastUsedIndex].drm;
- *sessionId = infos[leastUsedIndex].sessionId;
- }
- return (leastUsedIndex != -1);
+void DrmSessionManager::binderDied(const wp<IBinder>& /*who*/) {
+ ALOGW("ResourceManagerService died.");
+ Mutex::Autolock lock(mLock);
+ mService.clear();
}
} // namespace android
diff --git a/drm/libmediadrm/include/mediadrm/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
index bdf1b30..542d300 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHal.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -26,8 +26,10 @@
#include <android/hardware/drm/1.2/IDrmPlugin.h>
#include <android/hardware/drm/1.2/IDrmPluginListener.h>
+#include <media/IResourceManagerService.h>
#include <media/MediaAnalyticsItem.h>
#include <mediadrm/DrmMetrics.h>
+#include <mediadrm/DrmSessionManager.h>
#include <mediadrm/IDrm.h>
#include <mediadrm/IDrmClient.h>
#include <utils/threads.h>
@@ -59,6 +61,26 @@
struct DrmHal : public BnDrm,
public IBinder::DeathRecipient,
public IDrmPluginListener_V1_2 {
+
+ struct DrmSessionClient : public BnResourceManagerClient {
+ explicit DrmSessionClient(DrmHal* drm, const Vector<uint8_t>& sessionId)
+ : mSessionId(sessionId),
+ mDrm(drm) {}
+
+ virtual bool reclaimResource();
+ virtual String8 getName();
+
+ const Vector<uint8_t> mSessionId;
+
+ protected:
+ virtual ~DrmSessionClient();
+
+ private:
+ wp<DrmHal> mDrm;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
+ };
+
DrmHal();
virtual ~DrmHal();
@@ -193,8 +215,6 @@
private:
static Mutex mLock;
- sp<DrmSessionClientInterface> mDrmSessionClient;
-
sp<IDrmClient> mListener;
mutable Mutex mEventLock;
mutable Mutex mNotifyLock;
@@ -208,7 +228,7 @@
// Mutable to allow modification within GetPropertyByteArray.
mutable MediaDrmMetrics mMetrics;
- Vector<Vector<uint8_t>> mOpenSessions;
+ Vector<sp<DrmSessionClient>> mOpenSessions;
void closeOpenSessions();
void cleanup();
diff --git a/drm/libmediadrm/include/mediadrm/DrmSessionManager.h b/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
index ba27199..b1ad580 100644
--- a/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
+++ b/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
@@ -18,56 +18,61 @@
#define DRM_SESSION_MANAGER_H_
+#include <binder/IBinder.h>
+#include <media/IResourceManagerService.h>
#include <media/stagefright/foundation/ABase.h>
#include <utils/RefBase.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
#include <utils/Vector.h>
+#include <map>
+#include <utility>
+#include <vector>
+
namespace android {
class DrmSessionManagerTest;
-struct DrmSessionClientInterface;
-struct ProcessInfoInterface;
+class IResourceManagerClient;
bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2);
struct SessionInfo {
- sp<DrmSessionClientInterface> drm;
- Vector<uint8_t> sessionId;
- int64_t timeStamp;
+ pid_t pid;
+ uid_t uid;
+ int64_t clientId;
};
-typedef Vector<SessionInfo > SessionInfos;
-typedef KeyedVector<int, SessionInfos > PidSessionInfosMap;
+typedef std::map<std::vector<uint8_t>, SessionInfo> SessionInfoMap;
-struct DrmSessionManager : public RefBase {
+struct DrmSessionManager : public IBinder::DeathRecipient {
static sp<DrmSessionManager> Instance();
DrmSessionManager();
- explicit DrmSessionManager(sp<ProcessInfoInterface> processInfo);
+ explicit DrmSessionManager(const sp<IResourceManagerService> &service);
- void addSession(int pid, const sp<DrmSessionClientInterface>& drm, const Vector<uint8_t>& sessionId);
+ void addSession(int pid, const sp<IResourceManagerClient>& drm, const Vector<uint8_t>& sessionId);
void useSession(const Vector<uint8_t>& sessionId);
void removeSession(const Vector<uint8_t>& sessionId);
- void removeDrm(const sp<DrmSessionClientInterface>& drm);
bool reclaimSession(int callingPid);
+ // sanity check APIs
+ size_t getSessionCount() const;
+ bool containsSession(const Vector<uint8_t>& sessionId) const;
+
+ // implements DeathRecipient
+ virtual void binderDied(const wp<IBinder>& /*who*/);
+
protected:
virtual ~DrmSessionManager();
private:
- friend class DrmSessionManagerTest;
+ void init();
- int64_t getTime_l();
- bool getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority);
- bool getLeastUsedSession_l(
- int pid, sp<DrmSessionClientInterface>* drm, Vector<uint8_t>* sessionId);
-
- sp<ProcessInfoInterface> mProcessInfo;
+ sp<IResourceManagerService> mService;
mutable Mutex mLock;
- PidSessionInfosMap mSessionMap;
- int64_t mTime;
+ SessionInfoMap mSessionMap;
+ bool mInitialized;
DISALLOW_EVIL_CONSTRUCTORS(DrmSessionManager);
};
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 1b1f149..8aec80d 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -575,7 +575,7 @@
class AudioTrackServerProxy : public ServerProxy {
public:
AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
- size_t frameSize, bool clientInServer = false, uint32_t sampleRate = 0)
+ size_t frameSize, bool clientInServer, uint32_t sampleRate)
: ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer),
mPlaybackRateObserver(&cblk->mPlaybackRateQueue),
mUnderrunCount(0), mUnderrunning(false), mDrained(true) {
@@ -651,7 +651,7 @@
class StaticAudioTrackServerProxy : public AudioTrackServerProxy {
public:
StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
- size_t frameSize);
+ size_t frameSize, uint32_t sampleRate);
protected:
virtual ~StaticAudioTrackServerProxy() { }
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index 3f3ef69..5484613 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -6,10 +6,10 @@
capabilities BLOCK_SUSPEND
ioprio rt 4
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
- onrestart restart vendor.audio-hal-2-0
+ onrestart restart vendor.audio-hal
onrestart restart vendor.audio-hal-4-0-msd
- # Keep the original service name for backward compatibility when upgrading
- # O-MR1 devices with framework-only.
+ # Keep the original service names for backward compatibility
+ onrestart restart vendor.audio-hal-2-0
onrestart restart audio-hal-2-0
on property:vts.native_server.on=1
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 3820f90..f9eb2fa 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -243,6 +243,9 @@
kParamIndexTimestampGapAdjustment, // input-surface, struct
kParamIndexSurfaceAllocator, // u32
+
+ // low latency mode for decoders
+ kParamIndexLowLatencyMode, // bool
};
}
@@ -521,6 +524,7 @@
PROFILE_DV_HE_07 = _C2_PL_DV_BASE + 7, ///< Dolby Vision dvhe.07 profile
PROFILE_DV_HE_08 = _C2_PL_DV_BASE + 8, ///< Dolby Vision dvhe.08 profile
PROFILE_DV_AV_09 = _C2_PL_DV_BASE + 9, ///< Dolby Vision dvav.09 profile
+ PROFILE_DV_AV1_10 = _C2_PL_DV_BASE + 10, ///< Dolby Vision dav1.10 profile
// AV1 profiles
PROFILE_AV1_0 = _C2_PL_AV1_BASE, ///< AV1 Profile 0 (4:2:0, 8 to 10 bit)
@@ -804,6 +808,15 @@
constexpr char C2_PARAMKEY_PIPELINE_DELAY[] = "algo.delay";
/**
+ * Enable/disable low latency decoding mode.
+ * If true, low latency decoding mode is enabled, and the decoder doesn't hold input and output
+ * data more than required by the codec standards.
+ */
+typedef C2GlobalParam<C2Tuning, C2EasyBoolValue, kParamIndexLowLatencyMode>
+ C2GlobalLowLatencyModeTuning;
+constexpr char C2_PARAMKEY_LOW_LATENCY_MODE[] = "algo.low-latency";
+
+/**
* Reference characteristics.
*
* The component may hold onto input and output buffers even after completing the corresponding
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 5adcd94..ee3cdf6 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -823,6 +823,14 @@
add(ConfigMapper(C2_PARAMKEY_INPUT_TIME_STRETCH, C2_PARAMKEY_INPUT_TIME_STRETCH, "value"));
+ add(ConfigMapper(KEY_LOW_LATENCY, C2_PARAMKEY_LOW_LATENCY_MODE, "value")
+ .limitTo(D::DECODER & (D::CONFIG | D::PARAM))
+ .withMapper([](C2Value v) -> C2Value {
+ int32_t value = 0;
+ (void)v.get(&value);
+ return value == 0 ? C2_FALSE : C2_TRUE;
+ }));
+
/* still to do
constexpr char KEY_PUSH_BLANK_BUFFERS_ON_STOP[] = "push-blank-buffers-on-shutdown";
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index ef6af48..2f3d688 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -190,6 +190,7 @@
{ C2Config::PROFILE_DV_HE_07, DolbyVisionProfileDvheDtb },
{ C2Config::PROFILE_DV_HE_08, DolbyVisionProfileDvheSt },
{ C2Config::PROFILE_DV_AV_09, DolbyVisionProfileDvavSe },
+ { C2Config::PROFILE_DV_AV1_10, DolbyVisionProfileDvav110 },
};
ALookup<C2Config::level_t, int32_t> sH263Levels = {
diff --git a/media/codec2/vndk/C2AllocatorIon.cpp b/media/codec2/vndk/C2AllocatorIon.cpp
index 752bc46..0470a31 100644
--- a/media/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/codec2/vndk/C2AllocatorIon.cpp
@@ -600,7 +600,7 @@
}
std::shared_ptr<C2AllocationIon> alloc
- = std::make_shared<C2AllocationIon>(dup(mIonFd), capacity, align, heapMask, flags, mTraits->id);
+ = std::make_shared<C2AllocationIon>(dup(mIonFd), capacity, align, heapMask, flags, getId());
ret = alloc->status();
if (ret == C2_OK) {
*allocation = alloc;
@@ -622,7 +622,7 @@
// TODO: get capacity and validate it
const C2HandleIon *h = static_cast<const C2HandleIon*>(handle);
std::shared_ptr<C2AllocationIon> alloc
- = std::make_shared<C2AllocationIon>(dup(mIonFd), h->size(), h->bufferFd(), mTraits->id);
+ = std::make_shared<C2AllocationIon>(dup(mIonFd), h->size(), h->bufferFd(), getId());
c2_status_t ret = alloc->status();
if (ret == C2_OK) {
*allocation = alloc;
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index b91d16f..81e1b8c 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -133,6 +133,7 @@
bool mIsAVC;
bool mIsHEVC;
+ bool mIsDolbyVision;
bool mIsAC4;
bool mIsPcm;
size_t mNALLengthSize;
@@ -337,6 +338,14 @@
case FOURCC("hvc1"):
case FOURCC("hev1"):
return MEDIA_MIMETYPE_VIDEO_HEVC;
+
+ case FOURCC("dvav"):
+ case FOURCC("dva1"):
+ case FOURCC("dvhe"):
+ case FOURCC("dvh1"):
+ case FOURCC("dav1"):
+ return MEDIA_MIMETYPE_VIDEO_DOLBY_VISION;
+
case FOURCC("ac-4"):
return MEDIA_MIMETYPE_AUDIO_AC4;
case FOURCC("Opus"):
@@ -1062,6 +1071,62 @@
mLastTrack->mTx3gBuffer = NULL;
}
+ const char *mime;
+ AMediaFormat_getString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, &mime);
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
+ void *data;
+ size_t size;
+
+ if (AMediaFormat_getBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_2, &data, &size)) {
+ const uint8_t *ptr = (const uint8_t *)data;
+ const uint8_t profile = ptr[2] >> 1;
+ const uint8_t bl_compatibility_id = (ptr[4]) >> 4;
+
+ if (4 == profile || 7 == profile ||
+ (profile >= 8 && profile < 11 && bl_compatibility_id)) {
+ // we need a backward compatible track
+ ALOGV("Adding new backward compatible track");
+ Track *track_b = new Track;
+
+ track_b->timescale = mLastTrack->timescale;
+ track_b->sampleTable = mLastTrack->sampleTable;
+ track_b->includes_expensive_metadata = mLastTrack->includes_expensive_metadata;
+ track_b->skipTrack = mLastTrack->skipTrack;
+ track_b->has_elst = mLastTrack->has_elst;
+ track_b->elst_media_time = mLastTrack->elst_media_time;
+ track_b->elst_segment_duration = mLastTrack->elst_segment_duration;
+ track_b->elstShiftStartTicks = mLastTrack->elstShiftStartTicks;
+ track_b->subsample_encryption = mLastTrack->subsample_encryption;
+
+ track_b->mTx3gBuffer = mLastTrack->mTx3gBuffer;
+ track_b->mTx3gSize = mLastTrack->mTx3gSize;
+ track_b->mTx3gFilled = mLastTrack->mTx3gFilled;
+
+ track_b->meta = AMediaFormat_new();
+ AMediaFormat_copy(track_b->meta, mLastTrack->meta);
+
+ mLastTrack->next = track_b;
+ track_b->next = NULL;
+
+ auto id = track_b->meta->mFormat->findEntryByName(AMEDIAFORMAT_KEY_CSD_2);
+ track_b->meta->mFormat->removeEntryAt(id);
+
+ if (4 == profile || 7 == profile || 8 == profile ) {
+ AMediaFormat_setString(track_b->meta,
+ AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_HEVC);
+ } else if (9 == profile) {
+ AMediaFormat_setString(track_b->meta,
+ AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AVC);
+ } else if (10 == profile) {
+ AMediaFormat_setString(track_b->meta,
+ AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AV1);
+ } // Should never get to else part
+
+ mLastTrack = track_b;
+ }
+ }
+ }
} else if (chunk_type == FOURCC("moov")) {
mInitCheck = OK;
@@ -1830,6 +1895,11 @@
case FOURCC("avc1"):
case FOURCC("hvc1"):
case FOURCC("hev1"):
+ case FOURCC("dvav"):
+ case FOURCC("dva1"):
+ case FOURCC("dvhe"):
+ case FOURCC("dvh1"):
+ case FOURCC("dav1"):
case FOURCC("av01"):
{
uint8_t buffer[78];
@@ -1984,7 +2054,8 @@
// for audio, use 128KB
max_size = 1024 * 128;
} else if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
- || !strcmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
+ || !strcmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)
+ || !strcmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
// AVC & HEVC requires compression ratio of at least 2, and uses
// macroblocks
max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
@@ -2315,6 +2386,30 @@
*offset += chunk_size;
break;
}
+ case FOURCC("dvcC"):
+ case FOURCC("dvvC"): {
+ auto buffer = heapbuffer<uint8_t>(chunk_data_size);
+
+ if (buffer.get() == NULL) {
+ ALOGE("b/28471206");
+ return NO_MEMORY;
+ }
+
+ if (mDataSource->readAt(data_offset, buffer.get(), chunk_data_size) < chunk_data_size) {
+ return ERROR_IO;
+ }
+
+ if (mLastTrack == NULL)
+ return ERROR_MALFORMED;
+
+ AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_2,
+ buffer.get(), chunk_data_size);
+ AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME,
+ MEDIA_MIMETYPE_VIDEO_DOLBY_VISION);
+
+ *offset += chunk_size;
+ break;
+ }
case FOURCC("d263"):
{
*offset += chunk_size;
@@ -4127,7 +4222,20 @@
if (!strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)) {
itemTable = mItemTable;
}
- } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AV1)) {
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
+ void *data;
+ size_t size;
+ if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_2, &data, &size)) {
+ return NULL;
+ }
+
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ // dv_major.dv_minor Should be 1.0 or 2.1
+ if (size != 24 || ((ptr[0] != 1 || ptr[1] != 0) && (ptr[0] != 2 || ptr[1] != 1))) {
+ return NULL;
+ }
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AV1)) {
void *data;
size_t size;
if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_0, &data, &size)) {
@@ -4172,6 +4280,10 @@
if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_HEVC, &data, &size)) {
return ERROR_MALFORMED;
}
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
+ if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_2, &data, &size)) {
+ return ERROR_MALFORMED;
+ }
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AV1)) {
if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_0, &data, &size)) {
return ERROR_MALFORMED;
@@ -4659,6 +4771,7 @@
mCurrentSampleInfoOffsets(NULL),
mIsAVC(false),
mIsHEVC(false),
+ mIsDolbyVision(false),
mIsAC4(false),
mIsPcm(false),
mNALLengthSize(0),
@@ -4698,6 +4811,7 @@
mIsHEVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC) ||
!strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC);
mIsAC4 = !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC4);
+ mIsDolbyVision = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION);
if (mIsAVC) {
void *data;
@@ -4722,6 +4836,42 @@
CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
mNALLengthSize = 1 + (ptr[14 + 7] & 3);
+ } else if (mIsDolbyVision) {
+ ALOGV("%s DolbyVision stream detected", __FUNCTION__);
+ void *data;
+ size_t size;
+ CHECK(AMediaFormat_getBuffer(format, AMEDIAFORMAT_KEY_CSD_2, &data, &size));
+
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ CHECK(size == 24);
+
+ // dv_major.dv_minor Should be 1.0 or 2.1
+ CHECK(!((ptr[0] != 1 || ptr[1] != 0) && (ptr[0] != 2 || ptr[1] != 1)));
+
+ const uint8_t profile = ptr[2] >> 1;
+ // profile == (unknown,1,9) --> AVC; profile = (2,3,4,5,6,7,8) --> HEVC;
+ // profile == (10) --> AV1
+ if (profile > 1 && profile < 9) {
+ CHECK(AMediaFormat_getBuffer(format, AMEDIAFORMAT_KEY_CSD_HEVC, &data, &size));
+
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ CHECK(size >= 22);
+ CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
+
+ mNALLengthSize = 1 + (ptr[14 + 7] & 3);
+ } else if (10 == profile) {
+ /* AV1 profile nothing to do */
+ } else {
+ CHECK(AMediaFormat_getBuffer(format, AMEDIAFORMAT_KEY_CSD_AVC, &data, &size));
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ CHECK(size >= 7);
+ CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
+ // The number of bytes used to encode the length of a NAL unit.
+ mNALLengthSize = 1 + (ptr[4] & 3);
+ }
}
mIsPcm = !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW);
@@ -5789,7 +5939,7 @@
}
}
- if (!mIsAVC && !mIsHEVC && !mIsAC4) {
+ if (!mIsAVC && !mIsHEVC && !(mIsDolbyVision && mNALLengthSize) && !mIsAC4) {
if (newBuffer) {
if (mIsPcm) {
// The twos' PCM block reader assumes that all samples has the same size.
@@ -6179,7 +6329,7 @@
AMediaFormat_setBuffer(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_IV, iv, ivlength);
}
- if (!mIsAVC && !mIsHEVC) {
+ if (!mIsAVC && !mIsHEVC && !(mIsDolbyVision && mNALLengthSize)) {
if (newBuffer) {
if (!isInRange((size_t)0u, mBuffer->size(), size)) {
mBuffer->release();
diff --git a/media/libaudioclient/AudioTrackShared.cpp b/media/libaudioclient/AudioTrackShared.cpp
index ee6c335..f1f8f9c 100644
--- a/media/libaudioclient/AudioTrackShared.cpp
+++ b/media/libaudioclient/AudioTrackShared.cpp
@@ -984,8 +984,9 @@
// ---------------------------------------------------------------------------
StaticAudioTrackServerProxy::StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers,
- size_t frameCount, size_t frameSize)
- : AudioTrackServerProxy(cblk, buffers, frameCount, frameSize),
+ size_t frameCount, size_t frameSize, uint32_t sampleRate)
+ : AudioTrackServerProxy(cblk, buffers, frameCount, frameSize, false /*clientInServer*/,
+ sampleRate),
mObserver(&cblk->u.mStatic.mSingleStateQueue),
mPosLoopMutator(&cblk->u.mStatic.mPosLoopQueue),
mFramesReadySafe(frameCount), mFramesReady(frameCount),
diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp
index fcb07e7..3970583 100644
--- a/media/libaudiofoundation/Android.bp
+++ b/media/libaudiofoundation/Android.bp
@@ -9,6 +9,7 @@
vendor_available: true,
srcs: [
+ "AudioContainers.cpp",
"AudioGain.cpp",
"AudioPort.cpp",
"AudioProfile.cpp",
diff --git a/media/libaudiofoundation/AudioContainers.cpp b/media/libaudiofoundation/AudioContainers.cpp
new file mode 100644
index 0000000..adc5d40
--- /dev/null
+++ b/media/libaudiofoundation/AudioContainers.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+#include <string>
+
+#include <media/AudioContainers.h>
+
+namespace android {
+
+const DeviceTypeSet& getAudioDeviceOutAllSet() {
+ static const DeviceTypeSet audioDeviceOutAllSet = DeviceTypeSet(
+ std::begin(AUDIO_DEVICE_OUT_ALL_ARRAY),
+ std::end(AUDIO_DEVICE_OUT_ALL_ARRAY));
+ return audioDeviceOutAllSet;
+}
+
+const DeviceTypeSet& getAudioDeviceOutAllA2dpSet() {
+ static const DeviceTypeSet audioDeviceOutAllA2dpSet = DeviceTypeSet(
+ std::begin(AUDIO_DEVICE_OUT_ALL_A2DP_ARRAY),
+ std::end(AUDIO_DEVICE_OUT_ALL_A2DP_ARRAY));
+ return audioDeviceOutAllA2dpSet;
+}
+
+const DeviceTypeSet& getAudioDeviceOutAllScoSet() {
+ static const DeviceTypeSet audioDeviceOutAllScoSet = DeviceTypeSet(
+ std::begin(AUDIO_DEVICE_OUT_ALL_SCO_ARRAY),
+ std::end(AUDIO_DEVICE_OUT_ALL_SCO_ARRAY));
+ return audioDeviceOutAllScoSet;
+}
+
+const DeviceTypeSet& getAudioDeviceInAllSet() {
+ static const DeviceTypeSet audioDeviceInAllSet = DeviceTypeSet(
+ std::begin(AUDIO_DEVICE_IN_ALL_ARRAY),
+ std::end(AUDIO_DEVICE_IN_ALL_ARRAY));
+ return audioDeviceInAllSet;
+}
+
+bool deviceTypesToString(const DeviceTypeSet &deviceTypes, std::string &str) {
+ bool ret = true;
+ for (auto it = deviceTypes.begin(); it != deviceTypes.end();) {
+ std::string deviceTypeStr;
+ ret = audio_is_output_device(*it) ?
+ OutputDeviceConverter::toString(*it, deviceTypeStr) :
+ InputDeviceConverter::toString(*it, deviceTypeStr);
+ if (!ret) {
+ break;
+ }
+ str.append(deviceTypeStr);
+ if (++it != deviceTypes.end()) {
+ str.append(" , ");
+ }
+ }
+ if (!ret) {
+ str = "Unknown values";
+ }
+ return ret;
+}
+
+std::string dumpDeviceTypes(const DeviceTypeSet &deviceTypes) {
+ std::string ret;
+ for (auto it = deviceTypes.begin(); it != deviceTypes.end();) {
+ std::stringstream ss;
+ ss << "0x" << std::hex << (*it);
+ ret.append(ss.str());
+ if (++it != deviceTypes.end()) {
+ ret.append(" , ");
+ }
+ }
+ return ret;
+}
+
+} // namespace android
diff --git a/media/libaudiofoundation/AudioGain.cpp b/media/libaudiofoundation/AudioGain.cpp
index 9d1d6db..0d28335 100644
--- a/media/libaudiofoundation/AudioGain.cpp
+++ b/media/libaudiofoundation/AudioGain.cpp
@@ -24,6 +24,8 @@
#define ALOGVV(a...) do { } while(0)
#endif
+#include <algorithm>
+
#include <android-base/stringprintf.h>
#include <media/AudioGain.h>
#include <utils/Log.h>
@@ -111,6 +113,22 @@
dst->append(base::StringPrintf("%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms));
}
+bool AudioGain::equals(const sp<AudioGain>& other) const
+{
+ return other != nullptr &&
+ mUseInChannelMask == other->mUseInChannelMask &&
+ mUseForVolume == other->mUseForVolume &&
+ // Compare audio gain
+ mGain.mode == other->mGain.mode &&
+ mGain.channel_mask == other->mGain.channel_mask &&
+ mGain.min_value == other->mGain.min_value &&
+ mGain.max_value == other->mGain.max_value &&
+ mGain.default_value == other->mGain.default_value &&
+ mGain.step_value == other->mGain.step_value &&
+ mGain.min_ramp_ms == other->mGain.min_ramp_ms &&
+ mGain.max_ramp_ms == other->mGain.max_ramp_ms;
+}
+
status_t AudioGain::writeToParcel(android::Parcel *parcel) const
{
status_t status = NO_ERROR;
@@ -145,9 +163,17 @@
return status;
}
+bool AudioGains::equals(const AudioGains &other) const
+{
+ return std::equal(begin(), end(), other.begin(), other.end(),
+ [](const sp<AudioGain>& left, const sp<AudioGain>& right) {
+ return left->equals(right);
+ });
+}
+
status_t AudioGains::writeToParcel(android::Parcel *parcel) const {
status_t status = NO_ERROR;
- if ((status = parcel->writeUint64(this->size())) != NO_ERROR) return status;
+ if ((status = parcel->writeVectorSize(*this)) != NO_ERROR) return status;
for (const auto &audioGain : *this) {
if ((status = parcel->writeParcelable(*audioGain)) != NO_ERROR) {
break;
@@ -158,15 +184,14 @@
status_t AudioGains::readFromParcel(const android::Parcel *parcel) {
status_t status = NO_ERROR;
- uint64_t count;
- if ((status = parcel->readUint64(&count)) != NO_ERROR) return status;
- for (uint64_t i = 0; i < count; i++) {
- sp<AudioGain> audioGain = new AudioGain(0, false);
- if ((status = parcel->readParcelable(audioGain.get())) != NO_ERROR) {
+ this->clear();
+ if ((status = parcel->resizeOutVector(this)) != NO_ERROR) return status;
+ for (size_t i = 0; i < this->size(); i++) {
+ this->at(i) = new AudioGain(0, false);
+ if ((status = parcel->readParcelable(this->at(i).get())) != NO_ERROR) {
this->clear();
break;
}
- this->push_back(audioGain);
}
return status;
}
diff --git a/media/libaudiofoundation/AudioPort.cpp b/media/libaudiofoundation/AudioPort.cpp
index cde31e4..f988690 100644
--- a/media/libaudiofoundation/AudioPort.cpp
+++ b/media/libaudiofoundation/AudioPort.cpp
@@ -105,6 +105,46 @@
ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.c_str(), mType, mRole);
}
+bool AudioPort::equals(const sp<AudioPort> &other) const
+{
+ return other != nullptr &&
+ mGains.equals(other->getGains()) &&
+ mName.compare(other->getName()) == 0 &&
+ mType == other->getType() &&
+ mRole == other->getRole() &&
+ mProfiles.equals(other->getAudioProfiles());
+}
+
+status_t AudioPort::writeToParcel(Parcel *parcel) const
+{
+ status_t status = NO_ERROR;
+ if ((status = parcel->writeUtf8AsUtf16(mName)) != NO_ERROR) return status;
+ if ((status = parcel->writeUint32(mType)) != NO_ERROR) return status;
+ if ((status = parcel->writeUint32(mRole)) != NO_ERROR) return status;
+ if ((status = parcel->writeParcelable(mProfiles)) != NO_ERROR) return status;
+ if ((status = parcel->writeParcelable(mGains)) != NO_ERROR) return status;
+ return status;
+}
+
+status_t AudioPort::readFromParcel(const Parcel *parcel)
+{
+ status_t status = NO_ERROR;
+ if ((status = parcel->readUtf8FromUtf16(&mName)) != NO_ERROR) return status;
+ static_assert(sizeof(mType) == sizeof(uint32_t));
+ if ((status = parcel->readUint32(reinterpret_cast<uint32_t*>(&mType))) != NO_ERROR) {
+ return status;
+ }
+ static_assert(sizeof(mRole) == sizeof(uint32_t));
+ if ((status = parcel->readUint32(reinterpret_cast<uint32_t*>(&mRole))) != NO_ERROR) {
+ return status;
+ }
+ mProfiles.clear();
+ if ((status = parcel->readParcelable(&mProfiles)) != NO_ERROR) return status;
+ mGains.clear();
+ if ((status = parcel->readParcelable(&mGains)) != NO_ERROR) return status;
+ return status;
+}
+
// --- AudioPortConfig class implementation
status_t AudioPortConfig::applyAudioPortConfig(
@@ -188,4 +228,60 @@
: audioport->getGains().size() > 0;
}
+bool AudioPortConfig::equals(const sp<AudioPortConfig> &other) const
+{
+ return other != nullptr &&
+ mSamplingRate == other->getSamplingRate() &&
+ mFormat == other->getFormat() &&
+ mChannelMask == other->getChannelMask() &&
+ // Compare audio gain config
+ mGain.index == other->mGain.index &&
+ mGain.mode == other->mGain.mode &&
+ mGain.channel_mask == other->mGain.channel_mask &&
+ std::equal(std::begin(mGain.values), std::end(mGain.values),
+ std::begin(other->mGain.values)) &&
+ mGain.ramp_duration_ms == other->mGain.ramp_duration_ms;
}
+
+status_t AudioPortConfig::writeToParcel(Parcel *parcel) const
+{
+ status_t status = NO_ERROR;
+ if ((status = parcel->writeUint32(mSamplingRate)) != NO_ERROR) return status;
+ if ((status = parcel->writeUint32(mFormat)) != NO_ERROR) return status;
+ if ((status = parcel->writeUint32(mChannelMask)) != NO_ERROR) return status;
+ if ((status = parcel->writeInt32(mId)) != NO_ERROR) return status;
+ // Write mGain to parcel.
+ if ((status = parcel->writeInt32(mGain.index)) != NO_ERROR) return status;
+ if ((status = parcel->writeUint32(mGain.mode)) != NO_ERROR) return status;
+ if ((status = parcel->writeUint32(mGain.channel_mask)) != NO_ERROR) return status;
+ if ((status = parcel->writeUint32(mGain.ramp_duration_ms)) != NO_ERROR) return status;
+ std::vector<int> values(std::begin(mGain.values), std::end(mGain.values));
+ if ((status = parcel->writeInt32Vector(values)) != NO_ERROR) return status;
+ return status;
+}
+
+status_t AudioPortConfig::readFromParcel(const Parcel *parcel)
+{
+ status_t status = NO_ERROR;
+ if ((status = parcel->readUint32(&mSamplingRate)) != NO_ERROR) return status;
+ static_assert(sizeof(mFormat) == sizeof(uint32_t));
+ if ((status = parcel->readUint32(reinterpret_cast<uint32_t*>(&mFormat))) != NO_ERROR) {
+ return status;
+ }
+ if ((status = parcel->readUint32(&mChannelMask)) != NO_ERROR) return status;
+ if ((status = parcel->readInt32(&mId)) != NO_ERROR) return status;
+ // Read mGain from parcel.
+ if ((status = parcel->readInt32(&mGain.index)) != NO_ERROR) return status;
+ if ((status = parcel->readUint32(&mGain.mode)) != NO_ERROR) return status;
+ if ((status = parcel->readUint32(&mGain.channel_mask)) != NO_ERROR) return status;
+ if ((status = parcel->readUint32(&mGain.ramp_duration_ms)) != NO_ERROR) return status;
+ std::vector<int> values;
+ if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
+ if (values.size() != std::size(mGain.values)) {
+ return BAD_VALUE;
+ }
+ std::copy(values.begin(), values.end(), mGain.values);
+ return status;
+}
+
+} // namespace android
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
index 1ae18c5..91be346 100644
--- a/media/libaudiofoundation/AudioProfile.cpp
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -118,6 +118,56 @@
}
}
+bool AudioProfile::equals(const sp<AudioProfile>& other) const
+{
+ return other != nullptr &&
+ mName.compare(other->mName) == 0 &&
+ mFormat == other->getFormat() &&
+ mChannelMasks == other->getChannels() &&
+ mSamplingRates == other->getSampleRates() &&
+ mIsDynamicFormat == other->isDynamicFormat() &&
+ mIsDynamicChannels == other->isDynamicChannels() &&
+ mIsDynamicRate == other->isDynamicRate();
+}
+
+status_t AudioProfile::writeToParcel(Parcel *parcel) const
+{
+ status_t status = NO_ERROR;
+ if ((status = parcel->writeUtf8AsUtf16(mName)) != NO_ERROR) return status;
+ if ((status = parcel->writeUint32(mFormat)) != NO_ERROR) return status;
+ std::vector<int> values(mChannelMasks.begin(), mChannelMasks.end());
+ if ((status = parcel->writeInt32Vector(values)) != NO_ERROR) return status;
+ values.clear();
+ values.assign(mSamplingRates.begin(), mSamplingRates.end());
+ if ((status = parcel->writeInt32Vector(values)) != NO_ERROR) return status;
+ if ((status = parcel->writeBool(mIsDynamicFormat)) != NO_ERROR) return status;
+ if ((status = parcel->writeBool(mIsDynamicChannels)) != NO_ERROR) return status;
+ if ((status = parcel->writeBool(mIsDynamicRate)) != NO_ERROR) return status;
+ return status;
+}
+
+status_t AudioProfile::readFromParcel(const Parcel *parcel)
+{
+ status_t status = NO_ERROR;
+ if ((status = parcel->readUtf8FromUtf16(&mName)) != NO_ERROR) return status;
+ static_assert(sizeof(mFormat) == sizeof(uint32_t));
+ if ((status = parcel->readUint32(reinterpret_cast<uint32_t*>(&mFormat))) != NO_ERROR) {
+ return status;
+ }
+ std::vector<int> values;
+ if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
+ mChannelMasks.clear();
+ mChannelMasks.insert(values.begin(), values.end());
+ values.clear();
+ if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
+ mSamplingRates.clear();
+ mSamplingRates.insert(values.begin(), values.end());
+ if ((status = parcel->readBool(&mIsDynamicFormat)) != NO_ERROR) return status;
+ if ((status = parcel->readBool(&mIsDynamicChannels)) != NO_ERROR) return status;
+ if ((status = parcel->readBool(&mIsDynamicRate)) != NO_ERROR) return status;
+ return status;
+}
+
ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile)
{
ssize_t index = size();
@@ -219,4 +269,39 @@
}
}
+status_t AudioProfileVector::writeToParcel(Parcel *parcel) const
+{
+ status_t status = NO_ERROR;
+ if ((status = parcel->writeVectorSize(*this)) != NO_ERROR) return status;
+ for (const auto &audioProfile : *this) {
+ if ((status = parcel->writeParcelable(*audioProfile)) != NO_ERROR) {
+ break;
+ }
+ }
+ return status;
+}
+
+status_t AudioProfileVector::readFromParcel(const Parcel *parcel)
+{
+ status_t status = NO_ERROR;
+ this->clear();
+ if ((status = parcel->resizeOutVector(this)) != NO_ERROR) return status;
+ for (size_t i = 0; i < this->size(); ++i) {
+ this->at(i) = new AudioProfile(AUDIO_FORMAT_DEFAULT, AUDIO_CHANNEL_NONE, 0 /*sampleRate*/);
+ if ((status = parcel->readParcelable(this->at(i).get())) != NO_ERROR) {
+ this->clear();
+ break;
+ }
+ }
+ return status;
+}
+
+bool AudioProfileVector::equals(const AudioProfileVector& other) const
+{
+ return std::equal(begin(), end(), other.begin(), other.end(),
+ [](const sp<AudioProfile>& left, const sp<AudioProfile>& right) {
+ return left->equals(right);
+ });
+}
+
} // namespace android
diff --git a/media/libaudiofoundation/DeviceDescriptorBase.cpp b/media/libaudiofoundation/DeviceDescriptorBase.cpp
index f92c05d..18fd184 100644
--- a/media/libaudiofoundation/DeviceDescriptorBase.cpp
+++ b/media/libaudiofoundation/DeviceDescriptorBase.cpp
@@ -110,4 +110,33 @@
AudioPort::log(" ");
}
+bool DeviceDescriptorBase::equals(const sp<DeviceDescriptorBase> &other) const
+{
+ return other != nullptr &&
+ static_cast<const AudioPort*>(this)->equals(other) &&
+ static_cast<const AudioPortConfig*>(this)->equals(other) &&
+ mAddress.compare(other->address()) == 0 &&
+ mDeviceType == other->type();
+}
+
+status_t DeviceDescriptorBase::writeToParcel(Parcel *parcel) const
+{
+ status_t status = NO_ERROR;
+ if ((status = AudioPort::writeToParcel(parcel)) != NO_ERROR) return status;
+ if ((status = AudioPortConfig::writeToParcel(parcel)) != NO_ERROR) return status;
+ if ((status = parcel->writeUtf8AsUtf16(mAddress)) != NO_ERROR) return status;
+ if ((status = parcel->writeUint32(mDeviceType)) != NO_ERROR) return status;
+ return status;
+}
+
+status_t DeviceDescriptorBase::readFromParcel(const Parcel *parcel)
+{
+ status_t status = NO_ERROR;
+ if ((status = AudioPort::readFromParcel(parcel)) != NO_ERROR) return status;
+ if ((status = AudioPortConfig::readFromParcel(parcel)) != NO_ERROR) return status;
+ if ((status = parcel->readUtf8FromUtf16(&mAddress)) != NO_ERROR) return status;
+ if ((status = parcel->readUint32(&mDeviceType)) != NO_ERROR) return status;
+ return status;
+}
+
} // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index 3313224..8347c71 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -16,19 +16,37 @@
#pragma once
+#include <algorithm>
+#include <iterator>
#include <set>
#include <vector>
+#include <media/TypeConverter.h>
#include <system/audio.h>
namespace android {
using ChannelMaskSet = std::set<audio_channel_mask_t>;
+using DeviceTypeSet = std::set<audio_devices_t>;
using FormatSet = std::set<audio_format_t>;
using SampleRateSet = std::set<uint32_t>;
using FormatVector = std::vector<audio_format_t>;
+const DeviceTypeSet& getAudioDeviceOutAllSet();
+const DeviceTypeSet& getAudioDeviceOutAllA2dpSet();
+const DeviceTypeSet& getAudioDeviceOutAllScoSet();
+const DeviceTypeSet& getAudioDeviceInAllSet();
+
+template<typename T>
+static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) {
+ std::vector<T> intersection;
+ std::set_intersection(a.begin(), a.end(),
+ b.begin(), b.end(),
+ std::back_inserter(intersection));
+ return intersection;
+}
+
static inline ChannelMaskSet asInMask(const ChannelMaskSet& channelMasks) {
ChannelMaskSet inMaskSet;
for (const auto &channel : channelMasks) {
@@ -49,4 +67,55 @@
return outMaskSet;
}
+static inline bool isSingleDeviceType(const DeviceTypeSet& deviceTypes,
+ audio_devices_t deviceType) {
+ return deviceTypes.size() == 1 && *(deviceTypes.begin()) == deviceType;
+}
+
+typedef bool (*DeviceTypeUnaryPredicate)(audio_devices_t);
+static inline bool isSingleDeviceType(const DeviceTypeSet& deviceTypes,
+ DeviceTypeUnaryPredicate p) {
+ return deviceTypes.size() == 1 && p(*(deviceTypes.begin()));
+}
+
+static inline void resetDeviceTypes(DeviceTypeSet& deviceTypes, audio_devices_t typeToAdd) {
+ deviceTypes.clear();
+ deviceTypes.insert(typeToAdd);
+}
+
+// FIXME: This is temporary helper function. Remove this when getting rid of all
+// bit mask usages of audio device types.
+static inline audio_devices_t deviceTypesToBitMask(const DeviceTypeSet& deviceTypes) {
+ audio_devices_t types = AUDIO_DEVICE_NONE;
+ for (auto deviceType : deviceTypes) {
+ types |= deviceType;
+ }
+ return types;
+}
+
+// FIXME: This is temporary helper function. Remove this when getting rid of all
+// bit mask usages of audio device types.
+static inline DeviceTypeSet deviceTypesFromBitMask(audio_devices_t types) {
+ DeviceTypeSet deviceTypes;
+ if ((types & AUDIO_DEVICE_BIT_IN) == 0) {
+ for (auto deviceType : AUDIO_DEVICE_OUT_ALL_ARRAY) {
+ if ((types & deviceType) == deviceType) {
+ deviceTypes.insert(deviceType);
+ }
+ }
+ } else {
+ for (auto deviceType : AUDIO_DEVICE_IN_ALL_ARRAY) {
+ if ((types & deviceType) == deviceType) {
+ deviceTypes.insert(deviceType);
+ }
+ }
+ }
+ return deviceTypes;
+}
+
+bool deviceTypesToString(const DeviceTypeSet& deviceTypes, std::string &str);
+
+std::string dumpDeviceTypes(const DeviceTypeSet& deviceTypes);
+
+
} // namespace android
\ No newline at end of file
diff --git a/media/libaudiofoundation/include/media/AudioGain.h b/media/libaudiofoundation/include/media/AudioGain.h
index 6a7fb55..859f1e7 100644
--- a/media/libaudiofoundation/include/media/AudioGain.h
+++ b/media/libaudiofoundation/include/media/AudioGain.h
@@ -67,6 +67,8 @@
const struct audio_gain &getGain() const { return mGain; }
+ bool equals(const sp<AudioGain>& other) const;
+
status_t writeToParcel(Parcel* parcel) const override;
status_t readFromParcel(const Parcel* parcel) override;
@@ -96,6 +98,8 @@
return 0;
}
+ bool equals(const AudioGains& other) const;
+
status_t writeToParcel(Parcel* parcel) const override;
status_t readFromParcel(const Parcel* parcel) override;
};
diff --git a/media/libaudiofoundation/include/media/AudioPort.h b/media/libaudiofoundation/include/media/AudioPort.h
index b8d54de..3c013cb 100644
--- a/media/libaudiofoundation/include/media/AudioPort.h
+++ b/media/libaudiofoundation/include/media/AudioPort.h
@@ -18,6 +18,8 @@
#include <string>
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
#include <media/AudioGain.h>
#include <media/AudioProfile.h>
#include <utils/Errors.h>
@@ -27,7 +29,7 @@
namespace android {
-class AudioPort : public virtual RefBase
+class AudioPort : public virtual RefBase, public virtual Parcelable
{
public:
AudioPort(const std::string& name, audio_port_type_t type, audio_port_role_t role) :
@@ -79,6 +81,11 @@
void log(const char* indent) const;
+ bool equals(const sp<AudioPort>& other) const;
+
+ status_t writeToParcel(Parcel* parcel) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
AudioGains mGains; // gain controllers
protected:
std::string mName;
@@ -88,7 +95,7 @@
};
-class AudioPortConfig : public virtual RefBase
+class AudioPortConfig : public virtual RefBase, public virtual Parcelable
{
public:
virtual ~AudioPortConfig() = default;
@@ -108,6 +115,11 @@
bool hasGainController(bool canUseForVolume = false) const;
+ bool equals(const sp<AudioPortConfig>& other) const;
+
+ status_t writeToParcel(Parcel* parcel) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
protected:
unsigned int mSamplingRate = 0u;
audio_format_t mFormat = AUDIO_FORMAT_INVALID;
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
index f4c2e12..730138a 100644
--- a/media/libaudiofoundation/include/media/AudioProfile.h
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -19,13 +19,15 @@
#include <string>
#include <vector>
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
#include <media/AudioContainers.h>
#include <system/audio.h>
#include <utils/RefBase.h>
namespace android {
-class AudioProfile final : public RefBase
+class AudioProfile final : public RefBase, public Parcelable
{
public:
static sp<AudioProfile> createFullDynamic(audio_format_t dynamicFormat = AUDIO_FORMAT_DEFAULT);
@@ -66,6 +68,11 @@
void dump(std::string *dst, int spaces) const;
+ bool equals(const sp<AudioProfile>& other) const;
+
+ status_t writeToParcel(Parcel* parcel) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
private:
std::string mName;
audio_format_t mFormat; // The format for an audio profile should only be set when initialized.
@@ -77,7 +84,7 @@
bool mIsDynamicRate = false;
};
-class AudioProfileVector : public std::vector<sp<AudioProfile>>
+class AudioProfileVector : public std::vector<sp<AudioProfile>>, public Parcelable
{
public:
virtual ~AudioProfileVector() = default;
@@ -99,6 +106,11 @@
bool hasDynamicRateFor(audio_format_t format) const;
virtual void dump(std::string *dst, int spaces) const;
+
+ bool equals(const AudioProfileVector& other) const;
+
+ status_t writeToParcel(Parcel* parcel) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
};
bool operator == (const AudioProfile &left, const AudioProfile &right);
diff --git a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
index bbe0517..6a34b4d 100644
--- a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
+++ b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
@@ -16,6 +16,8 @@
#pragma once
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
#include <media/AudioPort.h>
#include <utils/Errors.h>
#include <cutils/config_utils.h>
@@ -51,6 +53,11 @@
void log() const;
std::string toString() const;
+ bool equals(const sp<DeviceDescriptorBase>& other) const;
+
+ status_t writeToParcel(Parcel* parcel) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
protected:
std::string mAddress{""};
audio_devices_t mDeviceType;
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 5837fcf..74b48f3 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -16,6 +16,7 @@
"libaudiohal@2.0",
"libaudiohal@4.0",
"libaudiohal@5.0",
+ "libaudiohal@6.0",
"libutils",
],
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index a23d945..8669e2a 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -99,3 +99,20 @@
"-include common/all-versions/VersionMacro.h",
]
}
+
+cc_library_shared {
+ name: "libaudiohal@6.0",
+ defaults: ["libaudiohal_default"],
+ shared_libs: [
+ "android.hardware.audio.common@6.0",
+ "android.hardware.audio.common@6.0-util",
+ "android.hardware.audio.effect@6.0",
+ "android.hardware.audio@6.0",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=6",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ]
+}
+
diff --git a/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h b/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
index 829f99c..271bafc 100644
--- a/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
+++ b/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
@@ -34,6 +34,7 @@
* the preferred available impl.
*/
enum class AudioHALVersion {
+ V6_0,
V5_0,
V4_0,
V2_0,
diff --git a/media/libmedia/MediaResource.cpp b/media/libmedia/MediaResource.cpp
index e636a50..8626009 100644
--- a/media/libmedia/MediaResource.cpp
+++ b/media/libmedia/MediaResource.cpp
@@ -19,6 +19,8 @@
#include <utils/Log.h>
#include <media/MediaResource.h>
+#include <vector>
+
namespace android {
MediaResource::MediaResource()
@@ -36,26 +38,48 @@
mSubType(subType),
mValue(value) {}
+MediaResource::MediaResource(Type type, const std::vector<uint8_t> &id, uint64_t value)
+ : mType(type),
+ mSubType(kUnspecifiedSubType),
+ mValue(value),
+ mId(id) {}
+
void MediaResource::readFromParcel(const Parcel &parcel) {
mType = static_cast<Type>(parcel.readInt32());
mSubType = static_cast<SubType>(parcel.readInt32());
mValue = parcel.readUint64();
+ parcel.readByteVector(&mId);
}
void MediaResource::writeToParcel(Parcel *parcel) const {
parcel->writeInt32(static_cast<int32_t>(mType));
parcel->writeInt32(static_cast<int32_t>(mSubType));
parcel->writeUint64(mValue);
+ parcel->writeByteVector(mId);
+}
+
+static String8 bytesToHexString(const std::vector<uint8_t> &bytes) {
+ String8 str;
+ for (auto &b : bytes) {
+ str.appendFormat("%02x", b);
+ }
+ return str;
}
String8 MediaResource::toString() const {
String8 str;
- str.appendFormat("%s/%s:%llu", asString(mType), asString(mSubType), (unsigned long long)mValue);
+ str.appendFormat("%s/%s:[%s]:%llu",
+ asString(mType), asString(mSubType),
+ bytesToHexString(mId).c_str(),
+ (unsigned long long)mValue);
return str;
}
bool MediaResource::operator==(const MediaResource &other) const {
- return (other.mType == mType) && (other.mSubType == mSubType) && (other.mValue == mValue);
+ return (other.mType == mType)
+ && (other.mSubType == mSubType)
+ && (other.mValue == mValue)
+ && (other.mId == mId);
}
bool MediaResource::operator!=(const MediaResource &other) const {
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index d8ef9cf..6d46363 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -17,7 +17,6 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MidiIoWrapper"
#include <utils/Log.h>
-#include <utils/RefBase.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -50,7 +49,7 @@
mDataSource = nullptr;
}
-class DataSourceUnwrapper : public DataSourceBase {
+class DataSourceUnwrapper {
public:
explicit DataSourceUnwrapper(CDataSource *csource) {
diff --git a/media/libmedia/include/media/MediaResource.h b/media/libmedia/include/media/MediaResource.h
index 10a07bb..e9684f0 100644
--- a/media/libmedia/include/media/MediaResource.h
+++ b/media/libmedia/include/media/MediaResource.h
@@ -20,6 +20,7 @@
#include <binder/Parcel.h>
#include <utils/String8.h>
+#include <vector>
namespace android {
@@ -32,6 +33,7 @@
kGraphicMemory,
kCpuBoost,
kBattery,
+ kDrmSession,
};
enum SubType {
@@ -43,6 +45,7 @@
MediaResource();
MediaResource(Type type, uint64_t value);
MediaResource(Type type, SubType subType, uint64_t value);
+ MediaResource(Type type, const std::vector<uint8_t> &id, uint64_t value);
void readFromParcel(const Parcel &parcel);
void writeToParcel(Parcel *parcel) const;
@@ -55,6 +58,8 @@
Type mType;
SubType mSubType;
uint64_t mValue;
+ // for kDrmSession-type mId is the unique session id obtained via MediaDrm#openSession
+ std::vector<uint8_t> mId;
};
inline static const char *asString(MediaResource::Type i, const char *def = "??") {
@@ -65,6 +70,7 @@
case MediaResource::kGraphicMemory: return "graphic-memory";
case MediaResource::kCpuBoost: return "cpu-boost";
case MediaResource::kBattery: return "battery";
+ case MediaResource::kDrmSession: return "drm-session";
default: return def;
}
}
diff --git a/media/libmediaplayerservice/tests/Android.bp b/media/libmediaplayerservice/tests/Android.bp
index f8c89e5..8357925 100644
--- a/media/libmediaplayerservice/tests/Android.bp
+++ b/media/libmediaplayerservice/tests/Android.bp
@@ -6,14 +6,22 @@
shared_libs: [
"liblog",
+ "libbinder",
+ "libmedia",
"libmediaplayerservice",
"libmediadrm",
+ "libresourcemanagerservice",
"libutils",
"android.hardware.drm@1.0",
"android.hardware.drm@1.1",
"android.hardware.drm@1.2",
],
+ include_dirs: [
+ "frameworks/av/include",
+ "frameworks/av/services/mediaresourcemanager",
+ ],
+
cflags: [
"-Werror",
"-Wall",
diff --git a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
index d81ee05..58e4bee 100644
--- a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
+++ b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
@@ -20,14 +20,29 @@
#include <gtest/gtest.h>
+#include <media/IResourceManagerService.h>
+#include <media/IResourceManagerClient.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/ProcessInfoInterface.h>
#include <mediadrm/DrmHal.h>
#include <mediadrm/DrmSessionClientInterface.h>
#include <mediadrm/DrmSessionManager.h>
+#include <algorithm>
+#include <vector>
+
+#include "ResourceManagerService.h"
+
namespace android {
+static Vector<uint8_t> toAndroidVector(const std::vector<uint8_t> &vec) {
+ Vector<uint8_t> aVec;
+ for (auto b : vec) {
+ aVec.push_back(b);
+ }
+ return aVec;
+}
+
struct FakeProcessInfo : public ProcessInfoInterface {
FakeProcessInfo() {}
virtual ~FakeProcessInfo() {}
@@ -47,173 +62,128 @@
DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
};
-struct FakeDrm : public DrmSessionClientInterface {
- FakeDrm() {}
+struct FakeDrm : public BnResourceManagerClient {
+ FakeDrm(const std::vector<uint8_t>& sessionId, const sp<DrmSessionManager>& manager)
+ : mSessionId(toAndroidVector(sessionId)),
+ mReclaimed(false),
+ mDrmSessionManager(manager) {}
+
virtual ~FakeDrm() {}
- virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
- mReclaimedSessions.push_back(sessionId);
+ virtual bool reclaimResource() {
+ mReclaimed = true;
+ mDrmSessionManager->removeSession(mSessionId);
return true;
}
- const Vector<Vector<uint8_t> >& reclaimedSessions() const {
- return mReclaimedSessions;
+ virtual String8 getName() {
+ String8 name("FakeDrm[");
+ for (size_t i = 0; i < mSessionId.size(); ++i) {
+ name.appendFormat("%02x", mSessionId[i]);
+ }
+ name.append("]");
+ return name;
}
+ bool isReclaimed() const {
+ return mReclaimed;
+ }
+
+ const Vector<uint8_t> mSessionId;
+
private:
- Vector<Vector<uint8_t> > mReclaimedSessions;
+ bool mReclaimed;
+ const sp<DrmSessionManager> mDrmSessionManager;
DISALLOW_EVIL_CONSTRUCTORS(FakeDrm);
};
+struct FakeSystemCallback :
+ public ResourceManagerService::SystemCallbackInterface {
+ FakeSystemCallback() {}
+
+ virtual void noteStartVideo(int /*uid*/) override {}
+
+ virtual void noteStopVideo(int /*uid*/) override {}
+
+ virtual void noteResetVideo() override {}
+
+ virtual bool requestCpusetBoost(
+ bool /*enable*/, const sp<IInterface> &/*client*/) override {
+ return true;
+ }
+
+protected:
+ virtual ~FakeSystemCallback() {}
+
+private:
+
+ DISALLOW_EVIL_CONSTRUCTORS(FakeSystemCallback);
+};
+
static const int kTestPid1 = 30;
static const int kTestPid2 = 20;
-static const uint8_t kTestSessionId1[] = {1, 2, 3};
-static const uint8_t kTestSessionId2[] = {4, 5, 6, 7, 8};
-static const uint8_t kTestSessionId3[] = {9, 0};
+static const std::vector<uint8_t> kTestSessionId1{1, 2, 3};
+static const std::vector<uint8_t> kTestSessionId2{4, 5, 6, 7, 8};
+static const std::vector<uint8_t> kTestSessionId3{9, 0};
class DrmSessionManagerTest : public ::testing::Test {
public:
DrmSessionManagerTest()
- : mDrmSessionManager(new DrmSessionManager(new FakeProcessInfo())),
- mTestDrm1(new FakeDrm()),
- mTestDrm2(new FakeDrm()) {
- GetSessionId(kTestSessionId1, ARRAY_SIZE(kTestSessionId1), &mSessionId1);
- GetSessionId(kTestSessionId2, ARRAY_SIZE(kTestSessionId2), &mSessionId2);
- GetSessionId(kTestSessionId3, ARRAY_SIZE(kTestSessionId3), &mSessionId3);
+ : mService(new ResourceManagerService(new FakeProcessInfo(), new FakeSystemCallback())),
+ mDrmSessionManager(new DrmSessionManager(mService)),
+ mTestDrm1(new FakeDrm(kTestSessionId1, mDrmSessionManager)),
+ mTestDrm2(new FakeDrm(kTestSessionId2, mDrmSessionManager)),
+ mTestDrm3(new FakeDrm(kTestSessionId3, mDrmSessionManager)) {
+ DrmSessionManager *ptr = new DrmSessionManager(mService);
+ EXPECT_NE(ptr, nullptr);
+ /* mDrmSessionManager = ptr; */
}
protected:
- static void GetSessionId(const uint8_t* ids, size_t num, Vector<uint8_t>* sessionId) {
- for (size_t i = 0; i < num; ++i) {
- sessionId->push_back(ids[i]);
- }
- }
-
- static void ExpectEqSessionInfo(const SessionInfo& info, sp<DrmSessionClientInterface> drm,
- const Vector<uint8_t>& sessionId, int64_t timeStamp) {
- EXPECT_EQ(drm, info.drm);
- EXPECT_TRUE(isEqualSessionId(sessionId, info.sessionId));
- EXPECT_EQ(timeStamp, info.timeStamp);
- }
-
void addSession() {
- mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mSessionId1);
- mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId2);
- mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId3);
- const PidSessionInfosMap& map = sessionMap();
- EXPECT_EQ(2u, map.size());
- ssize_t index1 = map.indexOfKey(kTestPid1);
- ASSERT_GE(index1, 0);
- const SessionInfos& infos1 = map[index1];
- EXPECT_EQ(1u, infos1.size());
- ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 0);
-
- ssize_t index2 = map.indexOfKey(kTestPid2);
- ASSERT_GE(index2, 0);
- const SessionInfos& infos2 = map[index2];
- EXPECT_EQ(2u, infos2.size());
- ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId2, 1);
- ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 2);
+ mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mTestDrm1->mSessionId);
+ mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
+ mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
}
- const PidSessionInfosMap& sessionMap() {
- return mDrmSessionManager->mSessionMap;
- }
-
- void testGetLowestPriority() {
- int pid;
- int priority;
- EXPECT_FALSE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
-
- addSession();
- EXPECT_TRUE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
-
- EXPECT_EQ(kTestPid1, pid);
- FakeProcessInfo processInfo;
- int priority1;
- processInfo.getPriority(kTestPid1, &priority1);
- EXPECT_EQ(priority1, priority);
- }
-
- void testGetLeastUsedSession() {
- sp<DrmSessionClientInterface> drm;
- Vector<uint8_t> sessionId;
- EXPECT_FALSE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
-
- addSession();
-
- EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
- EXPECT_EQ(mTestDrm1, drm);
- EXPECT_TRUE(isEqualSessionId(mSessionId1, sessionId));
-
- EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
- EXPECT_EQ(mTestDrm2, drm);
- EXPECT_TRUE(isEqualSessionId(mSessionId2, sessionId));
-
- // mSessionId2 is no longer the least used session.
- mDrmSessionManager->useSession(mSessionId2);
- EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
- EXPECT_EQ(mTestDrm2, drm);
- EXPECT_TRUE(isEqualSessionId(mSessionId3, sessionId));
- }
-
+ sp<IResourceManagerService> mService;
sp<DrmSessionManager> mDrmSessionManager;
sp<FakeDrm> mTestDrm1;
sp<FakeDrm> mTestDrm2;
- Vector<uint8_t> mSessionId1;
- Vector<uint8_t> mSessionId2;
- Vector<uint8_t> mSessionId3;
+ sp<FakeDrm> mTestDrm3;
};
TEST_F(DrmSessionManagerTest, addSession) {
addSession();
+
+ EXPECT_EQ(3u, mDrmSessionManager->getSessionCount());
+ EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
+ EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
+ EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
}
TEST_F(DrmSessionManagerTest, useSession) {
addSession();
- mDrmSessionManager->useSession(mSessionId1);
- mDrmSessionManager->useSession(mSessionId3);
+ mDrmSessionManager->useSession(mTestDrm1->mSessionId);
+ mDrmSessionManager->useSession(mTestDrm3->mSessionId);
- const PidSessionInfosMap& map = sessionMap();
- const SessionInfos& infos1 = map.valueFor(kTestPid1);
- const SessionInfos& infos2 = map.valueFor(kTestPid2);
- ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 3);
- ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 4);
+ EXPECT_EQ(3u, mDrmSessionManager->getSessionCount());
+ EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
+ EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
+ EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
}
TEST_F(DrmSessionManagerTest, removeSession) {
addSession();
- mDrmSessionManager->removeSession(mSessionId2);
+ mDrmSessionManager->removeSession(mTestDrm2->mSessionId);
- const PidSessionInfosMap& map = sessionMap();
- EXPECT_EQ(2u, map.size());
- const SessionInfos& infos1 = map.valueFor(kTestPid1);
- const SessionInfos& infos2 = map.valueFor(kTestPid2);
- EXPECT_EQ(1u, infos1.size());
- EXPECT_EQ(1u, infos2.size());
- // mSessionId2 has been removed.
- ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId3, 2);
-}
-
-TEST_F(DrmSessionManagerTest, removeDrm) {
- addSession();
-
- sp<FakeDrm> drm = new FakeDrm;
- const uint8_t ids[] = {123};
- Vector<uint8_t> sessionId;
- GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
- mDrmSessionManager->addSession(kTestPid2, drm, sessionId);
-
- mDrmSessionManager->removeDrm(mTestDrm2);
-
- const PidSessionInfosMap& map = sessionMap();
- const SessionInfos& infos2 = map.valueFor(kTestPid2);
- EXPECT_EQ(1u, infos2.size());
- // mTestDrm2 has been removed.
- ExpectEqSessionInfo(infos2[0], drm, sessionId, 3);
+ EXPECT_EQ(2u, mDrmSessionManager->getSessionCount());
+ EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
+ EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
+ EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
}
TEST_F(DrmSessionManagerTest, reclaimSession) {
@@ -224,30 +194,63 @@
EXPECT_FALSE(mDrmSessionManager->reclaimSession(50));
EXPECT_TRUE(mDrmSessionManager->reclaimSession(10));
- EXPECT_EQ(1u, mTestDrm1->reclaimedSessions().size());
- EXPECT_TRUE(isEqualSessionId(mSessionId1, mTestDrm1->reclaimedSessions()[0]));
-
- mDrmSessionManager->removeSession(mSessionId1);
+ EXPECT_TRUE(mTestDrm1->isReclaimed());
// add a session from a higher priority process.
- sp<FakeDrm> drm = new FakeDrm;
- const uint8_t ids[] = {1, 3, 5};
- Vector<uint8_t> sessionId;
- GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
- mDrmSessionManager->addSession(15, drm, sessionId);
+ const std::vector<uint8_t> sid{1, 3, 5};
+ sp<FakeDrm> drm = new FakeDrm(sid, mDrmSessionManager);
+ mDrmSessionManager->addSession(15, drm, drm->mSessionId);
+ // make sure mTestDrm2 is reclaimed next instead of mTestDrm3
+ mDrmSessionManager->useSession(mTestDrm3->mSessionId);
EXPECT_TRUE(mDrmSessionManager->reclaimSession(18));
- EXPECT_EQ(1u, mTestDrm2->reclaimedSessions().size());
- // mSessionId2 is reclaimed.
- EXPECT_TRUE(isEqualSessionId(mSessionId2, mTestDrm2->reclaimedSessions()[0]));
+ EXPECT_TRUE(mTestDrm2->isReclaimed());
+
+ EXPECT_EQ(2u, mDrmSessionManager->getSessionCount());
+ EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
+ EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
+ EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
+ EXPECT_TRUE(mDrmSessionManager->containsSession(drm->mSessionId));
}
-TEST_F(DrmSessionManagerTest, getLowestPriority) {
- testGetLowestPriority();
-}
+TEST_F(DrmSessionManagerTest, reclaimAfterUse) {
+ // nothing to reclaim yet
+ EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1));
+ EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid2));
-TEST_F(DrmSessionManagerTest, getLeastUsedSession_l) {
- testGetLeastUsedSession();
+ // add sessions from same pid
+ mDrmSessionManager->addSession(kTestPid2, mTestDrm1, mTestDrm1->mSessionId);
+ mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
+ mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
+
+ // use some but not all sessions
+ mDrmSessionManager->useSession(mTestDrm1->mSessionId);
+ mDrmSessionManager->useSession(mTestDrm1->mSessionId);
+ mDrmSessionManager->useSession(mTestDrm2->mSessionId);
+
+ // calling pid priority is too low
+ int lowPriorityPid = kTestPid2 + 1;
+ EXPECT_FALSE(mDrmSessionManager->reclaimSession(lowPriorityPid));
+
+ // unused session is reclaimed first
+ int highPriorityPid = kTestPid2 - 1;
+ EXPECT_TRUE(mDrmSessionManager->reclaimSession(highPriorityPid));
+ EXPECT_FALSE(mTestDrm1->isReclaimed());
+ EXPECT_FALSE(mTestDrm2->isReclaimed());
+ EXPECT_TRUE(mTestDrm3->isReclaimed());
+ mDrmSessionManager->removeSession(mTestDrm3->mSessionId);
+
+ // less-used session is reclaimed next
+ EXPECT_TRUE(mDrmSessionManager->reclaimSession(highPriorityPid));
+ EXPECT_FALSE(mTestDrm1->isReclaimed());
+ EXPECT_TRUE(mTestDrm2->isReclaimed());
+ EXPECT_TRUE(mTestDrm3->isReclaimed());
+
+ // most-used session still open
+ EXPECT_EQ(1u, mDrmSessionManager->getSessionCount());
+ EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
+ EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
+ EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
}
} // namespace android
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index b282c4a..0ca20b9 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -6927,7 +6927,7 @@
}
}
- if (mCodec->mMaxPtsGapUs != 0LL) {
+ if (mCodec->mIsVideo && mCodec->mMaxPtsGapUs != 0LL) {
OMX_PARAM_U32TYPE maxPtsGapParams;
InitOMXParams(&maxPtsGapParams);
maxPtsGapParams.nPortIndex = kPortIndexInput;
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index c02b276..f2fb768 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -213,7 +213,6 @@
"libogg",
"libwebm",
"libstagefright_id3",
- "libFLAC",
],
header_libs:[
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index f130c9b..bf4e7de 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -2213,8 +2213,10 @@
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC) ||
!strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)) {
mMeta->findData(kKeyHVCC, &type, &data, &size);
- } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
- || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
+ mMeta->findData(kKeyDVCC, &type, &data, &size);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
+ !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
ESDS esds(data, size);
if (esds.getCodecSpecificInfo(&data, &size) == OK &&
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index bda6053..ac4d087 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -227,6 +227,68 @@
}
}
+static void parseDolbyVisionProfileLevelFromDvcc(const uint8_t *ptr, size_t size, sp<AMessage> &format) {
+ // dv_major.dv_minor Should be 1.0 or 2.1
+ if (size != 24 || ((ptr[0] != 1 || ptr[1] != 0) && (ptr[0] != 2 || ptr[1] != 1))) {
+ ALOGV("Size %zu, dv_major %d, dv_minor %d", size, ptr[0], ptr[1]);
+ return;
+ }
+
+ const uint8_t profile = ptr[2] >> 1;
+ const uint8_t level = ((ptr[2] & 0x1) << 5) | ((ptr[3] >> 3) & 0x1f);
+ const uint8_t rpu_present_flag = (ptr[3] >> 2) & 0x01;
+ const uint8_t el_present_flag = (ptr[3] >> 1) & 0x01;
+ const uint8_t bl_present_flag = (ptr[3] & 0x01);
+ const int32_t bl_compatibility_id = (int32_t)(ptr[4] >> 4);
+
+ ALOGV("profile-level-compatibility value in dv(c|v)c box %d-%d-%d",
+ profile, level, bl_compatibility_id);
+
+ // All Dolby Profiles will have profile and level info in MediaFormat
+ // Profile 8 and 9 will have bl_compatibility_id too.
+ const static ALookup<uint8_t, OMX_VIDEO_DOLBYVISIONPROFILETYPE> profiles{
+ {1, OMX_VIDEO_DolbyVisionProfileDvavPen},
+ {3, OMX_VIDEO_DolbyVisionProfileDvheDen},
+ {4, OMX_VIDEO_DolbyVisionProfileDvheDtr},
+ {5, OMX_VIDEO_DolbyVisionProfileDvheStn},
+ {6, OMX_VIDEO_DolbyVisionProfileDvheDth},
+ {7, OMX_VIDEO_DolbyVisionProfileDvheDtb},
+ {8, OMX_VIDEO_DolbyVisionProfileDvheSt},
+ {9, OMX_VIDEO_DolbyVisionProfileDvavSe},
+ {10, OMX_VIDEO_DolbyVisionProfileDvav110},
+ };
+
+ const static ALookup<uint8_t, OMX_VIDEO_DOLBYVISIONLEVELTYPE> levels{
+ {0, OMX_VIDEO_DolbyVisionLevelUnknown},
+ {1, OMX_VIDEO_DolbyVisionLevelHd24},
+ {2, OMX_VIDEO_DolbyVisionLevelHd30},
+ {3, OMX_VIDEO_DolbyVisionLevelFhd24},
+ {4, OMX_VIDEO_DolbyVisionLevelFhd30},
+ {5, OMX_VIDEO_DolbyVisionLevelFhd60},
+ {6, OMX_VIDEO_DolbyVisionLevelUhd24},
+ {7, OMX_VIDEO_DolbyVisionLevelUhd30},
+ {8, OMX_VIDEO_DolbyVisionLevelUhd48},
+ {9, OMX_VIDEO_DolbyVisionLevelUhd60},
+ };
+ // set rpuAssoc
+ if (rpu_present_flag && el_present_flag && !bl_present_flag) {
+ format->setInt32("rpuAssoc", 1);
+ }
+ // set profile & level if they are recognized
+ OMX_VIDEO_DOLBYVISIONPROFILETYPE codecProfile;
+ OMX_VIDEO_DOLBYVISIONLEVELTYPE codecLevel;
+ if (profiles.map(profile, &codecProfile)) {
+ format->setInt32("profile", codecProfile);
+ if (codecProfile == OMX_VIDEO_DolbyVisionProfileDvheSt ||
+ codecProfile == OMX_VIDEO_DolbyVisionProfileDvavSe) {
+ format->setInt32("bl_compatibility_id", bl_compatibility_id);
+ }
+ if (levels.map(level, &codecLevel)) {
+ format->setInt32("level", codecLevel);
+ }
+ }
+}
+
static void parseH263ProfileLevelFromD263(const uint8_t *ptr, size_t size, sp<AMessage> &format) {
if (size < 7) {
return;
@@ -1411,6 +1473,12 @@
msg->setBuffer("csd-0", buffer);
}
+ if (meta->findData(kKeyDVCC, &type, &data, &size)) {
+ const uint8_t *ptr = (const uint8_t *)data;
+ ALOGV("DV: calling parseDolbyVisionProfileLevelFromDvcc with data size %zu", size);
+ parseDolbyVisionProfileLevelFromDvcc(ptr, size, msg);
+ }
+
*format = msg;
return OK;
@@ -1839,6 +1907,32 @@
meta->setData(kKeyHVCC, kTypeHVCC, hvcc.data(), outsize);
} else if (mime == MEDIA_MIMETYPE_VIDEO_AV1) {
meta->setData(kKeyAV1C, 0, csd0->data(), csd0->size());
+ } else if (mime == MEDIA_MIMETYPE_VIDEO_DOLBY_VISION) {
+ if (msg->findBuffer("csd-2", &csd2)) {
+ meta->setData(kKeyDVCC, kTypeDVCC, csd2->data(), csd2->size());
+
+ size_t dvcc_size = 1024;
+ uint8_t dvcc[dvcc_size];
+ memcpy(dvcc, csd2->data(), dvcc_size);
+ const uint8_t profile = dvcc[2] >> 1;
+
+ if (profile > 1 && profile < 9) {
+ std::vector<uint8_t> hvcc(csd0size + 1024);
+ size_t outsize = reassembleHVCC(csd0, hvcc.data(), hvcc.size(), 4);
+ meta->setData(kKeyHVCC, kTypeHVCC, hvcc.data(), outsize);
+ } else if (DolbyVisionProfileDvav110 == profile) {
+ meta->setData(kKeyAV1C, 0, csd0->data(), csd0->size());
+ } else {
+ sp<ABuffer> csd1;
+ if (msg->findBuffer("csd-1", &csd1)) {
+ std::vector<char> avcc(csd0size + csd1->size() + 1024);
+ size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
+ meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
+ }
+ }
+ } else {
+ ALOGW("We need csd-2!!. %s", msg->debugString().c_str());
+ }
} else if (mime == MEDIA_MIMETYPE_VIDEO_VP9) {
meta->setData(kKeyVp9CodecPrivate, 0, csd0->data(), csd0->size());
} else if (mime == MEDIA_MIMETYPE_AUDIO_OPUS) {
@@ -1885,8 +1979,18 @@
meta->setData(kKeyStreamHeader, 'mdat', csd0->data(), csd0->size());
} else if (msg->findBuffer("d263", &csd0)) {
meta->setData(kKeyD263, kTypeD263, csd0->data(), csd0->size());
- }
+ } else if (mime == MEDIA_MIMETYPE_VIDEO_DOLBY_VISION && msg->findBuffer("csd-2", &csd2)) {
+ meta->setData(kKeyDVCC, kTypeDVCC, csd2->data(), csd2->size());
+ // Remove CSD-2 from the data here to avoid duplicate data in meta
+ meta->remove(kKeyOpaqueCSD2);
+
+ if (msg->findBuffer("csd-avc", &csd0)) {
+ meta->setData(kKeyAVCC, kTypeAVCC, csd0->data(), csd0->size());
+ } else if (msg->findBuffer("csd-hevc", &csd0)) {
+ meta->setData(kKeyHVCC, kTypeHVCC, csd0->data(), csd0->size());
+ }
+ }
// XXX TODO add whatever other keys there are
#if 0
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 50d7724..16e207d 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -510,22 +510,24 @@
constexpr int32_t DolbyVisionProfileDvheStn = 0x20;
constexpr int32_t DolbyVisionProfileDvheDth = 0x40;
constexpr int32_t DolbyVisionProfileDvheDtb = 0x80;
-constexpr int32_t DolbyVisionProfileDvheSt = 0x100;
-constexpr int32_t DolbyVisionProfileDvavSe = 0x200;
+constexpr int32_t DolbyVisionProfileDvheSt = 0x100;
+constexpr int32_t DolbyVisionProfileDvavSe = 0x200;
+constexpr int32_t DolbyVisionProfileDvav110 = 0x400;
inline static const char *asString_DolbyVisionProfile(int32_t i, const char *def = "??") {
switch (i) {
- case DolbyVisionProfileDvavPer: return "DvavPer";
- case DolbyVisionProfileDvavPen: return "DvavPen";
- case DolbyVisionProfileDvheDer: return "DvheDer";
- case DolbyVisionProfileDvheDen: return "DvheDen";
- case DolbyVisionProfileDvheDtr: return "DvheDtr";
- case DolbyVisionProfileDvheStn: return "DvheStn";
- case DolbyVisionProfileDvheDth: return "DvheDth";
- case DolbyVisionProfileDvheDtb: return "DvheDtb";
- case DolbyVisionProfileDvheSt: return "DvheSt";
- case DolbyVisionProfileDvavSe: return "DvavSe";
- default: return def;
+ case DolbyVisionProfileDvavPer: return "DvavPer";
+ case DolbyVisionProfileDvavPen: return "DvavPen";
+ case DolbyVisionProfileDvheDer: return "DvheDer";
+ case DolbyVisionProfileDvheDen: return "DvheDen";
+ case DolbyVisionProfileDvheDtr: return "DvheDtr";
+ case DolbyVisionProfileDvheStn: return "DvheStn";
+ case DolbyVisionProfileDvheDth: return "DvheDth";
+ case DolbyVisionProfileDvheDtb: return "DvheDtb";
+ case DolbyVisionProfileDvheSt: return "DvheSt";
+ case DolbyVisionProfileDvavSe: return "DvavSe";
+ case DolbyVisionProfileDvav110: return "Dav110";
+ default: return def;
}
}
@@ -774,6 +776,7 @@
constexpr char KEY_LANGUAGE[] = "language";
constexpr char KEY_LATENCY[] = "latency";
constexpr char KEY_LEVEL[] = "level";
+constexpr char KEY_LOW_LATENCY[] = "low-latency";
constexpr char KEY_MAX_B_FRAMES[] = "max-bframes";
constexpr char KEY_MAX_BIT_RATE[] = "max-bitrate";
constexpr char KEY_MAX_FPS_TO_ENCODER[] = "max-fps-to-encoder";
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index 659bd5b..e17093a 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -59,6 +59,7 @@
kKeyAACProfile = 'aacp', // int32_t
kKeyAVCC = 'avcc', // raw data
kKeyHVCC = 'hvcc', // raw data
+ kKeyDVCC = 'dvcc', // raw data
kKeyAV1C = 'av1c', // raw data
kKeyThumbnailHVCC = 'thvc', // raw data
kKeyD263 = 'd263', // raw data
@@ -245,6 +246,7 @@
kTypeAVCC = 'avcc',
kTypeHVCC = 'hvcc',
kTypeAV1C = 'av1c',
+ kTypeDVCC = 'dvcc',
kTypeD263 = 'd263',
};
diff --git a/media/utils/ProcessInfo.cpp b/media/utils/ProcessInfo.cpp
index 27f1a79..113e4a7 100644
--- a/media/utils/ProcessInfo.cpp
+++ b/media/utils/ProcessInfo.cpp
@@ -23,6 +23,7 @@
#include <binder/IPCThreadState.h>
#include <binder/IProcessInfoService.h>
#include <binder/IServiceManager.h>
+#include <private/android_filesystem_config.h>
namespace android {
@@ -55,8 +56,9 @@
bool ProcessInfo::isValidPid(int pid) {
int callingPid = IPCThreadState::self()->getCallingPid();
+ int callingUid = IPCThreadState::self()->getCallingUid();
// Trust it if this is called from the same process otherwise pid has to match the calling pid.
- return (callingPid == getpid()) || (callingPid == pid);
+ return (callingPid == getpid()) || (callingPid == pid) || (callingUid == AID_MEDIA);
}
ProcessInfo::~ProcessInfo() {}
diff --git a/media/utils/TimeCheck.cpp b/media/utils/TimeCheck.cpp
index 265a232..96f7802 100644
--- a/media/utils/TimeCheck.cpp
+++ b/media/utils/TimeCheck.cpp
@@ -82,10 +82,10 @@
if (waitTimeNs > 0) {
status = mCond.waitRelative(mMutex, waitTimeNs);
}
- }
- if (status != NO_ERROR) {
- LOG_EVENT_STRING(LOGTAG_AUDIO_BINDER_TIMEOUT, tag);
- LOG_ALWAYS_FATAL("TimeCheck timeout for %s", tag);
+ if (status != NO_ERROR) {
+ LOG_EVENT_STRING(LOGTAG_AUDIO_BINDER_TIMEOUT, tag);
+ LOG_ALWAYS_FATAL("TimeCheck timeout for %s", tag);
+ }
}
return true;
}
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 9e76096..41a71d5 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -563,7 +563,7 @@
mFrameSize, !isExternalTrack(), sampleRate);
} else {
mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
- mFrameSize);
+ mFrameSize, sampleRate);
}
mServerProxy = mAudioTrackServerProxy;
diff --git a/services/audiopolicy/common/Android.bp b/services/audiopolicy/common/Android.bp
index a925b9a..6e0d2f6 100644
--- a/services/audiopolicy/common/Android.bp
+++ b/services/audiopolicy/common/Android.bp
@@ -1,4 +1,7 @@
cc_library_headers {
name: "libaudiopolicycommon",
+ header_libs: [
+ "libaudiofoundation_headers",
+ ],
export_include_dirs: ["include"],
}
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h
index 1dbd1eb..c3a02f9 100644
--- a/services/audiopolicy/common/include/Volume.h
+++ b/services/audiopolicy/common/include/Volume.h
@@ -17,6 +17,7 @@
#pragma once
#include <media/AudioCommonTypes.h>
+#include <media/AudioContainers.h>
#include <system/audio.h>
#include <utils/Log.h>
#include <math.h>
@@ -82,43 +83,55 @@
*
* @return subset of device required to limit the number of volume category per device
*/
- static audio_devices_t getDeviceForVolume(audio_devices_t device)
+ static audio_devices_t getDeviceForVolume(const android::DeviceTypeSet& deviceTypes)
{
- if (device == AUDIO_DEVICE_NONE) {
+ audio_devices_t deviceType = AUDIO_DEVICE_NONE;
+ if (deviceTypes.empty()) {
// this happens when forcing a route update and no track is active on an output.
// In this case the returned category is not important.
- device = AUDIO_DEVICE_OUT_SPEAKER;
- } else if (popcount(device) > 1) {
+ deviceType = AUDIO_DEVICE_OUT_SPEAKER;
+ } else if (deviceTypes.size() > 1) {
// Multiple device selection is either:
// - speaker + one other device: give priority to speaker in this case.
// - one A2DP device + another device: happens with duplicated output. In this case
// retain the device on the A2DP output as the other must not correspond to an active
// selection if not the speaker.
// - HDMI-CEC system audio mode only output: give priority to available item in order.
- if (device & AUDIO_DEVICE_OUT_SPEAKER) {
- device = AUDIO_DEVICE_OUT_SPEAKER;
- } else if (device & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
- device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
- } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) {
- device = AUDIO_DEVICE_OUT_HDMI_ARC;
- } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) {
- device = AUDIO_DEVICE_OUT_AUX_LINE;
- } else if (device & AUDIO_DEVICE_OUT_SPDIF) {
- device = AUDIO_DEVICE_OUT_SPDIF;
+ if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER) != 0) {
+ deviceType = AUDIO_DEVICE_OUT_SPEAKER;
+ } else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER_SAFE) != 0) {
+ deviceType = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+ } else if (deviceTypes.count(AUDIO_DEVICE_OUT_HDMI_ARC) != 0) {
+ deviceType = AUDIO_DEVICE_OUT_HDMI_ARC;
+ } else if (deviceTypes.count(AUDIO_DEVICE_OUT_AUX_LINE) != 0) {
+ deviceType = AUDIO_DEVICE_OUT_AUX_LINE;
+ } else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPDIF) != 0) {
+ deviceType = AUDIO_DEVICE_OUT_SPDIF;
} else {
- device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP);
+ std::vector<audio_devices_t> a2dpDevices = android::Intersection(
+ deviceTypes, android::getAudioDeviceOutAllA2dpSet());
+ if (a2dpDevices.size() > 1) {
+ ALOGW("getDeviceForVolume() invalid device combination: %s",
+ android::dumpDeviceTypes(deviceTypes).c_str());
+ }
+ if (!a2dpDevices.empty()) {
+ deviceType = a2dpDevices[0];
+ }
}
+ } else {
+ deviceType = *(deviceTypes.begin());
}
/*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
- if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
- device = AUDIO_DEVICE_OUT_SPEAKER;
+ if (deviceType == AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
+ deviceType = AUDIO_DEVICE_OUT_SPEAKER;
+ }
- ALOGW_IF(popcount(device) != 1,
- "getDeviceForVolume() invalid device combination: %08x",
- device);
+ ALOGW_IF(deviceType == AUDIO_DEVICE_NONE,
+ "getDeviceForVolume() invalid device combination: %s, returning AUDIO_DEVICE_NONE",
+ android::dumpDeviceTypes(deviceTypes).c_str());
- return device;
+ return deviceType;
}
/**
@@ -128,9 +141,9 @@
*
* @return device category.
*/
- static device_category getDeviceCategory(audio_devices_t device)
+ static device_category getDeviceCategory(const android::DeviceTypeSet& deviceTypes)
{
- switch(getDeviceForVolume(device)) {
+ switch(getDeviceForVolume(deviceTypes)) {
case AUDIO_DEVICE_OUT_EARPIECE:
return DEVICE_CATEGORY_EARPIECE;
case AUDIO_DEVICE_OUT_WIRED_HEADSET:
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 96fec4a..41f7dfc 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -21,6 +21,7 @@
#include <sys/types.h>
+#include <media/AudioContainers.h>
#include <utils/Errors.h>
#include <utils/Timers.h>
#include <utils/KeyedVector.h>
@@ -156,10 +157,10 @@
virtual DeviceVector supportedDevices() const { return mDevices; }
virtual bool isDuplicated() const { return false; }
virtual uint32_t latency() { return 0; }
- virtual bool isFixedVolume(audio_devices_t device);
+ virtual bool isFixedVolume(const DeviceTypeSet& deviceTypes);
virtual bool setVolume(float volumeDb,
VolumeSource volumeSource, const StreamTypeVector &streams,
- audio_devices_t device,
+ const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
bool force);
@@ -329,10 +330,10 @@
void setDevices(const DeviceVector &devices) { mDevices = devices; }
bool sharesHwModuleWith(const sp<SwAudioOutputDescriptor>& outputDesc);
virtual DeviceVector supportedDevices() const;
- virtual bool deviceSupportsEncodedFormats(audio_devices_t device);
+ virtual bool devicesSupportEncodedFormats(const DeviceTypeSet& deviceTypes);
virtual uint32_t latency();
virtual bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); }
- virtual bool isFixedVolume(audio_devices_t device);
+ virtual bool isFixedVolume(const DeviceTypeSet& deviceTypes);
sp<SwAudioOutputDescriptor> subOutput1() { return mOutput1; }
sp<SwAudioOutputDescriptor> subOutput2() { return mOutput2; }
void setClientActive(const sp<TrackClientDescriptor>& client, bool active) override;
@@ -344,7 +345,7 @@
}
virtual bool setVolume(float volumeDb,
VolumeSource volumeSource, const StreamTypeVector &streams,
- audio_devices_t device,
+ const DeviceTypeSet& device,
uint32_t delayMs,
bool force);
@@ -418,7 +419,7 @@
virtual bool setVolume(float volumeDb,
VolumeSource volumeSource, const StreamTypeVector &streams,
- audio_devices_t device,
+ const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
bool force);
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index eb1bfa7..158215d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -17,6 +17,7 @@
#pragma once
#include "PolicyAudioPort.h"
+#include <media/AudioContainers.h>
#include <media/DeviceDescriptorBase.h>
#include <utils/Errors.h>
#include <utils/String8.h>
@@ -93,7 +94,7 @@
class DeviceVector : public SortedVector<sp<DeviceDescriptor> >
{
public:
- DeviceVector() : SortedVector(), mDeviceTypes(AUDIO_DEVICE_NONE) {}
+ DeviceVector() : SortedVector() {}
explicit DeviceVector(const sp<DeviceDescriptor>& item) : DeviceVector()
{
add(item);
@@ -105,13 +106,16 @@
void remove(const DeviceVector &devices);
ssize_t indexOf(const sp<DeviceDescriptor>& item) const;
- audio_devices_t types() const { return mDeviceTypes; }
+ DeviceTypeSet types() const { return mDeviceTypes; }
// If 'address' is empty and 'codec' is AUDIO_FORMAT_DEFAULT, a device with a non-empty
// address may be returned if there is no device with the specified 'type' and empty address.
sp<DeviceDescriptor> getDevice(audio_devices_t type, const String8 &address,
audio_format_t codec) const;
- DeviceVector getDevicesFromTypeMask(audio_devices_t types) const;
+ DeviceVector getDevicesFromTypes(const DeviceTypeSet& types) const;
+ DeviceVector getDevicesFromType(audio_devices_t type) const {
+ return getDevicesFromTypes({type});
+ }
/**
* @brief getDeviceFromId
@@ -122,7 +126,6 @@
sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
sp<DeviceDescriptor> getDeviceFromTagName(const std::string &tagName) const;
DeviceVector getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
- audio_devices_t getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const;
DeviceVector getFirstDevicesFromTypes(std::vector<audio_devices_t> orderedTypes) const;
sp<DeviceDescriptor> getFirstExistingDevice(std::vector<audio_devices_t> orderedTypes) const;
@@ -131,6 +134,18 @@
// remove all the devices with the given type and add all the devices to add.
void replaceDevicesByType(audio_devices_t typeToRemove, const DeviceVector &devicesToAdd);
+ bool containsDeviceAmongTypes(const DeviceTypeSet& deviceTypes) const {
+ return !Intersection(mDeviceTypes, deviceTypes).empty();
+ }
+
+ bool containsDeviceWithType(audio_devices_t deviceType) const {
+ return containsDeviceAmongTypes({deviceType});
+ }
+
+ bool onlyContainsDevicesWithType(audio_devices_t deviceType) const {
+ return isSingleDeviceType(mDeviceTypes, deviceType);
+ }
+
bool contains(const sp<DeviceDescriptor>& item) const { return indexOf(item) >= 0; }
/**
@@ -223,7 +238,7 @@
private:
void refreshTypes();
- audio_devices_t mDeviceTypes;
+ DeviceTypeSet mDeviceTypes;
};
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index 028cb63..23f0c9a 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -131,8 +131,8 @@
public:
sp<HwModule> getModuleFromName(const char *name) const;
- sp<HwModule> getModuleForDeviceTypes(audio_devices_t device,
- audio_format_t encodedFormat) const;
+ sp<HwModule> getModuleForDeviceType(audio_devices_t device,
+ audio_format_t encodedFormat) const;
sp<HwModule> getModuleForDevice(const sp<DeviceDescriptor> &device,
audio_format_t encodedFormat) const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index dcb4730..2044863 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -19,6 +19,7 @@
#include "DeviceDescriptor.h"
#include "PolicyAudioPort.h"
#include "policy.h"
+#include <media/AudioContainers.h>
#include <utils/String8.h>
#include <system/audio.h>
@@ -102,15 +103,12 @@
bool hasSupportedDevices() const { return !mSupportedDevices.isEmpty(); }
- bool supportsDeviceTypes(audio_devices_t device) const
+ bool supportsDeviceTypes(const DeviceTypeSet& deviceTypes) const
{
- if (audio_is_output_devices(device)) {
- if (deviceSupportsEncodedFormats(device)) {
- return mSupportedDevices.types() & device;
- }
- return false;
- }
- return mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN);
+ const bool areOutputDevices = Intersection(deviceTypes, getAudioDeviceInAllSet()).empty();
+ const bool devicesSupported = !mSupportedDevices.getDevicesFromTypes(deviceTypes).empty();
+ return devicesSupported &&
+ (!areOutputDevices || devicesSupportEncodedFormats(deviceTypes));
}
/**
@@ -125,18 +123,18 @@
bool supportsDevice(const sp<DeviceDescriptor> &device, bool forceCheckOnAddress = false) const
{
if (!device_distinguishes_on_address(device->type()) && !forceCheckOnAddress) {
- return supportsDeviceTypes(device->type());
+ return supportsDeviceTypes(DeviceTypeSet({device->type()}));
}
return mSupportedDevices.contains(device);
}
- bool deviceSupportsEncodedFormats(audio_devices_t device) const
+ bool devicesSupportEncodedFormats(DeviceTypeSet deviceTypes) const
{
- if (device == AUDIO_DEVICE_NONE) {
+ if (deviceTypes.empty()) {
return true; // required for isOffloadSupported() check
}
DeviceVector deviceList =
- mSupportedDevices.getDevicesFromTypeMask(device);
+ mSupportedDevices.getDevicesFromTypes(deviceTypes);
if (!deviceList.empty()) {
return deviceList.itemAt(0)->hasCurrentEncodedFormat();
}
diff --git a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
index d408446..fd8b81a 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
@@ -16,8 +16,9 @@
#pragma once
-#include <system/audio.h>
#include <Volume.h>
+#include <media/AudioContainers.h>
+#include <system/audio.h>
#include <utils/Errors.h>
#include <utils/String8.h>
#include <vector>
@@ -33,7 +34,7 @@
virtual void addCurrentVolumeIndex(audio_devices_t device, int index) = 0;
virtual bool canBeMuted() const = 0;
virtual int getVolumeIndexMin() const = 0;
- virtual int getVolumeIndex(audio_devices_t device) const = 0;
+ virtual int getVolumeIndex(const DeviceTypeSet& device) const = 0;
virtual int getVolumeIndexMax() const = 0;
virtual float volIndexToDb(device_category device, int indexInUi) const = 0;
virtual bool hasVolumeIndexForDevice(audio_devices_t device) const = 0;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 00000fe..4ff69ee 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -30,10 +30,11 @@
// A device mask for all audio output devices that are considered "remote" when evaluating
// active output devices in isStreamActiveRemotely()
-#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL AUDIO_DEVICE_OUT_REMOTE_SUBMIX
namespace android {
+DeviceTypeSet APM_AUDIO_OUT_DEVICE_REMOTE_ALL = {AUDIO_DEVICE_OUT_REMOTE_SUBMIX};
+
AudioOutputDescriptor::AudioOutputDescriptor(const sp<PolicyAudioPort>& policyAudioPort,
AudioPolicyClientInterface *clientInterface)
: mPolicyAudioPort(policyAudioPort), mClientInterface(clientInterface)
@@ -140,7 +141,7 @@
return false;
}
-bool AudioOutputDescriptor::isFixedVolume(audio_devices_t device __unused)
+bool AudioOutputDescriptor::isFixedVolume(const DeviceTypeSet& deviceTypes __unused)
{
return false;
}
@@ -148,7 +149,7 @@
bool AudioOutputDescriptor::setVolume(float volumeDb,
VolumeSource volumeSource,
const StreamTypeVector &/*streams*/,
- audio_devices_t /*device*/,
+ const DeviceTypeSet& /*deviceTypes*/,
uint32_t delayMs,
bool force)
{
@@ -334,13 +335,13 @@
return filteredDevices.filter(devices);
}
-bool SwAudioOutputDescriptor::deviceSupportsEncodedFormats(audio_devices_t device)
+bool SwAudioOutputDescriptor::devicesSupportEncodedFormats(const DeviceTypeSet& deviceTypes)
{
if (isDuplicated()) {
- return (mOutput1->deviceSupportsEncodedFormats(device)
- || mOutput2->deviceSupportsEncodedFormats(device));
+ return (mOutput1->devicesSupportEncodedFormats(deviceTypes)
+ || mOutput2->devicesSupportEncodedFormats(deviceTypes));
} else {
- return mProfile->deviceSupportsEncodedFormats(device);
+ return mProfile->devicesSupportEncodedFormats(deviceTypes);
}
}
@@ -363,16 +364,16 @@
AudioOutputDescriptor::setClientActive(client, active);
}
-bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device)
+bool SwAudioOutputDescriptor::isFixedVolume(const DeviceTypeSet& deviceTypes)
{
// unit gain if rerouting to external policy
- if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) {
+ if (isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) {
if (mPolicyMix != NULL) {
ALOGV("max gain when rerouting for output=%d", mIoHandle);
return true;
}
}
- if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
+ if (isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
ALOGV("max gain when output device is telephony tx");
return true;
}
@@ -405,12 +406,12 @@
bool SwAudioOutputDescriptor::setVolume(float volumeDb,
VolumeSource vs, const StreamTypeVector &streamTypes,
- audio_devices_t device,
+ const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
bool force)
{
StreamTypeVector streams = streamTypes;
- if (!AudioOutputDescriptor::setVolume(volumeDb, vs, streamTypes, device, delayMs, force)) {
+ if (!AudioOutputDescriptor::setVolume(volumeDb, vs, streamTypes, deviceTypes, delayMs, force)) {
return false;
}
if (streams.empty()) {
@@ -420,7 +421,7 @@
// APM loops on all group, so filter on active group to set the port gain,
// let the other groups set the stream volume as per legacy
// TODO: Pass in the device address and check against it.
- if (device == devicePort->type() &&
+ if (isSingleDeviceType(deviceTypes, devicePort->type()) &&
devicePort->hasGainController(true) && isActive(vs)) {
ALOGV("%s: device %s has gain controller", __func__, devicePort->toString().c_str());
// @todo: here we might be in trouble if the SwOutput has several active clients with
@@ -467,7 +468,7 @@
{
mDevices = devices;
const String8& address = devices.getFirstValidAddress();
- audio_devices_t device = devices.types();
+ DeviceTypeSet deviceTypes = devices.types();
audio_config_t lConfig;
if (config == nullptr) {
@@ -499,21 +500,25 @@
ALOGV("opening output for device %s profile %p name %s",
mDevices.toString().c_str(), mProfile.get(), mProfile->getName().c_str());
+ // FIXME: Stop using device types as bit mask when the interface updated.
+ audio_devices_t deviceType = deviceTypesToBitMask(deviceTypes);
status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
output,
&lConfig,
- &device,
+ &deviceType,
address,
&mLatency,
mFlags);
- LOG_ALWAYS_FATAL_IF(mDevices.types() != device,
- "%s openOutput returned device %08x when given device %08x",
- __FUNCTION__, mDevices.types(), device);
+ deviceTypes = deviceTypesFromBitMask(deviceType);
+ LOG_ALWAYS_FATAL_IF(mDevices.types() != deviceTypes,
+ "%s openOutput returned device %s when given device %s",
+ __FUNCTION__, dumpDeviceTypes(mDevices.types()).c_str(),
+ dumpDeviceTypes(deviceTypes).c_str());
if (status == NO_ERROR) {
LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
- "%s openOutput returned output handle %d for device %08x",
- __FUNCTION__, *output, device);
+ "%s openOutput returned output handle %d for device %s",
+ __FUNCTION__, *output, dumpDeviceTypes(deviceTypes).c_str());
mSamplingRate = lConfig.sample_rate;
mChannelMask = lConfig.channel_mask;
mFormat = lConfig.format;
@@ -646,12 +651,12 @@
bool HwAudioOutputDescriptor::setVolume(float volumeDb,
VolumeSource volumeSource, const StreamTypeVector &streams,
- audio_devices_t device,
+ const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
bool force)
{
- bool changed =
- AudioOutputDescriptor::setVolume(volumeDb, volumeSource, streams, device, delayMs, force);
+ bool changed = AudioOutputDescriptor::setVolume(
+ volumeDb, volumeSource, streams, deviceTypes, delayMs, force);
if (changed) {
// TODO: use gain controller on source device if any to adjust volume
@@ -678,7 +683,8 @@
for (size_t i = 0; i < this->size(); i++) {
const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
if (outputDesc->isActive(volumeSource, inPastMs, sysTime)
- && ((outputDesc->devices().types() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) == 0)) {
+ && (!(outputDesc->devices()
+ .containsDeviceAmongTypes(APM_AUDIO_OUT_DEVICE_REMOTE_ALL)))) {
return true;
}
}
@@ -690,7 +696,7 @@
nsecs_t sysTime = systemTime();
for (size_t i = 0; i < size(); i++) {
const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
- if (((outputDesc->devices().types() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
+ if (outputDesc->devices().containsDeviceAmongTypes(APM_AUDIO_OUT_DEVICE_REMOTE_ALL) &&
outputDesc->isActive(volumeSource, inPastMs, sysTime)) {
// do not consider re routing (when the output is going to a dynamic policy)
// as "remote playback"
@@ -721,9 +727,8 @@
for (size_t i = 0; i < size(); i++) {
sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
if (!outputDesc->isDuplicated() &&
- outputDesc->devices().types() & AUDIO_DEVICE_OUT_ALL_A2DP &&
- outputDesc->deviceSupportsEncodedFormats(
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
+ outputDesc->devices().containsDeviceAmongTypes(getAudioDeviceOutAllA2dpSet()) &&
+ outputDesc->devicesSupportEncodedFormats(getAudioDeviceOutAllA2dpSet())) {
return this->keyAt(i);
}
}
@@ -739,7 +744,7 @@
sp<HwModule> primaryHwModule = primaryOutput->mProfile->getModule();
for (const auto &outputProfile : primaryHwModule->getOutputProfiles()) {
- if (outputProfile->supportsDeviceTypes(AUDIO_DEVICE_OUT_ALL_A2DP)) {
+ if (outputProfile->supportsDeviceTypes(getAudioDeviceOutAllA2dpSet())) {
return true;
}
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 3d3eb9c..4e8c01c 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -164,11 +164,11 @@
void DeviceVector::refreshTypes()
{
- mDeviceTypes = AUDIO_DEVICE_NONE;
+ mDeviceTypes.clear();
for (size_t i = 0; i < size(); i++) {
- mDeviceTypes |= itemAt(i)->type();
+ mDeviceTypes.insert(itemAt(i)->type());
}
- ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
+ ALOGV("DeviceVector::refreshTypes() mDeviceTypes %s", dumpDeviceTypes(mDeviceTypes).c_str());
}
ssize_t DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
@@ -243,17 +243,6 @@
return devices;
}
-audio_devices_t DeviceVector::getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const
-{
- audio_devices_t deviceTypes = AUDIO_DEVICE_NONE;
- for (const auto& device : *this) {
- if (device->getModuleHandle() == moduleHandle) {
- deviceTypes |= device->type();
- }
- }
- return deviceTypes;
-}
-
sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, const String8& address,
audio_format_t format) const
{
@@ -290,15 +279,14 @@
return nullptr;
}
-DeviceVector DeviceVector::getDevicesFromTypeMask(audio_devices_t type) const
+DeviceVector DeviceVector::getDevicesFromTypes(const DeviceTypeSet& types) const
{
DeviceVector devices;
- bool isOutput = audio_is_output_devices(type);
- type &= ~AUDIO_DEVICE_BIT_IN;
- for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) {
- bool curIsOutput = audio_is_output_devices(itemAt(i)->type());
- audio_devices_t curType = itemAt(i)->type() & ~AUDIO_DEVICE_BIT_IN;
- if ((isOutput == curIsOutput) && ((type & curType) != 0)) {
+ if (types.empty()) {
+ return devices;
+ }
+ for (size_t i = 0; i < size(); i++) {
+ if (types.count(itemAt(i)->type()) != 0) {
devices.add(itemAt(i));
ALOGV("DeviceVector::%s() for type %08x found %p",
__func__, itemAt(i)->type(), itemAt(i).get());
@@ -322,7 +310,7 @@
{
DeviceVector devices;
for (auto deviceType : orderedTypes) {
- if (!(devices = getDevicesFromTypeMask(deviceType)).isEmpty()) {
+ if (!(devices = getDevicesFromType(deviceType)).isEmpty()) {
break;
}
}
@@ -342,7 +330,7 @@
void DeviceVector::replaceDevicesByType(
audio_devices_t typeToRemove, const DeviceVector &devicesToAdd) {
- DeviceVector devicesToRemove = getDevicesFromTypeMask(typeToRemove);
+ DeviceVector devicesToRemove = getDevicesFromType(typeToRemove);
if (!devicesToRemove.isEmpty() && !devicesToAdd.isEmpty()) {
remove(devicesToRemove);
add(devicesToAdd);
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 453006a..0b4d3d4 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -273,14 +273,14 @@
return nullptr;
}
-sp <HwModule> HwModuleCollection::getModuleForDeviceTypes(audio_devices_t type,
- audio_format_t encodedFormat) const
+sp <HwModule> HwModuleCollection::getModuleForDeviceType(audio_devices_t type,
+ audio_format_t encodedFormat) const
{
for (const auto& module : *this) {
const auto& profiles = audio_is_output_device(type) ?
module->getOutputProfiles() : module->getInputProfiles();
for (const auto& profile : profiles) {
- if (profile->supportsDeviceTypes(type)) {
+ if (profile->supportsDeviceTypes({type})) {
if (encodedFormat != AUDIO_FORMAT_DEFAULT) {
DeviceVector declaredDevices = module->getDeclaredDevices();
sp <DeviceDescriptor> deviceDesc =
@@ -300,7 +300,7 @@
sp<HwModule> HwModuleCollection::getModuleForDevice(const sp<DeviceDescriptor> &device,
audio_format_t encodedFormat) const
{
- return getModuleForDeviceTypes(device->type(), encodedFormat);
+ return getModuleForDeviceType(device->type(), encodedFormat);
}
DeviceVector HwModuleCollection::getAvailableDevicesFromModuleName(
@@ -354,7 +354,7 @@
const char *name,
const audio_format_t encodedFormat) const
{
- sp<HwModule> hwModule = getModuleForDeviceTypes(type, encodedFormat);
+ sp<HwModule> hwModule = getModuleForDeviceType(type, encodedFormat);
if (hwModule == 0) {
ALOGE("%s: could not find HW module for device %04x address %s", __FUNCTION__, type,
address);
diff --git a/services/audiopolicy/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp
index d0775ad..b87c71d 100644
--- a/services/audiopolicy/engine/common/Android.bp
+++ b/services/audiopolicy/engine/common/Android.bp
@@ -44,4 +44,7 @@
"libaudiopolicycomponents",
"libaudiopolicyengine_config",
],
+ shared_libs: [
+ "libaudiofoundation",
+ ],
}
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index c538f52..ab8eff3 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -27,6 +27,7 @@
#include <utils/Errors.h>
#include <utils/String8.h>
#include <media/AudioAttributes.h>
+#include <media/AudioContainers.h>
namespace android {
@@ -77,12 +78,12 @@
std::string getDeviceAddress() const { return mDeviceAddress; }
- void setDeviceTypes(audio_devices_t devices)
+ void setDeviceTypes(const DeviceTypeSet& devices)
{
mApplicableDevices = devices;
}
- audio_devices_t getDeviceTypes() const { return mApplicableDevices; }
+ DeviceTypeSet getDeviceTypes() const { return mApplicableDevices; }
audio_attributes_t getAttributesForStreamType(audio_stream_type_t stream) const;
audio_stream_type_t getStreamTypeForAttributes(const audio_attributes_t &attr) const;
@@ -109,7 +110,7 @@
/**
* Applicable device(s) type mask for this strategy.
*/
- audio_devices_t mApplicableDevices = AUDIO_DEVICE_NONE;
+ DeviceTypeSet mApplicableDevices;
};
class ProductStrategyMap : public std::map<product_strategy_t, sp<ProductStrategy> >
@@ -144,7 +145,7 @@
*/
audio_attributes_t getAttributesForProductStrategy(product_strategy_t strategy) const;
- audio_devices_t getDeviceTypesForProductStrategy(product_strategy_t strategy) const;
+ DeviceTypeSet getDeviceTypesForProductStrategy(product_strategy_t strategy) const;
std::string getDeviceAddressForProductStrategy(product_strategy_t strategy) const;
diff --git a/services/audiopolicy/engine/common/include/VolumeCurve.h b/services/audiopolicy/engine/common/include/VolumeCurve.h
index d3d0904..2e75ff1 100644
--- a/services/audiopolicy/engine/common/include/VolumeCurve.h
+++ b/services/audiopolicy/engine/common/include/VolumeCurve.h
@@ -91,9 +91,9 @@
return valueFor(device);
}
- virtual int getVolumeIndex(audio_devices_t device) const
+ virtual int getVolumeIndex(const DeviceTypeSet& deviceTypes) const
{
- device = Volume::getDeviceForVolume(device);
+ audio_devices_t device = Volume::getDeviceForVolume(deviceTypes);
// there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME
if (mIndexCur.find(device) == end(mIndexCur)) {
device = AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME;
@@ -114,7 +114,7 @@
bool hasVolumeIndexForDevice(audio_devices_t device) const
{
- device = Volume::getDeviceForVolume(device);
+ device = Volume::getDeviceForVolume({device});
return mIndexCur.find(device) != end(mIndexCur);
}
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index ac3e462..14c9dd1 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -143,8 +143,9 @@
{
dst->appendFormat("\n%*s-%s (id: %d)\n", spaces, "", mName.c_str(), mId);
std::string deviceLiteral;
- if (!OutputDeviceConverter::toString(mApplicableDevices, deviceLiteral)) {
- ALOGE("%s: failed to convert device %d", __FUNCTION__, mApplicableDevices);
+ if (!deviceTypesToString(mApplicableDevices, deviceLiteral)) {
+ ALOGE("%s: failed to convert device %s",
+ __FUNCTION__, dumpDeviceTypes(mApplicableDevices).c_str());
}
dst->appendFormat("%*sSelected Device: {type:%s, @:%s}\n", spaces + 2, "",
deviceLiteral.c_str(), mDeviceAddress.c_str());
@@ -236,14 +237,14 @@
}
-audio_devices_t ProductStrategyMap::getDeviceTypesForProductStrategy(
+DeviceTypeSet ProductStrategyMap::getDeviceTypesForProductStrategy(
product_strategy_t strategy) const
{
if (find(strategy) == end()) {
ALOGE("Invalid %d strategy requested, returning device for default strategy", strategy);
product_strategy_t defaultStrategy = getDefault();
if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
- return AUDIO_DEVICE_NONE;
+ return {AUDIO_DEVICE_NONE};
}
return at(getDefault())->getDeviceTypes();
}
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 3987294..0a88685 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -32,6 +32,7 @@
#include <policy.h>
#include <AudioIODescriptorInterface.h>
#include <ParameterManagerWrapper.h>
+#include <media/AudioContainers.h>
#include <media/TypeConverter.h>
@@ -167,11 +168,13 @@
mPolicyParameterMgr->setDeviceConnectionState(devDesc, state);
if (audio_is_output_device(devDesc->type())) {
+ // FIXME: Use DeviceTypeSet when the interface is ready
return mPolicyParameterMgr->setAvailableOutputDevices(
- getApmObserver()->getAvailableOutputDevices().types());
+ deviceTypesToBitMask(getApmObserver()->getAvailableOutputDevices().types()));
} else if (audio_is_input_device(devDesc->type())) {
+ // FIXME: Use DeviceTypeSet when the interface is ready
return mPolicyParameterMgr->setAvailableInputDevices(
- getApmObserver()->getAvailableInputDevices().types());
+ deviceTypesToBitMask(getApmObserver()->getAvailableInputDevices().types()));
}
return BAD_TYPE;
}
@@ -211,7 +214,7 @@
}
const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
- uint32_t availableOutputDevicesType = availableOutputDevices.types();
+ DeviceTypeSet availableOutputDevicesTypes = availableOutputDevices.types();
/** This is the only case handled programmatically because the PFW is unable to know the
* activity of streams.
@@ -223,7 +226,7 @@
*
* -When media is not playing anymore, fall back on the sonification behavior
*/
- audio_devices_t devices = AUDIO_DEVICE_NONE;
+ DeviceTypeSet deviceTypes;
if (ps == getProductStrategyForStream(AUDIO_STREAM_NOTIFICATION) &&
!is_state_in_call(getPhoneState()) &&
!outputs.isActiveRemotely(toVolumeSource(AUDIO_STREAM_MUSIC),
@@ -232,7 +235,7 @@
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
product_strategy_t strategyForMedia =
getProductStrategyForStream(AUDIO_STREAM_MUSIC);
- devices = productStrategies.getDeviceTypesForProductStrategy(strategyForMedia);
+ deviceTypes = productStrategies.getDeviceTypesForProductStrategy(strategyForMedia);
} else if (ps == getProductStrategyForStream(AUDIO_STREAM_ACCESSIBILITY) &&
(outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM)))) {
@@ -240,36 +243,37 @@
// compressed format as they would likely not be mixed and dropped.
// Device For Sonification conf file has HDMI, SPDIF and HDMI ARC unreacheable.
product_strategy_t strategyNotification = getProductStrategyForStream(AUDIO_STREAM_RING);
- devices = productStrategies.getDeviceTypesForProductStrategy(strategyNotification);
+ deviceTypes = productStrategies.getDeviceTypesForProductStrategy(strategyNotification);
} else {
- devices = productStrategies.getDeviceTypesForProductStrategy(ps);
+ deviceTypes = productStrategies.getDeviceTypesForProductStrategy(ps);
}
- if (devices == AUDIO_DEVICE_NONE ||
- (devices & availableOutputDevicesType) == AUDIO_DEVICE_NONE) {
+ if (deviceTypes.empty() ||
+ Intersection(deviceTypes, availableOutputDevicesTypes).empty()) {
auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
ALOG_ASSERT(defaultDevice != nullptr, "no valid default device defined");
return DeviceVector(defaultDevice);
}
- if (/*device_distinguishes_on_address(devices)*/ devices == AUDIO_DEVICE_OUT_BUS) {
+ if (/*device_distinguishes_on_address(*deviceTypes.begin())*/ isSingleDeviceType(
+ deviceTypes, AUDIO_DEVICE_OUT_BUS)) {
// We do expect only one device for these types of devices
// Criterion device address garantee this one is available
// If this criterion is not wished, need to ensure this device is available
const String8 address(productStrategies.getDeviceAddressForProductStrategy(ps).c_str());
- ALOGV("%s:device 0x%x %s %d", __FUNCTION__, devices, address.c_str(), ps);
- auto busDevice = availableOutputDevices.getDevice(devices, address, AUDIO_FORMAT_DEFAULT);
+ ALOGV("%s:device %s %s %d",
+ __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), address.c_str(), ps);
+ auto busDevice = availableOutputDevices.getDevice(
+ *deviceTypes.begin(), address, AUDIO_FORMAT_DEFAULT);
if (busDevice == nullptr) {
- ALOGE("%s:unavailable device 0x%x %s, fallback on default", __func__, devices,
- address.c_str());
+ ALOGE("%s:unavailable device %s %s, fallback on default", __func__,
+ dumpDeviceTypes(deviceTypes).c_str(), address.c_str());
auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
ALOG_ASSERT(defaultDevice != nullptr, "Default Output Device NOT available");
return DeviceVector(defaultDevice);
}
- return DeviceVector(availableOutputDevices.getDevice(devices,
- address,
- AUDIO_FORMAT_DEFAULT));
+ return DeviceVector(busDevice);
}
- ALOGV("%s:device 0x%x %d", __FUNCTION__, devices, ps);
- return availableOutputDevices.getDevicesFromTypeMask(devices);
+ ALOGV("%s:device %s %d", __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), ps);
+ return availableOutputDevices.getDevicesFromTypes(deviceTypes);
}
DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
@@ -366,7 +370,8 @@
ALOGE("%s: set device %d on invalid strategy %d", __FUNCTION__, devices, strategy);
return false;
}
- getProductStrategies().at(strategy)->setDeviceTypes(devices);
+ // FIXME: stop using deviceTypesFromBitMask when the interface is ready
+ getProductStrategies().at(strategy)->setDeviceTypes(deviceTypesFromBitMask(devices));
return true;
}
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index a02f567..2a5cd49 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -31,6 +31,7 @@
#include <IOProfile.h>
#include <AudioIODescriptorInterface.h>
#include <policy.h>
+#include <media/AudioContainers.h>
#include <utils/String8.h>
#include <utils/Log.h>
@@ -146,7 +147,7 @@
switch (strategy) {
case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
- devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
+ devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
break;
case STRATEGY_SONIFICATION_RESPECTFUL:
@@ -161,7 +162,7 @@
toVolumeSource(AUDIO_STREAM_ACCESSIBILITY),
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
// routing is same as media without the "remote" device
- availableOutputDevices.remove(availableOutputDevices.getDevicesFromTypeMask(
+ availableOutputDevices.remove(availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_REMOTE_SUBMIX));
devices = getDevicesForStrategyInt(STRATEGY_MEDIA,
availableOutputDevices,
@@ -171,7 +172,7 @@
if (!media_active_locally) {
devices.replaceDevicesByType(
AUDIO_DEVICE_OUT_SPEAKER,
- availableOutputDevices.getDevicesFromTypeMask(
+ availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_SPEAKER_SAFE));
}
}
@@ -204,10 +205,10 @@
// audio_policy_configuration.xml, hearing aid is not there, but it's
// a primary device
// FIXME: this is not the right way of solving this problem
- DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypeMask(
+ DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypes(
primaryOutput->supportedDevices().types());
availPrimaryOutputDevices.add(
- availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID));
+ availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID));
if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
@@ -222,7 +223,7 @@
switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
case AUDIO_POLICY_FORCE_BT_SCO:
if (!isInCall() || strategy != STRATEGY_DTMF) {
- devices = availableOutputDevices.getDevicesFromTypeMask(
+ devices = availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
if (!devices.isEmpty()) break;
}
@@ -233,7 +234,7 @@
FALLTHROUGH_INTENDED;
default: // FORCE_NONE
- devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID);
+ devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
if (!devices.isEmpty()) break;
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
if (!isInCall() &&
@@ -255,7 +256,7 @@
AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
if (!devices.isEmpty()) break;
}
- devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_EARPIECE);
+ devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_EARPIECE);
break;
case AUDIO_POLICY_FORCE_SPEAKER:
@@ -264,7 +265,7 @@
if (!isInCall() &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
outputs.isA2dpSupported()) {
- devices = availableOutputDevices.getDevicesFromTypeMask(
+ devices = availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
if (!devices.isEmpty()) break;
}
@@ -275,7 +276,7 @@
AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
if (!devices.isEmpty()) break;
}
- devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
+ devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
break;
}
break;
@@ -299,12 +300,12 @@
if ((strategy == STRATEGY_SONIFICATION) ||
(getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) {
- devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
+ devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
}
// if SCO headset is connected and we are told to use it, play ringtone over
// speaker and BT SCO
- if (!availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_ALL_SCO).isEmpty()) {
+ if (!availableOutputDevices.getDevicesFromTypes(getAudioDeviceOutAllScoSet()).isEmpty()) {
DeviceVector devices2;
devices2 = availableOutputDevices.getFirstDevicesFromTypes({
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
@@ -325,7 +326,7 @@
if (strategy == STRATEGY_SONIFICATION) {
devices.replaceDevicesByType(
AUDIO_DEVICE_OUT_SPEAKER,
- availableOutputDevices.getDevicesFromTypeMask(
+ availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_SPEAKER_SAFE));
}
if (!devices2.isEmpty()) {
@@ -344,9 +345,9 @@
for (size_t i = 0; i < outputs.size(); i++) {
sp<AudioOutputDescriptor> desc = outputs.valueAt(i);
if (desc->isActive() && !audio_is_linear_pcm(desc->getFormat())) {
- availableOutputDevices.remove(desc->devices().getDevicesFromTypeMask(
- AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF
- | AUDIO_DEVICE_OUT_HDMI_ARC));
+ availableOutputDevices.remove(desc->devices().getDevicesFromTypes({
+ AUDIO_DEVICE_OUT_HDMI, AUDIO_DEVICE_OUT_SPDIF,
+ AUDIO_DEVICE_OUT_HDMI_ARC}));
}
}
if (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
@@ -383,7 +384,7 @@
// FIXME: Find a better solution to prevent routing to BT hearing aid(b/122931261).
if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
- devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID);
+ devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
}
if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
@@ -394,7 +395,7 @@
}
if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_SPEAKER)) {
- devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
+ devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
}
if (devices2.isEmpty()) {
devices2 = availableOutputDevices.getFirstDevicesFromTypes({
@@ -405,21 +406,21 @@
}
if ((devices2.isEmpty()) && (strategy != STRATEGY_SONIFICATION)) {
// no sonification on aux digital (e.g. HDMI)
- devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_AUX_DIGITAL);
+ devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_AUX_DIGITAL);
}
if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_DOCK) == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
- devices2 = availableOutputDevices.getDevicesFromTypeMask(
+ devices2 = availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET);
}
if (devices2.isEmpty()) {
- devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
+ devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
}
DeviceVector devices3;
if (strategy == STRATEGY_MEDIA) {
// ARC, SPDIF and AUX_LINE can co-exist with others.
- devices3 = availableOutputDevices.getDevicesFromTypeMask(
- AUDIO_DEVICE_OUT_HDMI_ARC | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_AUX_LINE);
+ devices3 = availableOutputDevices.getDevicesFromTypes({
+ AUDIO_DEVICE_OUT_HDMI_ARC, AUDIO_DEVICE_OUT_SPDIF, AUDIO_DEVICE_OUT_AUX_LINE});
}
devices2.add(devices3);
@@ -431,7 +432,7 @@
if ((strategy == STRATEGY_MEDIA) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO) ==
AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
- devices.remove(devices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER));
+ devices.remove(devices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER));
}
// for STRATEGY_SONIFICATION:
@@ -439,7 +440,7 @@
if (strategy == STRATEGY_SONIFICATION) {
devices.replaceDevicesByType(
AUDIO_DEVICE_OUT_SPEAKER,
- availableOutputDevices.getDevicesFromTypeMask(
+ availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_SPEAKER_SAFE));
}
} break;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index aec9cee..72221a8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -425,7 +425,7 @@
if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
// Check if the device is currently connected
- DeviceVector deviceList = mAvailableOutputDevices.getDevicesFromTypeMask(device);
+ DeviceVector deviceList = mAvailableOutputDevices.getDevicesFromType(device);
if (deviceList.empty()) {
// Nothing to do: device is not connected
return NO_ERROR;
@@ -439,8 +439,8 @@
// Case 1: A2DP active device switches from primary to primary
// module
// Case 2: A2DP device config changes on primary module.
- if (device & AUDIO_DEVICE_OUT_ALL_A2DP) {
- sp<HwModule> module = mHwModules.getModuleForDeviceTypes(device, encodedFormat);
+ if (audio_is_a2dp_out_device(device)) {
+ sp<HwModule> module = mHwModules.getModuleForDeviceType(device, encodedFormat);
audio_module_handle_t primaryHandle = mPrimaryOutput->getModuleHandle();
if (availablePrimaryOutputDevices().contains(devDesc) &&
(module != 0 && module->getHandle() == primaryHandle)) {
@@ -496,8 +496,8 @@
ALOGE("%s() unable to get primary module", __func__);
return NO_INIT;
}
- DeviceVector declaredDevices = primaryModule->getDeclaredDevices().getDevicesFromTypeMask(
- AUDIO_DEVICE_OUT_ALL_A2DP);
+ DeviceVector declaredDevices = primaryModule->getDeclaredDevices().getDevicesFromTypes(
+ getAudioDeviceOutAllA2dpSet());
for (const auto& device : declaredDevices) {
formatSet.insert(device->encodedFormats().begin(), device->encodedFormats().end());
}
@@ -511,7 +511,8 @@
bool createRxPatch = false;
uint32_t muteWaitMs = 0;
- if(!hasPrimaryOutput() || mPrimaryOutput->devices().types() == AUDIO_DEVICE_OUT_STUB) {
+ if(!hasPrimaryOutput() ||
+ mPrimaryOutput->devices().onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_STUB)) {
return muteWaitMs;
}
ALOG_ASSERT(!rxDevices.isEmpty(), "updateCallRouting() no selected output device");
@@ -535,9 +536,9 @@
}
auto telephonyRxModule =
- mHwModules.getModuleForDeviceTypes(AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT);
+ mHwModules.getModuleForDeviceType(AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT);
auto telephonyTxModule =
- mHwModules.getModuleForDeviceTypes(AUDIO_DEVICE_OUT_TELEPHONY_TX, AUDIO_FORMAT_DEFAULT);
+ mHwModules.getModuleForDeviceType(AUDIO_DEVICE_OUT_TELEPHONY_TX, AUDIO_FORMAT_DEFAULT);
// retrieve Rx Source and Tx Sink device descriptors
sp<DeviceDescriptor> rxSourceDevice =
mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
@@ -648,20 +649,6 @@
return audioPatch;
}
-sp<DeviceDescriptor> AudioPolicyManager::findDevice(
- const DeviceVector& devices, audio_devices_t device) const {
- DeviceVector deviceList = devices.getDevicesFromTypeMask(device);
- ALOG_ASSERT(!deviceList.isEmpty(),
- "%s() selected device type %#x is not in devices list", __func__, device);
- return deviceList.itemAt(0);
-}
-
-audio_devices_t AudioPolicyManager::getModuleDeviceTypes(
- const DeviceVector& devices, const char *moduleId) const {
- sp<HwModule> mod = mHwModules.getModuleFromName(moduleId);
- return mod != 0 ? devices.getDeviceTypesFromHwModule(mod->getHandle()) : AUDIO_DEVICE_NONE;
-}
-
bool AudioPolicyManager::isDeviceOfModule(
const sp<DeviceDescriptor>& devDesc, const char *moduleId) const {
sp<HwModule> module = mHwModules.getModuleFromName(moduleId);
@@ -881,7 +868,7 @@
continue;
}
// reject profiles if connected device does not support codec
- if (!curProfile->deviceSupportsEncodedFormats(devices.types())) {
+ if (!curProfile->devicesSupportEncodedFormats(devices.types())) {
continue;
}
if (!directOnly) return curProfile;
@@ -1025,7 +1012,7 @@
// FIXME: provide a more generic approach which is not device specific and move this back
// to getOutputForDevice.
// TODO: Remove check of AUDIO_STREAM_MUSIC once migration is completed on the app side.
- if (outputDevices.types() == AUDIO_DEVICE_OUT_TELEPHONY_TX &&
+ if (outputDevices.onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX) &&
(*stream == AUDIO_STREAM_MUSIC || resultAttr->usage == AUDIO_USAGE_VOICE_COMMUNICATION) &&
audio_is_linear_pcm(config->format) &&
isInCall()) {
@@ -1234,7 +1221,7 @@
for (size_t j = 0; j < patch->mPatch.num_sinks; ++j) {
const struct audio_port_config *sink = &patch->mPatch.sinks[j];
if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
- (sink->ext.device.type & devices.types()) != AUDIO_DEVICE_NONE &&
+ devices.containsDeviceWithType(sink->ext.device.type) &&
(address.isEmpty() || strncmp(sink->ext.device.address, address.string(),
AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
releaseAudioPatch(patch->mHandle, mUidCached);
@@ -1777,14 +1764,15 @@
}
if (stream == AUDIO_STREAM_ENFORCED_AUDIBLE &&
- mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
+ mEngine->getForceUse(
+ AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
setStrategyMute(streamToStrategy(AUDIO_STREAM_ALARM), true, outputDesc);
}
// Automatically enable the remote submix input when output is started on a re routing mix
// of type MIX_TYPE_RECORDERS
- if (audio_is_remote_submix_device(devices.types()) && policyMix != NULL &&
- policyMix->mMixType == MIX_TYPE_RECORDERS) {
+ if (isSingleDeviceType(devices.types(), &audio_is_remote_submix_device) &&
+ policyMix != NULL && policyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
address,
@@ -1831,7 +1819,8 @@
// Automatically disable the remote submix input when output is stopped on a
// re routing mix of type MIX_TYPE_RECORDERS
sp<AudioPolicyMix> policyMix = outputDesc->mPolicyMix.promote();
- if (audio_is_remote_submix_device(outputDesc->devices().types()) &&
+ if (isSingleDeviceType(
+ outputDesc->devices().types(), &audio_is_remote_submix_device) &&
policyMix != NULL &&
policyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
@@ -2491,10 +2480,12 @@
{
// if device is AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, return volume for device selected for this
// stream by the engine.
+ DeviceTypeSet deviceTypes = {device};
if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
- device = mEngine->getOutputDevicesForStream(stream, true /*fromCache*/).types();
+ deviceTypes = mEngine->getOutputDevicesForStream(
+ stream, true /*fromCache*/).types();
}
- return getVolumeIndex(getVolumeCurves(stream), *index, device);
+ return getVolumeIndex(getVolumeCurves(stream), *index, deviceTypes);
}
status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_t &attributes,
@@ -2519,19 +2510,20 @@
return status;
}
- audio_devices_t curSrcDevice;
+ DeviceTypeSet curSrcDevices;
auto curCurvAttrs = curves.getAttributes();
if (!curCurvAttrs.empty() && curCurvAttrs.front() != defaultAttr) {
auto attr = curCurvAttrs.front();
- curSrcDevice = mEngine->getOutputDevicesForAttributes(attr, nullptr, false).types();
+ curSrcDevices = mEngine->getOutputDevicesForAttributes(attr, nullptr, false).types();
} else if (!curves.getStreamTypes().empty()) {
auto stream = curves.getStreamTypes().front();
- curSrcDevice = mEngine->getOutputDevicesForStream(stream, false).types();
+ curSrcDevices = mEngine->getOutputDevicesForStream(stream, false).types();
} else {
ALOGE("%s: Invalid src %d: no valid attributes nor stream",__func__, vs);
return BAD_VALUE;
}
- curSrcDevice = Volume::getDeviceForVolume(curSrcDevice);
+ audio_devices_t curSrcDevice = Volume::getDeviceForVolume(curSrcDevices);
+ resetDeviceTypes(curSrcDevices, curSrcDevice);
// update volume on all outputs and streams matching the following:
// - The requested stream (or a stream matching for volume control) is active on the output
@@ -2543,11 +2535,10 @@
// no specific device volume value exists for currently selected device.
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- audio_devices_t curDevice = desc->devices().types();
+ DeviceTypeSet curDevices = desc->devices().types();
- if (curDevice & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
- curDevice |= AUDIO_DEVICE_OUT_SPEAKER;
- curDevice &= ~AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+ if (curDevices.erase(AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
+ curDevices.insert(AUDIO_DEVICE_OUT_SPEAKER);
}
// Inter / intra volume group priority management: Loop on strategies arranged by priority
@@ -2591,7 +2582,7 @@
if (!applyVolume) {
continue; // next output
}
- status_t volStatus = checkAndSetVolume(curves, vs, index, desc, curDevice,
+ status_t volStatus = checkAndSetVolume(curves, vs, index, desc, curDevices,
(vs == toVolumeSource(AUDIO_STREAM_SYSTEM)?
TOUCH_SOUND_FIXED_DELAY_MS : 0));
if (volStatus != NO_ERROR) {
@@ -2602,12 +2593,14 @@
if (!(desc->isActive(vs) || isInCall())) {
continue;
}
- if ((device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) && ((curDevice & device) == 0)) {
+ if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME &&
+ curDevices.find(device) == curDevices.end()) {
continue;
}
if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
- curSrcDevice |= device;
- applyVolume = (Volume::getDeviceForVolume(curDevice) & curSrcDevice) != 0;
+ curSrcDevices.insert(device);
+ applyVolume = (curSrcDevices.find(
+ Volume::getDeviceForVolume(curDevices)) != curSrcDevices.end());
} else {
applyVolume = !curves.hasVolumeIndexForDevice(curSrcDevice);
}
@@ -2616,7 +2609,7 @@
// delayed volume change for system stream to be removed when the problem is
// handled by system UI
status_t volStatus = checkAndSetVolume(
- curves, vs, index, desc, curDevice,
+ curves, vs, index, desc, curDevices,
((vs == toVolumeSource(AUDIO_STREAM_SYSTEM))?
TOUCH_SOUND_FIXED_DELAY_MS : 0));
if (volStatus != NO_ERROR) {
@@ -2659,22 +2652,23 @@
{
// if device is AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, return volume for device selected for this
// stream by the engine.
+ DeviceTypeSet deviceTypes = {device};
if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
- device = mEngine->getOutputDevicesForAttributes(attr, nullptr, true /*fromCache*/).types();
+ DeviceTypeSet deviceTypes = mEngine->getOutputDevicesForAttributes(
+ attr, nullptr, true /*fromCache*/).types();
}
- return getVolumeIndex(getVolumeCurves(attr), index, device);
+ return getVolumeIndex(getVolumeCurves(attr), index, deviceTypes);
}
status_t AudioPolicyManager::getVolumeIndex(const IVolumeCurves &curves,
int &index,
- audio_devices_t device) const
+ const DeviceTypeSet& deviceTypes) const
{
- if (!audio_is_output_device(device)) {
+ if (isSingleDeviceType(deviceTypes, audio_is_output_device)) {
return BAD_VALUE;
}
- device = Volume::getDeviceForVolume(device);
- index = curves.getVolumeIndex(device);
- ALOGV("%s: device %08x index %d", __FUNCTION__, device, index);
+ index = curves.getVolumeIndex(deviceTypes);
+ ALOGV("%s: device %s index %d", __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), index);
return NO_ERROR;
}
@@ -3438,8 +3432,8 @@
}
// TODO: reconfigure output format and channels here
- ALOGV("createAudioPatch() setting device %08x on output %d",
- devices.types(), outputDesc->mIoHandle);
+ ALOGV("createAudioPatch() setting device %s on output %d",
+ dumpDeviceTypes(devices.types()).c_str(), outputDesc->mIoHandle);
setOutputDevices(outputDesc, devices, true, 0, handle);
index = mAudioPatches.indexOfKey(*handle);
if (index >= 0) {
@@ -3919,12 +3913,14 @@
&selectedDeviceId, &isRequestedDeviceForExclusiveUse,
&secondaryOutputs);
if (output == AUDIO_IO_HANDLE_NONE) {
- ALOGV("%s no output for device %08x", __FUNCTION__, sinkDevices.types());
+ ALOGV("%s no output for device %s",
+ __FUNCTION__, dumpDeviceTypes(sinkDevices.types()).c_str());
return INVALID_OPERATION;
}
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
if (outputDesc->isDuplicated()) {
- ALOGV("%s output for device %08x is duplicated", __FUNCTION__, sinkDevices.types());
+ ALOGV("%s output for device %s is duplicated",
+ __FUNCTION__, dumpDeviceTypes(sinkDevices.types()).c_str());
return INVALID_OPERATION;
}
status_t status = outputDesc->start();
@@ -4033,7 +4029,7 @@
float AudioPolicyManager::getStreamVolumeDB(
audio_stream_type_t stream, int index, audio_devices_t device)
{
- return computeVolume(getVolumeCurves(stream), toVolumeSource(stream), index, device);
+ return computeVolume(getVolumeCurves(stream), toVolumeSource(stream), index, {device});
}
status_t AudioPolicyManager::getSurroundFormats(unsigned int *numSurroundFormats,
@@ -4133,8 +4129,8 @@
sp<SwAudioOutputDescriptor> outputDesc;
bool profileUpdated = false;
- DeviceVector hdmiOutputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(
- AUDIO_DEVICE_OUT_HDMI);
+ DeviceVector hdmiOutputDevices = mAvailableOutputDevices.getDevicesFromType(
+ AUDIO_DEVICE_OUT_HDMI);
for (size_t i = 0; i < hdmiOutputDevices.size(); i++) {
// Simulate reconnection to update enabled surround sound formats.
String8 address = String8(hdmiOutputDevices[i]->address().c_str());
@@ -4155,7 +4151,7 @@
profileUpdated |= (status == NO_ERROR);
}
// FIXME: Why doing this for input HDMI devices if we don't augment their reported formats?
- DeviceVector hdmiInputDevices = mAvailableInputDevices.getDevicesFromTypeMask(
+ DeviceVector hdmiInputDevices = mAvailableInputDevices.getDevicesFromType(
AUDIO_DEVICE_IN_HDMI);
for (size_t i = 0; i < hdmiInputDevices.size(); i++) {
// Simulate reconnection to update enabled surround sound formats.
@@ -4551,7 +4547,7 @@
const sp<SwAudioOutputDescriptor>& outputDesc)
{
mOutputs.add(output, outputDesc);
- applyStreamVolumes(outputDesc, AUDIO_DEVICE_NONE, 0 /* delayMs */, true /* force */);
+ applyStreamVolumes(outputDesc, DeviceTypeSet(), 0 /* delayMs */, true /* force */);
updateMono(output); // update mono status when adding to output list
selectOutputForMusicEffects();
nextAudioPortGeneration();
@@ -4588,7 +4584,7 @@
for (size_t i = 0; i < mOutputs.size(); i++) {
desc = mOutputs.valueAt(i);
if (!desc->isDuplicated() && desc->supportsDevice(device)
- && desc->deviceSupportsEncodedFormats(deviceType)) {
+ && desc->devicesSupportEncodedFormats({deviceType})) {
ALOGV("checkOutputsForDevice(): adding opened output %d on device %s",
mOutputs.keyAt(i), device->toString().c_str());
outputs.add(mOutputs.keyAt(i));
@@ -4753,7 +4749,7 @@
if (!desc->isDuplicated()) {
// exact match on device
if (device_distinguishes_on_address(deviceType) && desc->supportsDevice(device)
- && desc->deviceSupportsEncodedFormats(deviceType)) {
+ && desc->devicesSupportEncodedFormats({deviceType})) {
outputs.add(mOutputs.keyAt(i));
} else if (!mAvailableOutputDevices.containsAtLeastOne(desc->supportedDevices())) {
ALOGV("checkOutputsForDevice(): disconnecting adding output %d",
@@ -5024,7 +5020,7 @@
i, openOutputs.valueAt(i)->isDuplicated(),
openOutputs.valueAt(i)->supportedDevices().toString().c_str());
if (openOutputs.valueAt(i)->supportsAllDevices(devices)
- && openOutputs.valueAt(i)->deviceSupportsEncodedFormats(devices.types())) {
+ && openOutputs.valueAt(i)->devicesSupportEncodedFormats(devices.types())) {
ALOGVV("%s() found output %d", __func__, openOutputs.keyAt(i));
outputs.add(openOutputs.keyAt(i));
}
@@ -5199,9 +5195,8 @@
}
bool isScoConnected =
- ((mAvailableInputDevices.types() & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET &
- ~AUDIO_DEVICE_BIT_IN) != 0) ||
- ((mAvailableOutputDevices.types() & AUDIO_DEVICE_OUT_ALL_SCO) != 0);
+ (mAvailableInputDevices.types().count(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) != 0 ||
+ !Intersection(mAvailableOutputDevices.types(), getAudioDeviceOutAllScoSet()).empty());
// if suspended, restore A2DP output if:
// ((SCO device is NOT connected) ||
@@ -5363,12 +5358,13 @@
}
/*Filter SPEAKER_SAFE out of results, as AudioService doesn't know about it
and doesn't really need to.*/
- DeviceVector speakerSafeDevices = devices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER_SAFE);
+ DeviceVector speakerSafeDevices = devices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER_SAFE);
if (!speakerSafeDevices.isEmpty()) {
- devices.merge(mAvailableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER));
+ devices.merge(mAvailableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER));
devices.remove(speakerSafeDevices);
}
- return devices.types();
+ // FIXME: use DeviceTypeSet when Java layer is ready for it.
+ return deviceTypesToBitMask(devices.types());
}
void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t stream) {
@@ -5428,7 +5424,7 @@
auto ttsVolumeSource = toVolumeSource(AUDIO_STREAM_TTS);
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- setVolumeSourceMute(ttsVolumeSource, mute/*on*/, desc, 0 /*delay*/, AUDIO_DEVICE_NONE);
+ setVolumeSourceMute(ttsVolumeSource, mute/*on*/, desc, 0 /*delay*/, DeviceTypeSet());
const uint32_t latency = desc->latency() * 2;
if (latency > maxLatency) {
maxLatency = latency;
@@ -5744,9 +5740,9 @@
float AudioPolicyManager::computeVolume(IVolumeCurves &curves,
VolumeSource volumeSource,
int index,
- audio_devices_t device)
+ const DeviceTypeSet& deviceTypes)
{
- float volumeDb = curves.volIndexToDb(Volume::getDeviceCategory(device), index);
+ float volumeDb = curves.volIndexToDb(Volume::getDeviceCategory(deviceTypes), index);
// handle the case of accessibility active while a ringtone is playing: if the ringtone is much
// louder than the accessibility prompt, the prompt cannot be heard, thus masking the touch
@@ -5762,7 +5758,7 @@
&& (AUDIO_MODE_RINGTONE == mEngine->getPhoneState()) &&
mOutputs.isActive(ringVolumeSrc, 0)) {
auto &ringCurves = getVolumeCurves(AUDIO_STREAM_RING);
- const float ringVolumeDb = computeVolume(ringCurves, ringVolumeSrc, index, device);
+ const float ringVolumeDb = computeVolume(ringCurves, ringVolumeSrc, index, deviceTypes);
return ringVolumeDb - 4 > volumeDb ? ringVolumeDb - 4 : volumeDb;
}
@@ -5777,9 +5773,9 @@
volumeSource == toVolumeSource(AUDIO_STREAM_DTMF) ||
volumeSource == a11yVolumeSrc)) {
auto &voiceCurves = getVolumeCurves(callVolumeSrc);
- int voiceVolumeIndex = voiceCurves.getVolumeIndex(device);
+ int voiceVolumeIndex = voiceCurves.getVolumeIndex(deviceTypes);
const float maxVoiceVolDb =
- computeVolume(voiceCurves, callVolumeSrc, voiceVolumeIndex, device)
+ computeVolume(voiceCurves, callVolumeSrc, voiceVolumeIndex, deviceTypes)
+ IN_CALL_EARPIECE_HEADROOM_DB;
// FIXME: Workaround for call screening applications until a proper audio mode is defined
// to support this scenario : Exempt the RING stream from the audio cap if the audio was
@@ -5805,9 +5801,10 @@
// speaker is part of the select devices
// - if music is playing, always limit the volume to current music volume,
// with a minimum threshold at -36dB so that notification is always perceived.
- if ((device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
- AUDIO_DEVICE_OUT_USB_HEADSET | AUDIO_DEVICE_OUT_HEARING_AID)) &&
+ if (!Intersection(deviceTypes,
+ {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
+ AUDIO_DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+ AUDIO_DEVICE_OUT_USB_HEADSET, AUDIO_DEVICE_OUT_HEARING_AID}).empty() &&
((volumeSource == alarmVolumeSrc ||
volumeSource == ringVolumeSrc) ||
(volumeSource == toVolumeSource(AUDIO_STREAM_NOTIFICATION)) ||
@@ -5822,31 +5819,33 @@
if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) ||
mLimitRingtoneVolume) {
volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
- audio_devices_t musicDevice =
+ DeviceTypeSet musicDevice =
mEngine->getOutputDevicesForAttributes(attributes_initializer(AUDIO_USAGE_MEDIA),
nullptr, true /*fromCache*/).types();
auto &musicCurves = getVolumeCurves(AUDIO_STREAM_MUSIC);
- float musicVolDb = computeVolume(musicCurves, musicVolumeSrc,
- musicCurves.getVolumeIndex(musicDevice), musicDevice);
+ float musicVolDb = computeVolume(musicCurves,
+ musicVolumeSrc,
+ musicCurves.getVolumeIndex(musicDevice),
+ musicDevice);
float minVolDb = (musicVolDb > SONIFICATION_HEADSET_VOLUME_MIN_DB) ?
musicVolDb : SONIFICATION_HEADSET_VOLUME_MIN_DB;
if (volumeDb > minVolDb) {
volumeDb = minVolDb;
ALOGV("computeVolume limiting volume to %f musicVol %f", minVolDb, musicVolDb);
}
- if (device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES)) {
+ if (!Intersection(deviceTypes, {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES}).empty()) {
// on A2DP, also ensure notification volume is not too low compared to media when
// intended to be played
if ((volumeDb > -96.0f) &&
(musicVolDb - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB > volumeDb)) {
- ALOGV("%s increasing volume for volume source=%d device=0x%X from %f to %f",
- __func__, volumeSource, device, volumeDb,
+ ALOGV("%s increasing volume for volume source=%d device=%s from %f to %f",
+ __func__, volumeSource, dumpDeviceTypes(deviceTypes).c_str(), volumeDb,
musicVolDb - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB);
volumeDb = musicVolDb - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB;
}
}
- } else if ((Volume::getDeviceForVolume(device) != AUDIO_DEVICE_OUT_SPEAKER) ||
+ } else if ((Volume::getDeviceForVolume(deviceTypes) != AUDIO_DEVICE_OUT_SPEAKER) ||
(!(volumeSource == alarmVolumeSrc || volumeSource == ringVolumeSrc))) {
volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
}
@@ -5885,7 +5884,7 @@
VolumeSource volumeSource,
int index,
const sp<AudioOutputDescriptor>& outputDesc,
- audio_devices_t device,
+ DeviceTypeSet deviceTypes,
int delayMs,
bool force)
{
@@ -5911,17 +5910,20 @@
volumeSource, forceUseForComm);
return INVALID_OPERATION;
}
- if (device == AUDIO_DEVICE_NONE) {
- device = outputDesc->devices().types();
+ if (deviceTypes.empty()) {
+ deviceTypes = outputDesc->devices().types();
}
- float volumeDb = computeVolume(curves, volumeSource, index, device);
- if (outputDesc->isFixedVolume(device) ||
+ float volumeDb = computeVolume(curves, volumeSource, index, deviceTypes);
+ if (outputDesc->isFixedVolume(deviceTypes) ||
// Force VoIP volume to max for bluetooth SCO
- ((isVoiceVolSrc || isBtScoVolSrc) && (device & AUDIO_DEVICE_OUT_ALL_SCO) != 0)) {
+
+ ((isVoiceVolSrc || isBtScoVolSrc) &&
+ isSingleDeviceType(deviceTypes, audio_is_bluetooth_out_sco_device))) {
volumeDb = 0.0f;
}
- outputDesc->setVolume(volumeDb, volumeSource, curves.getStreamTypes(), device, delayMs, force);
+ outputDesc->setVolume(
+ volumeDb, volumeSource, curves.getStreamTypes(), deviceTypes, delayMs, force);
if (isVoiceVolSrc || isBtScoVolSrc) {
float voiceVolume;
@@ -5940,15 +5942,16 @@
}
void AudioPolicyManager::applyStreamVolumes(const sp<AudioOutputDescriptor>& outputDesc,
- audio_devices_t device,
- int delayMs,
- bool force)
+ const DeviceTypeSet& deviceTypes,
+ int delayMs,
+ bool force)
{
ALOGVV("applyStreamVolumes() for device %08x", device);
for (const auto &volumeGroup : mEngine->getVolumeGroups()) {
auto &curves = getVolumeCurves(toVolumeSource(volumeGroup));
checkAndSetVolume(curves, toVolumeSource(volumeGroup),
- curves.getVolumeIndex(device), outputDesc, device, delayMs, force);
+ curves.getVolumeIndex(deviceTypes),
+ outputDesc, deviceTypes, delayMs, force);
}
}
@@ -5956,7 +5959,7 @@
bool on,
const sp<AudioOutputDescriptor>& outputDesc,
int delayMs,
- audio_devices_t device)
+ DeviceTypeSet deviceTypes)
{
std::vector<VolumeSource> sourcesToMute;
for (auto attributes: mEngine->getAllAttributesForProductStrategy(strategy)) {
@@ -5968,7 +5971,7 @@
}
}
for (auto source : sourcesToMute) {
- setVolumeSourceMute(source, on, outputDesc, delayMs, device);
+ setVolumeSourceMute(source, on, outputDesc, delayMs, deviceTypes);
}
}
@@ -5977,10 +5980,10 @@
bool on,
const sp<AudioOutputDescriptor>& outputDesc,
int delayMs,
- audio_devices_t device)
+ DeviceTypeSet deviceTypes)
{
- if (device == AUDIO_DEVICE_NONE) {
- device = outputDesc->devices().types();
+ if (deviceTypes.empty()) {
+ deviceTypes = outputDesc->devices().types();
}
auto &curves = getVolumeCurves(volumeSource);
if (on) {
@@ -5989,7 +5992,7 @@
(volumeSource != toVolumeSource(AUDIO_STREAM_ENFORCED_AUDIBLE) ||
(mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) ==
AUDIO_POLICY_FORCE_NONE))) {
- checkAndSetVolume(curves, volumeSource, 0, outputDesc, device, delayMs);
+ checkAndSetVolume(curves, volumeSource, 0, outputDesc, deviceTypes, delayMs);
}
}
// increment mMuteCount after calling checkAndSetVolume() so that volume change is not
@@ -6002,9 +6005,9 @@
}
if (outputDesc->decMuteCount(volumeSource) == 0) {
checkAndSetVolume(curves, volumeSource,
- curves.getVolumeIndex(device),
+ curves.getVolumeIndex(deviceTypes),
outputDesc,
- device,
+ deviceTypes,
delayMs);
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index e17ced8..707e4b0 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -176,7 +176,7 @@
IVolumeCurves &volumeCurves);
status_t getVolumeIndex(const IVolumeCurves &curves, int &index,
- audio_devices_t device) const;
+ const DeviceTypeSet& deviceTypes) const;
// return the strategy corresponding to a given stream type
virtual uint32_t getStrategyForStream(audio_stream_type_t stream)
@@ -422,7 +422,7 @@
virtual float computeVolume(IVolumeCurves &curves,
VolumeSource volumeSource,
int index,
- audio_devices_t device);
+ const DeviceTypeSet& deviceTypes);
// rescale volume index from srcStream within range of dstStream
int rescaleVolumeIndex(int srcIndex,
@@ -432,12 +432,13 @@
virtual status_t checkAndSetVolume(IVolumeCurves &curves,
VolumeSource volumeSource, int index,
const sp<AudioOutputDescriptor>& outputDesc,
- audio_devices_t device,
+ DeviceTypeSet deviceTypes,
int delayMs = 0, bool force = false);
// apply all stream volumes to the specified output and device
void applyStreamVolumes(const sp<AudioOutputDescriptor>& outputDesc,
- audio_devices_t device, int delayMs = 0, bool force = false);
+ const DeviceTypeSet& deviceTypes,
+ int delayMs = 0, bool force = false);
/**
* @brief setStrategyMute Mute or unmute all active clients on the considered output
@@ -452,7 +453,7 @@
bool on,
const sp<AudioOutputDescriptor>& outputDesc,
int delayMs = 0,
- audio_devices_t device = AUDIO_DEVICE_NONE);
+ DeviceTypeSet deviceTypes = DeviceTypeSet());
/**
* @brief setVolumeSourceMute Mute or unmute the volume source on the specified output
@@ -467,7 +468,7 @@
bool on,
const sp<AudioOutputDescriptor>& outputDesc,
int delayMs = 0,
- audio_devices_t device = AUDIO_DEVICE_NONE);
+ DeviceTypeSet deviceTypes = DeviceTypeSet());
audio_mode_t getPhoneState();
@@ -653,10 +654,6 @@
uint32_t updateCallRouting(const DeviceVector &rxDevices, uint32_t delayMs = 0);
sp<AudioPatch> createTelephonyPatch(bool isRx, const sp<DeviceDescriptor> &device,
uint32_t delayMs);
- sp<DeviceDescriptor> findDevice(
- const DeviceVector& devices, audio_devices_t device) const;
- audio_devices_t getModuleDeviceTypes(
- const DeviceVector& devices, const char *moduleId) const;
bool isDeviceOfModule(const sp<DeviceDescriptor>& devDesc, const char *moduleId) const;
status_t startSource(const sp<SwAudioOutputDescriptor>& outputDesc,
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 94642f2..a02178e 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -268,8 +268,12 @@
const std::vector<std::string> &normalDeviceIds) {
mNormalDeviceIdsWithoutSystemCamera.clear();
for (auto &deviceId : normalDeviceIds) {
- if (getSystemCameraKind(String8(deviceId.c_str())) ==
- SystemCameraKind::SYSTEM_ONLY_CAMERA) {
+ SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+ if (getSystemCameraKind(String8(deviceId.c_str()), &deviceKind) != OK) {
+ ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, deviceId.c_str());
+ continue;
+ }
+ if (deviceKind == SystemCameraKind::SYSTEM_ONLY_CAMERA) {
// All system camera ids will necessarily come after public camera
// device ids as per the HAL interface contract.
break;
@@ -280,6 +284,16 @@
mNormalDeviceIdsWithoutSystemCamera.size());
}
+status_t CameraService::getSystemCameraKind(const String8& cameraId, SystemCameraKind *kind) const {
+ auto state = getCameraState(cameraId);
+ if (state != nullptr) {
+ *kind = state->getSystemCameraKind();
+ return OK;
+ }
+ // Hidden physical camera ids won't have CameraState
+ return mCameraProviderManager->getSystemCameraKind(cameraId.c_str(), kind);
+}
+
void CameraService::updateCameraNumAndIds() {
Mutex::Autolock l(mServiceLock);
std::pair<int, int> systemAndNonSystemCameras = mCameraProviderManager->getCameraCount();
@@ -296,10 +310,16 @@
std::string cameraId(id.c_str());
hardware::camera::common::V1_0::CameraResourceCost cost;
status_t res = mCameraProviderManager->getResourceCost(cameraId, &cost);
+ SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
if (res != OK) {
ALOGE("Failed to query device resource cost: %s (%d)", strerror(-res), res);
return;
}
+ res = mCameraProviderManager->getSystemCameraKind(cameraId, &deviceKind);
+ if (res != OK) {
+ ALOGE("Failed to query device kind: %s (%d)", strerror(-res), res);
+ return;
+ }
std::set<String8> conflicting;
for (size_t i = 0; i < cost.conflictingDevices.size(); i++) {
conflicting.emplace(String8(cost.conflictingDevices[i].c_str()));
@@ -308,7 +328,7 @@
{
Mutex::Autolock lock(mCameraStatesLock);
mCameraStates.emplace(id, std::make_shared<CameraState>(id, cost.resourceCost,
- conflicting));
+ conflicting, deviceKind));
}
if (mFlashlight->hasFlashUnit(id)) {
@@ -594,7 +614,12 @@
"characteristics for device %s: %s (%d)", String8(cameraId).string(),
strerror(-res), res);
}
-
+ SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+ if (getSystemCameraKind(String8(cameraId), &deviceKind) != OK) {
+ ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, String8(cameraId).string());
+ return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera kind "
+ "for device %s", String8(cameraId).string());
+ }
int callingPid = CameraThreadState::getCallingPid();
int callingUid = CameraThreadState::getCallingUid();
std::vector<int32_t> tagsRemoved;
@@ -602,7 +627,7 @@
// android.permission.CAMERA is required. If android.permission.SYSTEM_CAMERA was needed,
// it would've already been checked in shouldRejectSystemCameraConnection.
if ((callingPid != getpid()) &&
- (getSystemCameraKind(String8(cameraId)) != SystemCameraKind::SYSTEM_ONLY_CAMERA) &&
+ (deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) &&
!checkPermission(sCameraPermission, callingPid, callingUid)) {
res = cameraInfo->removePermissionEntries(
mCameraProviderManager->getProviderTagIdLocked(String8(cameraId).string()),
@@ -1049,11 +1074,19 @@
return STATUS_ERROR_FMT(ERROR_DISCONNECTED, "No camera device with ID \"%s\" is"
"available", cameraId.string());
}
+ SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+ if (getSystemCameraKind(cameraId, &deviceKind) != OK) {
+ ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, cameraId.string());
+ return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "No camera device with ID \"%s\""
+ "found while trying to query device kind", cameraId.string());
+
+ }
+
// If it's not calling from cameraserver, check the permission if the
// device isn't a system only camera (shouldRejectSystemCameraConnection already checks for
// android.permission.SYSTEM_CAMERA for system only camera devices).
if (callingPid != getpid() &&
- (getSystemCameraKind(cameraId) != SystemCameraKind::SYSTEM_ONLY_CAMERA) &&
+ (deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) &&
!checkPermission(sCameraPermission, clientPid, clientUid)) {
ALOGE("Permission Denial: can't use the camera pid=%d, uid=%d", clientPid, clientUid);
return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
@@ -1407,9 +1440,8 @@
return ret;
}
-bool CameraService::shouldSkipStatusUpdates(const String8& cameraId, bool isVendorListener,
- int clientPid, int clientUid) const {
- SystemCameraKind systemCameraKind = getSystemCameraKind(cameraId);
+bool CameraService::shouldSkipStatusUpdates(SystemCameraKind systemCameraKind,
+ bool isVendorListener, int clientPid, int clientUid) {
// If the client is not a vendor client, don't add listener if
// a) the camera is a publicly hidden secure camera OR
// b) the camera is a system only camera and the client doesn't
@@ -1435,7 +1467,11 @@
int cPid = CameraThreadState::getCallingPid();
int cUid = CameraThreadState::getCallingUid();
- SystemCameraKind systemCameraKind = getSystemCameraKind(cameraId);
+ SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
+ if (getSystemCameraKind(cameraId, &systemCameraKind) != OK) {
+ ALOGE("%s: Invalid camera id %s, ", __FUNCTION__, cameraId.c_str());
+ return true;
+ }
// (1) Cameraserver trying to connect, accept.
if (CameraThreadState::getCallingPid() == getpid()) {
@@ -1926,14 +1962,24 @@
{
Mutex::Autolock lock(mCameraStatesLock);
for (auto& i : mCameraStates) {
- if (shouldSkipStatusUpdates(i.first, isVendorListener, clientPid, clientUid)) {
- ALOGV("Cannot add public listener for hidden system-only %s for pid %d",
- i.first.c_str(), CameraThreadState::getCallingPid());
- continue;
- }
cameraStatuses->emplace_back(i.first, mapToInterface(i.second->getStatus()));
}
}
+ // Remove the camera statuses that should be hidden from the client, we do
+ // this after collecting the states in order to avoid holding
+ // mCameraStatesLock and mInterfaceLock (held in getSystemCameraKind()) at
+ // the same time.
+ cameraStatuses->erase(std::remove_if(cameraStatuses->begin(), cameraStatuses->end(),
+ [this, &isVendorListener, &clientPid, &clientUid](const hardware::CameraStatus& s) {
+ SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+ if (getSystemCameraKind(s.cameraId, &deviceKind) != OK) {
+ ALOGE("%s: Invalid camera id %s, skipping status update",
+ __FUNCTION__, s.cameraId.c_str());
+ return true;
+ }
+ return shouldSkipStatusUpdates(deviceKind, isVendorListener, clientPid,
+ clientUid);}), cameraStatuses->end());
+
/*
* Immediately signal current torch status to this listener only
@@ -3023,8 +3069,9 @@
// ----------------------------------------------------------------------------
CameraService::CameraState::CameraState(const String8& id, int cost,
- const std::set<String8>& conflicting) : mId(id),
- mStatus(StatusInternal::NOT_PRESENT), mCost(cost), mConflicting(conflicting) {}
+ const std::set<String8>& conflicting, SystemCameraKind systemCameraKind) : mId(id),
+ mStatus(StatusInternal::NOT_PRESENT), mCost(cost), mConflicting(conflicting),
+ mSystemCameraKind(systemCameraKind) {}
CameraService::CameraState::~CameraState() {}
@@ -3053,6 +3100,10 @@
return mId;
}
+SystemCameraKind CameraService::CameraState::getSystemCameraKind() const {
+ return mSystemCameraKind;
+}
+
// ----------------------------------------------------------------------------
// ClientEventListener
// ----------------------------------------------------------------------------
@@ -3391,9 +3442,16 @@
return;
}
+ // Avoid calling getSystemCameraKind() with mStatusListenerLock held (b/141756275)
+ SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+ if (getSystemCameraKind(cameraId, &deviceKind) != OK) {
+ ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, cameraId.string());
+ return;
+ }
+
// Update the status for this camera state, then send the onStatusChangedCallbacks to each
// of the listeners with both the mStatusStatus and mStatusListenerLock held
- state->updateStatus(status, cameraId, rejectSourceStates, [this]
+ state->updateStatus(status, cameraId, rejectSourceStates, [this, &deviceKind]
(const String8& cameraId, StatusInternal status) {
if (status != StatusInternal::ENUMERATING) {
@@ -3415,7 +3473,7 @@
Mutex::Autolock lock(mStatusListenerLock);
for (auto& listener : mListenerList) {
- if (shouldSkipStatusUpdates(cameraId, listener->isVendorListener(),
+ if (shouldSkipStatusUpdates(deviceKind, listener->isVendorListener(),
listener->getListenerPid(), listener->getListenerUid())) {
ALOGV("Skipping camera discovery callback for system-only camera %s",
cameraId.c_str());
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 058d57e..8765fbf 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -490,7 +490,8 @@
* Make a new CameraState and set the ID, cost, and conflicting devices using the values
* returned in the HAL's camera_info struct for each device.
*/
- CameraState(const String8& id, int cost, const std::set<String8>& conflicting);
+ CameraState(const String8& id, int cost, const std::set<String8>& conflicting,
+ SystemCameraKind deviceKind);
virtual ~CameraState();
/**
@@ -542,6 +543,11 @@
*/
String8 getId() const;
+ /**
+ * Return the kind (SystemCameraKind) of this camera device.
+ */
+ SystemCameraKind getSystemCameraKind() const;
+
private:
const String8 mId;
StatusInternal mStatus; // protected by mStatusLock
@@ -549,6 +555,7 @@
std::set<String8> mConflicting;
mutable Mutex mStatusLock;
CameraParameters mShimParams;
+ const SystemCameraKind mSystemCameraKind;
}; // class CameraState
// Observer for UID lifecycle enforcing that UIDs in idle
@@ -660,12 +667,14 @@
// Should a device status update be skipped for a particular camera device ? (this can happen
// under various conditions. For example if a camera device is advertised as
// system only or hidden secure camera, amongst possible others.
- bool shouldSkipStatusUpdates(const String8& cameraId, bool isVendorListener, int clientPid,
- int clientUid) const;
+ static bool shouldSkipStatusUpdates(SystemCameraKind systemCameraKind, bool isVendorListener,
+ int clientPid, int clientUid);
- inline SystemCameraKind getSystemCameraKind(const String8& cameraId) const {
- return mCameraProviderManager->getSystemCameraKind(cameraId.c_str());
- }
+ // Gets the kind of camera device (i.e public, hidden secure or system only)
+ // getSystemCameraKind() needs mInterfaceMutex which might lead to deadlocks
+ // if held along with mStatusListenerLock (depending on lock ordering, b/141756275), it is
+ // recommended that we don't call this function with mStatusListenerLock held.
+ status_t getSystemCameraKind(const String8& cameraId, SystemCameraKind *kind) const;
// Update the set of API1Compatible camera devices without including system
// cameras and secure cameras. This is used for hiding system only cameras
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 974026c..608521a 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -110,7 +110,12 @@
int publicCameraCount = 0;
for (auto& provider : mProviders) {
for (auto &id : provider->mUniqueCameraIds) {
- switch(getSystemCameraKindLocked(id)) {
+ SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+ if (getSystemCameraKindLocked(id, &deviceKind) != OK) {
+ ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, id.c_str());
+ continue;
+ }
+ switch(deviceKind) {
case SystemCameraKind::PUBLIC:
publicCameraCount++;
break;
@@ -140,7 +145,12 @@
std::vector<std::string>& publicDeviceIds,
std::vector<std::string>& systemDeviceIds) const {
for (auto &deviceId : deviceIds) {
- if (getSystemCameraKindLocked(deviceId) == SystemCameraKind::SYSTEM_ONLY_CAMERA) {
+ SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+ if (getSystemCameraKindLocked(deviceId, &deviceKind) != OK) {
+ ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, deviceId.c_str());
+ continue;
+ }
+ if (deviceKind == SystemCameraKind::SYSTEM_ONLY_CAMERA) {
systemDeviceIds.push_back(deviceId);
} else {
publicDeviceIds.push_back(deviceId);
@@ -158,9 +168,13 @@
// Secure cameras should not be exposed through camera 1 api
providerDeviceIds.erase(std::remove_if(providerDeviceIds.begin(), providerDeviceIds.end(),
[this](const std::string& s) {
- bool rem = this->getSystemCameraKindLocked(s) ==
- SystemCameraKind::HIDDEN_SECURE_CAMERA;
- return rem;}), providerDeviceIds.end());
+ SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+ if (getSystemCameraKindLocked(s, &deviceKind) != OK) {
+ ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, s.c_str());
+ return true;
+ }
+ return deviceKind == SystemCameraKind::HIDDEN_SECURE_CAMERA;}),
+ providerDeviceIds.end());
// API1 app doesn't handle logical and physical camera devices well. So
// for each camera facing, only take the first id advertised by HAL in
// all [logical, physical1, physical2, ...] id combos, and filter out the rest.
@@ -1089,26 +1103,45 @@
return deviceInfo->mIsLogicalCamera;
}
-SystemCameraKind CameraProviderManager::getSystemCameraKind(const std::string& id) const {
+status_t CameraProviderManager::getSystemCameraKind(const std::string& id,
+ SystemCameraKind *kind) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
- return getSystemCameraKindLocked(id);
+ return getSystemCameraKindLocked(id, kind);
}
-SystemCameraKind CameraProviderManager::getSystemCameraKindLocked(const std::string& id) const {
+status_t CameraProviderManager::getSystemCameraKindLocked(const std::string& id,
+ SystemCameraKind *kind) const {
auto deviceInfo = findDeviceInfoLocked(id);
- if (deviceInfo == nullptr) {
- return SystemCameraKind::PUBLIC;
+ if (deviceInfo != nullptr) {
+ *kind = deviceInfo->mSystemCameraKind;
+ return OK;
}
- return deviceInfo->mSystemCameraKind;
+ // If this is a hidden physical camera, we should return what kind of
+ // camera the enclosing logical camera is.
+ auto isHiddenAndParent = isHiddenPhysicalCameraInternal(id);
+ if (isHiddenAndParent.first) {
+ LOG_ALWAYS_FATAL_IF(id == isHiddenAndParent.second->mId,
+ "%s: hidden physical camera id %s and enclosing logical camera id %s are the same",
+ __FUNCTION__, id.c_str(), isHiddenAndParent.second->mId.c_str());
+ return getSystemCameraKindLocked(isHiddenAndParent.second->mId, kind);
+ }
+ // Neither a hidden physical camera nor a logical camera
+ return NAME_NOT_FOUND;
}
-bool CameraProviderManager::isHiddenPhysicalCamera(const std::string& cameraId) {
+bool CameraProviderManager::isHiddenPhysicalCamera(const std::string& cameraId) const {
+ return isHiddenPhysicalCameraInternal(cameraId).first;
+}
+
+std::pair<bool, CameraProviderManager::ProviderInfo::DeviceInfo *>
+CameraProviderManager::isHiddenPhysicalCameraInternal(const std::string& cameraId) const {
+ auto falseRet = std::make_pair(false, nullptr);
for (auto& provider : mProviders) {
for (auto& deviceInfo : provider->mDevices) {
if (deviceInfo->mId == cameraId) {
// cameraId is found in public camera IDs advertised by the
// provider.
- return false;
+ return falseRet;
}
}
}
@@ -1120,7 +1153,7 @@
if (res != OK) {
ALOGE("%s: Failed to getCameraCharacteristics for id %s", __FUNCTION__,
deviceInfo->mId.c_str());
- return false;
+ return falseRet;
}
std::vector<std::string> physicalIds;
@@ -1132,16 +1165,16 @@
if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_5) {
ALOGE("%s: Wrong deviceVersion %x for hiddenPhysicalCameraId %s",
__FUNCTION__, deviceVersion, cameraId.c_str());
- return false;
+ return falseRet;
} else {
- return true;
+ return std::make_pair(true, deviceInfo.get());
}
}
}
}
}
- return false;
+ return falseRet;
}
status_t CameraProviderManager::addProviderLocked(const std::string& newProvider) {
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index f4cf667..4112711 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -292,8 +292,8 @@
*/
bool isLogicalCamera(const std::string& id, std::vector<std::string>* physicalCameraIds);
- SystemCameraKind getSystemCameraKind(const std::string& id) const;
- bool isHiddenPhysicalCamera(const std::string& cameraId);
+ status_t getSystemCameraKind(const std::string& id, SystemCameraKind *kind) const;
+ bool isHiddenPhysicalCamera(const std::string& cameraId) const;
static const float kDepthARTolerance;
private:
@@ -616,7 +616,8 @@
CameraMetadata* characteristics) const;
void filterLogicalCameraIdsLocked(std::vector<std::string>& deviceIds) const;
- SystemCameraKind getSystemCameraKindLocked(const std::string& id) const;
+ status_t getSystemCameraKindLocked(const std::string& id, SystemCameraKind *kind) const;
+ std::pair<bool, ProviderInfo::DeviceInfo *> isHiddenPhysicalCameraInternal(const std::string& cameraId) const;
void collectDeviceIdsLocked(const std::vector<std::string> deviceIds,
std::vector<std::string>& normalDeviceIds,
diff --git a/services/mediadrm/Android.mk b/services/mediadrm/Android.mk
index d4bb48a..707a2aa 100644
--- a/services/mediadrm/Android.mk
+++ b/services/mediadrm/Android.mk
@@ -26,6 +26,7 @@
LOCAL_SHARED_LIBRARIES:= \
libbinder \
liblog \
+ libmedia \
libmediadrm \
libutils \
libhidlbase \
diff --git a/services/mediaresourcemanager/Android.bp b/services/mediaresourcemanager/Android.bp
index f3339a0..d468406 100644
--- a/services/mediaresourcemanager/Android.bp
+++ b/services/mediaresourcemanager/Android.bp
@@ -23,4 +23,6 @@
"-Wall",
],
+ export_include_dirs: ["."],
+
}
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index bdcd5e4..45eea0f 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -290,6 +290,18 @@
}
}
+void ResourceManagerService::mergeResources(
+ MediaResource& r1, const MediaResource& r2) {
+ if (r1.mType == MediaResource::kDrmSession) {
+ // This means we are using a session. Each session's mValue is initialized to UINT64_MAX.
+ // The oftener a session is used the lower it's mValue. During reclaim the session with
+ // the highest mValue/lowest usage would be closed.
+ r1.mValue -= (r1.mValue == 0 ? 0 : 1);
+ } else {
+ r1.mValue += r2.mValue;
+ }
+}
+
void ResourceManagerService::addResource(
int pid,
int uid,
@@ -309,15 +321,16 @@
ResourceInfo& info = getResourceInfoForEdit(uid, clientId, client, infos);
for (size_t i = 0; i < resources.size(); ++i) {
- const auto resType = std::make_pair(resources[i].mType, resources[i].mSubType);
+ const auto &res = resources[i];
+ const auto resType = std::tuple(res.mType, res.mSubType, res.mId);
if (info.resources.find(resType) == info.resources.end()) {
- onFirstAdded(resources[i], info);
- info.resources[resType] = resources[i];
+ onFirstAdded(res, info);
+ info.resources[resType] = res;
} else {
- info.resources[resType].mValue += resources[i].mValue;
+ mergeResources(info.resources[resType], res);
}
}
- if (info.deathNotifier == nullptr) {
+ if (info.deathNotifier == nullptr && client != nullptr) {
info.deathNotifier = new DeathNotifier(this, pid, clientId);
IInterface::asBinder(client)->linkToDeath(info.deathNotifier);
}
@@ -351,14 +364,17 @@
ResourceInfo &info = infos.editValueAt(index);
for (size_t i = 0; i < resources.size(); ++i) {
- const auto resType = std::make_pair(resources[i].mType, resources[i].mSubType);
+ const auto &res = resources[i];
+ const auto resType = std::tuple(res.mType, res.mSubType, res.mId);
// ignore if we don't have it
if (info.resources.find(resType) != info.resources.end()) {
MediaResource &resource = info.resources[resType];
- if (resource.mValue > resources[i].mValue) {
- resource.mValue -= resources[i].mValue;
+ if (resource.mValue > res.mValue) {
+ resource.mValue -= res.mValue;
} else {
- onLastRemoved(resources[i], info);
+ // drm sessions always take this branch because res.mValue is set
+ // to UINT64_MAX
+ onLastRemoved(res, info);
info.resources.erase(resType);
}
}
@@ -430,6 +446,7 @@
const MediaResource *secureCodec = NULL;
const MediaResource *nonSecureCodec = NULL;
const MediaResource *graphicMemory = NULL;
+ const MediaResource *drmSession = NULL;
for (size_t i = 0; i < resources.size(); ++i) {
MediaResource::Type type = resources[i].mType;
if (resources[i].mType == MediaResource::kSecureCodec) {
@@ -438,6 +455,8 @@
nonSecureCodec = &resources[i];
} else if (type == MediaResource::kGraphicMemory) {
graphicMemory = &resources[i];
+ } else if (type == MediaResource::kDrmSession) {
+ drmSession = &resources[i];
}
}
@@ -461,6 +480,12 @@
}
}
}
+ if (drmSession != NULL) {
+ getClientForResource_l(callingPid, drmSession, &clients);
+ if (clients.size() == 0) {
+ return false;
+ }
+ }
if (clients.size() == 0) {
// if no secure/non-secure codec conflict, run second pass to handle other resources.
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index f086dc3..44d0c28 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -33,7 +33,7 @@
class ServiceLog;
struct ProcessInfoInterface;
-typedef std::map<std::pair<MediaResource::Type, MediaResource::SubType>, MediaResource> ResourceList;
+typedef std::map<std::tuple<MediaResource::Type, MediaResource::SubType, std::vector<uint8_t>>, MediaResource> ResourceList;
struct ResourceInfo {
int64_t clientId;
uid_t uid;
@@ -126,6 +126,9 @@
void onFirstAdded(const MediaResource& res, const ResourceInfo& clientInfo);
void onLastRemoved(const MediaResource& res, const ResourceInfo& clientInfo);
+ // Merge r2 into r1
+ void mergeResources(MediaResource& r1, const MediaResource& r2);
+
mutable Mutex mLock;
sp<ProcessInfoInterface> mProcessInfo;
sp<SystemCallbackInterface> mSystemCB;
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index ae97ec8..9e14151 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -173,8 +173,9 @@
// convert resource1 to ResourceList
ResourceList r1;
for (size_t i = 0; i < resources1.size(); ++i) {
- const auto resType = std::make_pair(resources1[i].mType, resources1[i].mSubType);
- r1[resType] = resources1[i];
+ const auto &res = resources1[i];
+ const auto resType = std::tuple(res.mType, res.mSubType, res.mId);
+ r1[resType] = res;
}
return r1 == resources2;
}