Merge "media: Fix MediaCodesXmlParser Result bug" into qt-dev
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 01efb22..d6db1d4 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -59,6 +59,7 @@
shared_libs: [
"android.hardware.drm@1.0",
"android.hardware.drm@1.1",
+ "android.hardware.drm@1.2",
"libbinder",
"libhidlbase",
"liblog",
@@ -89,6 +90,7 @@
shared_libs: [
"android.hardware.drm@1.0",
"android.hardware.drm@1.1",
+ "android.hardware.drm@1.2",
"libbase",
"libbinder",
"libhidlbase",
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 5888af0..919f4ee 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -40,7 +40,6 @@
#include <mediadrm/DrmSessionManager.h>
using drm::V1_0::KeyedVector;
-using drm::V1_0::KeyStatusType;
using drm::V1_0::KeyRequestType;
using drm::V1_0::KeyType;
using drm::V1_0::KeyValue;
@@ -51,6 +50,7 @@
using drm::V1_1::SecureStopRelease;
using drm::V1_1::SecurityLevel;
using drm::V1_2::KeySetId;
+using drm::V1_2::KeyStatusType;
using ::android::hardware::drm::V1_1::DrmMetricGroup;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_string;
@@ -517,6 +517,17 @@
}
Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus_V1_0>& keyStatusList_V1_0, bool hasNewUsableKey) {
+ std::vector<KeyStatus> keyStatusVec;
+ for (const auto &keyStatus_V1_0 : keyStatusList_V1_0) {
+ keyStatusVec.push_back({keyStatus_V1_0.keyId,
+ static_cast<KeyStatusType>(keyStatus_V1_0.type)});
+ }
+ hidl_vec<KeyStatus> keyStatusList_V1_2(keyStatusVec);
+ return sendKeysChange_1_2(sessionId, keyStatusList_V1_2, hasNewUsableKey);
+}
+
+Return<void> DrmHal::sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
mEventLock.lock();
@@ -546,6 +557,9 @@
case KeyStatusType::STATUSPENDING:
type = DrmPlugin::kKeyStatusType_StatusPending;
break;
+ case KeyStatusType::USABLEINFUTURE:
+ type = DrmPlugin::kKeyStatusType_UsableInFuture;
+ break;
case KeyStatusType::INTERNALERROR:
default:
type = DrmPlugin::kKeyStatusType_InternalError;
diff --git a/drm/libmediadrm/DrmMetrics.cpp b/drm/libmediadrm/DrmMetrics.cpp
index 4fed707..3080802 100644
--- a/drm/libmediadrm/DrmMetrics.cpp
+++ b/drm/libmediadrm/DrmMetrics.cpp
@@ -32,7 +32,7 @@
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::drm::V1_0::EventType;
-using ::android::hardware::drm::V1_0::KeyStatusType;
+using ::android::hardware::drm::V1_2::KeyStatusType;
using ::android::hardware::drm::V1_1::DrmMetricGroup;
using ::android::os::PersistableBundle;
diff --git a/drm/libmediadrm/tests/DrmMetrics_test.cpp b/drm/libmediadrm/tests/DrmMetrics_test.cpp
index 64aa9d0..5c8a1b0 100644
--- a/drm/libmediadrm/tests/DrmMetrics_test.cpp
+++ b/drm/libmediadrm/tests/DrmMetrics_test.cpp
@@ -30,7 +30,7 @@
using ::android::drm_metrics::DrmFrameworkMetrics;
using ::android::hardware::hidl_vec;
using ::android::hardware::drm::V1_0::EventType;
-using ::android::hardware::drm::V1_0::KeyStatusType;
+using ::android::hardware::drm::V1_2::KeyStatusType;
using ::android::hardware::drm::V1_0::Status;
using ::android::hardware::drm::V1_1::DrmMetricGroup;
using ::android::os::PersistableBundle;
diff --git a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
index 8ebb42b..b988ce0 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
@@ -51,16 +51,16 @@
// Build a list of the key IDs
std::vector<const uint8_t*> keyIds;
- if (mimeType == kIsoBmffVideoMimeType ||
- mimeType == kIsoBmffAudioMimeType ||
- mimeType == kCencInitDataFormat) {
+ if (mimeType == kIsoBmffVideoMimeType.c_str() ||
+ mimeType == kIsoBmffAudioMimeType.c_str() ||
+ mimeType == kCencInitDataFormat.c_str()) {
Status res = parsePssh(initData, &keyIds);
if (res != Status::OK) {
return res;
}
- } else if (mimeType == kWebmVideoMimeType ||
- mimeType == kWebmAudioMimeType ||
- mimeType == kWebmInitDataFormat) {
+ } else if (mimeType == kWebmVideoMimeType.c_str() ||
+ mimeType == kWebmAudioMimeType.c_str() ||
+ mimeType == kWebmInitDataFormat.c_str()) {
// WebM "init data" is just a single key ID
if (initData.size() != kKeyIdSize) {
return Status::ERROR_DRM_CANNOT_HANDLE;
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
index ba5fa65..f294d4d 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
@@ -62,6 +62,7 @@
typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1;
typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
+typedef drm::V1_2::KeyStatus KeyStatus_V1_2;
typedef drm::V1_2::Status Status_V1_2;
typedef drm::V1_2::HdcpLevel HdcpLevel_V1_2;
@@ -335,6 +336,15 @@
return Void();
}
+ Return<void> sendKeysChange_1_2(
+ const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus_V1_2>& keyStatusList, bool hasNewUsableKey) {
+ if (mListenerV1_2 != NULL) {
+ mListenerV1_2->sendKeysChange_1_2(sessionId, keyStatusList, hasNewUsableKey);
+ }
+ return Void();
+ }
+
Return<void> sendSessionLostState(
const hidl_vec<uint8_t>& sessionId) {
if (mListenerV1_2 != NULL) {
diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp
index b73f0c8..63fe36b 100644
--- a/media/codec2/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hidl/1.0/utils/Android.bp
@@ -48,9 +48,6 @@
cc_library {
name: "libcodec2_hidl@1.0",
vendor_available: true,
- vndk: {
- enabled: true,
- },
defaults: ["hidl_defaults"],
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index 198bd72..ca69810 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -14,9 +14,6 @@
cc_library_shared {
name: "libcodec2_vndk",
vendor_available: true,
- vndk: {
- enabled: true,
- },
srcs: [
"C2AllocatorIon.cpp",
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index d56abaa..8c8e6d1 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -426,10 +426,8 @@
}
ALOGV("extent_count %d", extent_count);
- if (extent_count > 1 && (offset_size == 0 || length_size == 0)) {
- // if the item is dividec into more than one extents, offset and
- // length must be present.
- return ERROR_MALFORMED;
+ if (extent_count > 1) {
+ return ERROR_UNSUPPORTED;
}
offset += 2;
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index e1bfb62..b4fd811 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -45,6 +45,7 @@
#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/foundation/avc_utils.h>
#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/OpusHeader.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaDataBase.h>
@@ -1735,15 +1736,21 @@
AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sample_rate);
if (chunk_type == FOURCC("Opus")) {
- uint8_t opusInfo[19];
+ uint8_t opusInfo[AOPUS_OPUSHEAD_MAXSIZE];
data_offset += sizeof(buffer);
+ size_t opusInfoSize = chunk_data_size - sizeof(buffer);
+
+ if (opusInfoSize < AOPUS_OPUSHEAD_MINSIZE ||
+ opusInfoSize > AOPUS_OPUSHEAD_MAXSIZE) {
+ return ERROR_MALFORMED;
+ }
// Read Opus Header
if (mDataSource->readAt(
- data_offset, opusInfo, sizeof(opusInfo)) < (ssize_t)sizeof(opusInfo)) {
+ data_offset, opusInfo, opusInfoSize) < opusInfoSize) {
return ERROR_IO;
}
- // OpusHeader must start with this magic sequence
+ // OpusHeader must start with this magic sequence, overwrite first 8 bytes
// http://wiki.xiph.org/OggOpus#ID_Header
strncpy((char *)opusInfo, "OpusHead", 8);
@@ -1760,17 +1767,18 @@
memcpy(&opusInfo[opusOffset + 2], &sample_rate, sizeof(sample_rate));
memcpy(&opusInfo[opusOffset + 6], &out_gain, sizeof(out_gain));
- int64_t codecDelay = 6500000;
- int64_t seekPreRollNs = 80000000; // Fixed 80 msec
+ static const int64_t kSeekPreRollNs = 80000000; // Fixed 80 msec
+ static const int32_t kOpusSampleRate = 48000;
+ int64_t codecDelay = pre_skip * 1000000000ll / kOpusSampleRate;
AMediaFormat_setBuffer(mLastTrack->meta,
AMEDIAFORMAT_KEY_CSD_0, opusInfo, sizeof(opusInfo));
AMediaFormat_setBuffer(mLastTrack->meta,
AMEDIAFORMAT_KEY_CSD_1, &codecDelay, sizeof(codecDelay));
AMediaFormat_setBuffer(mLastTrack->meta,
- AMEDIAFORMAT_KEY_CSD_2, &seekPreRollNs, sizeof(seekPreRollNs));
+ AMEDIAFORMAT_KEY_CSD_2, &kSeekPreRollNs, sizeof(kSeekPreRollNs));
- data_offset += sizeof(opusInfo);
+ data_offset += opusInfoSize;
*offset = data_offset;
CHECK_EQ(*offset, stop_offset);
}
@@ -4297,6 +4305,77 @@
return ERROR_MALFORMED;
}
+ if (objectTypeIndication == 0xdd) {
+ // vorbis audio
+ if (csd[0] != 0x02) {
+ return ERROR_MALFORMED;
+ }
+
+ // codecInfo starts with two lengths, len1 and len2, that are
+ // "Xiph-style-lacing encoded"..
+
+ size_t offset = 1;
+ size_t len1 = 0;
+ while (offset < csd_size && csd[offset] == 0xff) {
+ if (__builtin_add_overflow(len1, 0xff, &len1)) {
+ return ERROR_MALFORMED;
+ }
+ ++offset;
+ }
+ if (offset >= csd_size) {
+ return ERROR_MALFORMED;
+ }
+ if (__builtin_add_overflow(len1, csd[offset], &len1)) {
+ return ERROR_MALFORMED;
+ }
+ ++offset;
+ if (len1 == 0) {
+ return ERROR_MALFORMED;
+ }
+
+ size_t len2 = 0;
+ while (offset < csd_size && csd[offset] == 0xff) {
+ if (__builtin_add_overflow(len2, 0xff, &len2)) {
+ return ERROR_MALFORMED;
+ }
+ ++offset;
+ }
+ if (offset >= csd_size) {
+ return ERROR_MALFORMED;
+ }
+ if (__builtin_add_overflow(len2, csd[offset], &len2)) {
+ return ERROR_MALFORMED;
+ }
+ ++offset;
+ if (len2 == 0) {
+ return ERROR_MALFORMED;
+ }
+ if (offset >= csd_size || csd[offset] != 0x01) {
+ return ERROR_MALFORMED;
+ }
+ // formerly kKeyVorbisInfo
+ AMediaFormat_setBuffer(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_CSD_0, &csd[offset], len1);
+
+ if (__builtin_add_overflow(offset, len1, &offset) ||
+ offset >= csd_size || csd[offset] != 0x03) {
+ return ERROR_MALFORMED;
+ }
+
+ if (__builtin_add_overflow(offset, len2, &offset) ||
+ offset >= csd_size || csd[offset] != 0x05) {
+ return ERROR_MALFORMED;
+ }
+
+ // formerly kKeyVorbisBooks
+ AMediaFormat_setBuffer(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_CSD_1, &csd[offset], csd_size - offset);
+ AMediaFormat_setString(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_VORBIS);
+
+ return OK;
+ }
+
static uint32_t kSamplingRate[] = {
96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
16000, 12000, 11025, 8000, 7350
diff --git a/media/libaudioclient/RecordingActivityTracker.cpp b/media/libaudioclient/RecordingActivityTracker.cpp
index bd10895..42d4361 100644
--- a/media/libaudioclient/RecordingActivityTracker.cpp
+++ b/media/libaudioclient/RecordingActivityTracker.cpp
@@ -36,6 +36,9 @@
RecordingActivityTracker::~RecordingActivityTracker()
{
+ if (mRIId != RECORD_RIID_INVALID && mAudioManager) {
+ mAudioManager->releaseRecorder(mRIId);
+ }
}
audio_unique_id_t RecordingActivityTracker::getRiid()
diff --git a/media/libmedia/include/media/DrmHal.h b/media/libmedia/include/media/DrmHal.h
index a630bfd..bdf1b30 100644
--- a/media/libmedia/include/media/DrmHal.h
+++ b/media/libmedia/include/media/DrmHal.h
@@ -37,14 +37,15 @@
using drm::V1_0::IDrmFactory;
using drm::V1_0::IDrmPlugin;
using drm::V1_0::IDrmPluginListener;
-using drm::V1_0::KeyStatus;
using drm::V1_1::SecurityLevel;
+using drm::V1_2::KeyStatus;
using drm::V1_2::OfflineLicenseState;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
+typedef drm::V1_0::KeyStatus KeyStatus_V1_0;
namespace android {
@@ -56,7 +57,7 @@
}
struct DrmHal : public BnDrm,
- public IBinder::DeathRecipient,
+ public IBinder::DeathRecipient,
public IDrmPluginListener_V1_2 {
DrmHal();
virtual ~DrmHal();
@@ -180,6 +181,9 @@
int64_t expiryTimeInMS);
Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus_V1_0>& keyStatusList, bool hasNewUsableKey);
+
+ Return<void> sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey);
Return<void> sendSessionLostState(const hidl_vec<uint8_t>& sessionId);
diff --git a/media/libmedia/include/media/DrmMetrics.h b/media/libmedia/include/media/DrmMetrics.h
index 261998f..6f132bf 100644
--- a/media/libmedia/include/media/DrmMetrics.h
+++ b/media/libmedia/include/media/DrmMetrics.h
@@ -21,6 +21,7 @@
#include <android/hardware/drm/1.0/types.h>
#include <android/hardware/drm/1.1/types.h>
+#include <android/hardware/drm/1.2/types.h>
#include <binder/PersistableBundle.h>
#include <media/CounterMetric.h>
#include <media/EventMetric.h>
@@ -50,7 +51,7 @@
CounterMetric<status_t> mProvideProvisionResponseCounter;
// Count of key status events broken out by status type.
- CounterMetric<::android::hardware::drm::V1_0::KeyStatusType>
+ CounterMetric<::android::hardware::drm::V1_2::KeyStatusType>
mKeyStatusChangeCounter;
// Count of events broken out by event type
CounterMetric<::android::hardware::drm::V1_0::EventType> mEventCounter;
diff --git a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
index b1e5fbf..9783e9b 100644
--- a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
+++ b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
@@ -654,7 +654,7 @@
nextSection = SECTION_ENCODERS;
} else if (strEq(name, "Settings")) {
nextSection = SECTION_SETTINGS;
- } else if (strEq(name, "MediaCodecs")) {
+ } else if (strEq(name, "MediaCodecs") || strEq(name, "Included")) {
return;
} else {
break;
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 7d1c88b..a3cabd8 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -74,6 +74,7 @@
"android.hardware.graphics.bufferqueue@1.0",
"android.hidl.token@1.0-utils",
"libandroid_runtime_lazy",
+ "libbase",
"libbinder",
"libmedia",
"libmedia_omx",
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index 2deb1a4..85dbffe 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "NdkMediaDrm"
#include <inttypes.h>
+#include <unistd.h>
#include <media/NdkMediaDrm.h>
@@ -26,6 +27,8 @@
#include <utils/StrongPointer.h>
#include <gui/Surface.h>
+#include <android-base/properties.h>
+#include <binder/PermissionController.h>
#include <media/IDrm.h>
#include <media/IDrmClient.h>
#include <media/stagefright/MediaErrors.h>
@@ -231,6 +234,39 @@
return result;
}
+static bool ShouldGetAppPackageName(void) {
+ // Check what this device's first API level was.
+ int32_t firstApiLevel = android::base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
+ if (firstApiLevel == 0) {
+ // First API Level is 0 on factory ROMs, but we can assume the current SDK
+ // version is the first if it's a factory ROM.
+ firstApiLevel = android::base::GetIntProperty<int32_t>("ro.build.version.sdk", 0);
+ }
+ return firstApiLevel >= 29; // Android Q
+}
+
+static status_t GetAppPackageName(String8 *packageName) {
+ sp<IServiceManager> serviceManager = defaultServiceManager();
+ sp<IBinder> binder = serviceManager->getService(String16("permission"));
+
+ sp<IPermissionController> permissionContol = interface_cast<IPermissionController>(binder);
+ if (permissionContol == NULL) {
+ ALOGE("Failed to get permission service");
+ return UNKNOWN_ERROR;
+ }
+
+ Vector<String16> packages;
+ permissionContol->getPackagesForUid(getuid(), packages);
+
+ if (packages.isEmpty()) {
+ ALOGE("Unable to get package name for current UID");
+ return UNKNOWN_ERROR;
+ }
+
+ *packageName = String8(packages[0]);
+ return OK;
+}
+
static sp<IDrm> CreateDrm() {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("media.drm"));
@@ -255,8 +291,16 @@
return NULL;
}
- String8 nullPackageName;
- status_t err = drm->createPlugin(uuid, nullPackageName);
+ String8 packageName;
+ if (ShouldGetAppPackageName()) {
+ status_t err = GetAppPackageName(&packageName);
+
+ if (err != OK) {
+ return NULL;
+ }
+ }
+
+ status_t err = drm->createPlugin(uuid, packageName);
if (err != OK) {
return NULL;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 5e5ea11..66466b2 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1900,12 +1900,16 @@
input.opPackageName,
&input.config,
output.flags, &output.selectedDeviceId, &portId);
+ if (lStatus != NO_ERROR) {
+ ALOGE("createRecord() getInputForAttr return error %d", lStatus);
+ goto Exit;
+ }
{
Mutex::Autolock _l(mLock);
RecordThread *thread = checkRecordThread_l(output.inputId);
if (thread == NULL) {
- ALOGE("createRecord() checkRecordThread_l failed");
+ ALOGE("createRecord() checkRecordThread_l failed, input handle %d", output.inputId);
lStatus = BAD_VALUE;
goto Exit;
}
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index bb97f8d..7008cee 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -26,7 +26,7 @@
bool hasOpPlayAudio() const;
static sp<OpPlayAudioMonitor> createIfNeeded(
- uid_t uid, audio_usage_t usage, int id, audio_stream_type_t streamType);
+ uid_t uid, const audio_attributes_t& attr, int id, audio_stream_type_t streamType);
private:
OpPlayAudioMonitor(uid_t uid, audio_usage_t usage, int id);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index e1f00c1..b0817ed 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -387,18 +387,24 @@
// static
sp<AudioFlinger::PlaybackThread::OpPlayAudioMonitor>
AudioFlinger::PlaybackThread::OpPlayAudioMonitor::createIfNeeded(
- uid_t uid, audio_usage_t usage, int id, audio_stream_type_t streamType)
+ uid_t uid, const audio_attributes_t& attr, int id, audio_stream_type_t streamType)
{
if (isAudioServerOrRootUid(uid)) {
- ALOGD("OpPlayAudio: not muting track:%d usage:%d root or audioserver", id, usage);
+ ALOGD("OpPlayAudio: not muting track:%d usage:%d root or audioserver", id, attr.usage);
return nullptr;
}
// stream type has been filtered by audio policy to indicate whether it can be muted
if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
- ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, usage);
+ ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
return nullptr;
}
- return new OpPlayAudioMonitor(uid, usage, id);
+ if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
+ == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
+ ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
+ id, attr.flags);
+ return nullptr;
+ }
+ return new OpPlayAudioMonitor(uid, attr.usage, id);
}
AudioFlinger::PlaybackThread::OpPlayAudioMonitor::OpPlayAudioMonitor(
@@ -508,7 +514,7 @@
mPresentationCompleteFrames(0),
mFrameMap(16 /* sink-frame-to-track-frame map memory */),
mVolumeHandler(new media::VolumeHandler(sampleRate)),
- mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(uid, attr.usage, id(), streamType)),
+ mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(uid, attr, id(), streamType)),
// mSinkTimestamp
mFastIndex(-1),
mCachedVolume(1.0),
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 2dc7cad..6dc5eb8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1991,16 +1991,25 @@
strncmp(attributes.tags, "addr=", strlen("addr=")) == 0) {
status = mPolicyMixes.getInputMixForAttr(attributes, &policyMix);
if (status != NO_ERROR) {
+ ALOGW("%s could not find input mix for attr %s",
+ __func__, toString(attributes).c_str());
goto error;
}
+ device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ String8(attr->tags + strlen("addr=")),
+ AUDIO_FORMAT_DEFAULT);
+ if (device == nullptr) {
+ ALOGW("%s could not find device for source %d, tags %s",
+ __func__, attributes.source, attributes.tags);
+ status = BAD_VALUE;
+ goto error;
+ }
+
if (is_mix_loopback_render(policyMix->mRouteFlags)) {
*inputType = API_INPUT_MIX_PUBLIC_CAPTURE_PLAYBACK;
} else {
*inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
}
- device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- String8(attr->tags + strlen("addr=")),
- AUDIO_FORMAT_DEFAULT);
} else {
if (explicitRoutingDevice != nullptr) {
device = explicitRoutingDevice;
@@ -2042,7 +2051,7 @@
device->getId() : AUDIO_PORT_HANDLE_NONE;
isSoundTrigger = attributes.source == AUDIO_SOURCE_HOTWORD &&
- mSoundTriggerSessions.indexOfKey(session) > 0;
+ mSoundTriggerSessions.indexOfKey(session) >= 0;
*portId = AudioPort::getNextUniqueId();
clientDesc = new RecordClientDescriptor(*portId, riid, uid, session, attributes, *config,
@@ -2867,14 +2876,12 @@
rSubmixModule->addInputProfile(address, &inputConfig,
AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
- if (mix.mMixType == MIX_TYPE_PLAYERS) {
- setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address.string(), "remote-submix", AUDIO_FORMAT_DEFAULT);
- } else {
- setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address.string(), "remote-submix", AUDIO_FORMAT_DEFAULT);
+ if ((res = setDeviceConnectionStateInt(mix.mDeviceType,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ address.string(), "remote-submix", AUDIO_FORMAT_DEFAULT)) != NO_ERROR) {
+ ALOGE("Failed to set remote submix device available, type %u, address %s",
+ mix.mDeviceType, address.string());
+ break;
}
} else if ((mix.mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
String8 address = mix.mDeviceAddress;
@@ -5685,7 +5692,16 @@
const float maxVoiceVolDb =
computeVolume(voiceCurves, callVolumeSrc, voiceVolumeIndex, device)
+ IN_CALL_EARPIECE_HEADROOM_DB;
- if (volumeDb > maxVoiceVolDb) {
+ // 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
+ // programmatically muted.
+ // VOICE_CALL stream has minVolumeIndex > 0 : Users cannot set the volume of voice calls to
+ // 0. We don't want to cap volume when the system has programmatically muted the voice call
+ // stream. See setVolumeCurveIndex() for more information.
+ bool exemptFromCapping = (volumeSource == ringVolumeSrc) && (voiceVolumeIndex == 0);
+ ALOGV_IF(exemptFromCapping, "%s volume source %d at vol=%f not capped", __func__,
+ volumeSource, volumeDb);
+ if ((volumeDb > maxVoiceVolDb) && !exemptFromCapping) {
ALOGV("%s volume source %d at vol=%f overriden by volume group %d at vol=%f", __func__,
volumeSource, volumeDb, callVolumeSrc, maxVoiceVolDb);
volumeDb = maxVoiceVolDb;
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 5389c08..e3c72ae 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -411,19 +411,19 @@
// OR The client is the assistant
// AND an accessibility service is on TOP
// AND the source is VOICE_RECOGNITION or HOTWORD
-// OR uses VOICE_RECOGNITION AND is on TOP OR latest started
+// OR uses VOICE_RECOGNITION AND is on TOP
// OR uses HOTWORD
// AND there is no active privacy sensitive capture or call
// OR client has CAPTURE_AUDIO_OUTPUT privileged permission
// OR The client is an accessibility service
-// AND is on TOP OR latest started
+// AND is on TOP
// AND the source is VOICE_RECOGNITION or HOTWORD
// OR the client source is virtual (remote submix, call audio TX or RX...)
-// OR Any other client
+// OR Any client
// AND The assistant is not on TOP
+// AND is on TOP or latest started
// AND there is no active privacy sensitive capture or call
// OR client has CAPTURE_AUDIO_OUTPUT privileged permission
-//TODO: mamanage pre processing effects according to use case priority
sp<AudioRecordClient> topActive;
sp<AudioRecordClient> latestActive;
@@ -505,9 +505,11 @@
// By default allow capture if:
// The assistant is not on TOP
+ // AND is on TOP or latest started
// AND there is no active privacy sensitive capture or call
// OR client has CAPTURE_AUDIO_OUTPUT privileged permission
bool allowCapture = !isAssistantOnTop
+ && ((isTopOrLatestActive && !isLatestSensitive) || isLatestSensitive)
&& !(isSensitiveActive && !(isLatestSensitive || current->canCaptureOutput))
&& !(isInCall && !current->canCaptureOutput);
@@ -518,7 +520,7 @@
// For assistant allow capture if:
// An accessibility service is on TOP
// AND the source is VOICE_RECOGNITION or HOTWORD
- // OR is on TOP OR latest started AND uses VOICE_RECOGNITION
+ // OR is on TOP AND uses VOICE_RECOGNITION
// OR uses HOTWORD
// AND there is no active privacy sensitive capture or call
// OR client has CAPTURE_AUDIO_OUTPUT privileged permission
@@ -527,7 +529,7 @@
allowCapture = true;
}
} else {
- if (((isTopOrLatestActive && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
+ if (((isAssistantOnTop && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
source == AUDIO_SOURCE_HOTWORD) &&
(!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
allowCapture = true;
@@ -535,9 +537,9 @@
}
} else if (mUidPolicy->isA11yUid(current->uid)) {
// For accessibility service allow capture if:
- // Is on TOP OR latest started
+ // Is on TOP
// AND the source is VOICE_RECOGNITION or HOTWORD
- if (isTopOrLatestActive &&
+ if (isA11yOnTop &&
(source == AUDIO_SOURCE_VOICE_RECOGNITION || source == AUDIO_SOURCE_HOTWORD)) {
allowCapture = true;
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index fc6d6be..a87ebdf 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -117,6 +117,11 @@
static const String16 sManageCameraPermission("android.permission.MANAGE_CAMERA");
+// Matches with PERCEPTIBLE_APP_ADJ in ProcessList.java
+static constexpr int32_t kVendorClientScore = 200;
+// Matches with PROCESS_STATE_PERSISTENT_UI in ActivityManager.java
+static constexpr int32_t kVendorClientState = 1;
+
Mutex CameraService::sProxyMutex;
sp<hardware::ICameraServiceProxy> CameraService::sCameraServiceProxy;
@@ -1120,7 +1125,8 @@
std::map<int,resource_policy::ClientPriority> pidToPriorityMap;
for (size_t i = 0; i < ownerPids.size() - 1; i++) {
pidToPriorityMap.emplace(ownerPids[i],
- resource_policy::ClientPriority(priorityScores[i], states[i]));
+ resource_policy::ClientPriority(priorityScores[i], states[i],
+ /* isVendorClient won't get copied over*/ false));
}
mActiveClientManager.updatePriorities(pidToPriorityMap);
@@ -2980,8 +2986,12 @@
const std::set<String8>& conflictingKeys, int32_t score, int32_t ownerId,
int32_t state) {
+ bool isVendorClient = hardware::IPCThreadState::self()->isServingCall();
+ int32_t score_adj = isVendorClient ? kVendorClientScore : score;
+ int32_t state_adj = isVendorClient ? kVendorClientState: state;
+
return std::make_shared<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>(
- key, value, cost, conflictingKeys, score, ownerId, state);
+ key, value, cost, conflictingKeys, score_adj, ownerId, state_adj, isVendorClient);
}
CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h
index d7135f1..ec6f01c 100644
--- a/services/camera/libcameraservice/utils/ClientManager.h
+++ b/services/camera/libcameraservice/utils/ClientManager.h
@@ -33,12 +33,38 @@
class ClientPriority {
public:
- ClientPriority(int32_t score, int32_t state) :
- mScore(score), mState(state) {}
+ /**
+ * Choosing to set mIsVendorClient through a parameter instead of calling
+ * hardware::IPCThreadState::self()->isServingCall() to protect against the
+ * case where the construction is offloaded to another thread which isn't a
+ * hwbinder thread.
+ */
+ ClientPriority(int32_t score, int32_t state, bool isVendorClient) :
+ mScore(score), mState(state), mIsVendorClient(isVendorClient) { }
int32_t getScore() const { return mScore; }
int32_t getState() const { return mState; }
+ void setScore(int32_t score) {
+ // For vendor clients, the score is set once and for all during
+ // construction. Otherwise, it can get reset each time cameraserver
+ // queries ActivityManagerService for oom_adj scores / states .
+ if (!mIsVendorClient) {
+ mScore = score;
+ }
+ }
+
+ void setState(int32_t state) {
+ // For vendor clients, the score is set once and for all during
+ // construction. Otherwise, it can get reset each time cameraserver
+ // queries ActivityManagerService for oom_adj scores / states
+ // (ActivityManagerService returns a vendor process' state as
+ // PROCESS_STATE_NONEXISTENT.
+ if (!mIsVendorClient) {
+ mState = state;
+ }
+ }
+
bool operator==(const ClientPriority& rhs) const {
return (this->mScore == rhs.mScore) && (this->mState == rhs.mState);
}
@@ -66,6 +92,7 @@
private:
int32_t mScore;
int32_t mState;
+ bool mIsVendorClient = false;
};
// --------------------------------------------------------------------------------
@@ -82,9 +109,10 @@
class ClientDescriptor final {
public:
ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
- const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state);
+ const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
+ bool isVendorClient);
ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost, std::set<KEY>&& conflictingKeys,
- int32_t score, int32_t ownerId, int32_t state);
+ int32_t score, int32_t ownerId, int32_t state, bool isVendorClient);
~ClientDescriptor();
@@ -148,17 +176,19 @@
template<class KEY, class VALUE>
ClientDescriptor<KEY, VALUE>::ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
- const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state) :
+ const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
+ bool isVendorClient) :
mKey{key}, mValue{value}, mCost{cost}, mConflicting{conflictingKeys},
- mPriority(score, state),
+ mPriority(score, state, isVendorClient),
mOwnerId{ownerId} {}
template<class KEY, class VALUE>
ClientDescriptor<KEY, VALUE>::ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost,
- std::set<KEY>&& conflictingKeys, int32_t score, int32_t ownerId, int32_t state) :
+ std::set<KEY>&& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
+ bool isVendorClient) :
mKey{std::forward<KEY>(key)}, mValue{std::forward<VALUE>(value)}, mCost{cost},
mConflicting{std::forward<std::set<KEY>>(conflictingKeys)},
- mPriority(score, state), mOwnerId{ownerId} {}
+ mPriority(score, state, isVendorClient), mOwnerId{ownerId} {}
template<class KEY, class VALUE>
ClientDescriptor<KEY, VALUE>::~ClientDescriptor() {}
@@ -204,7 +234,13 @@
template<class KEY, class VALUE>
void ClientDescriptor<KEY, VALUE>::setPriority(const ClientPriority& priority) {
- mPriority = priority;
+ // We don't use the usual copy constructor here since we want to remember
+ // whether a client is a vendor client or not. This could have been wiped
+ // off in the incoming priority argument since an AIDL thread might have
+ // called hardware::IPCThreadState::self()->isServingCall() after refreshing
+ // priorities for old clients through ProcessInfoService::getProcessStatesScoresFromPids().
+ mPriority.setScore(priority.getScore());
+ mPriority.setState(priority.getState());
}
// --------------------------------------------------------------------------------
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index 473e21c..ecd437b 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -22,6 +22,7 @@
libstagefright_soft_vorbisdec \
libstagefright_soft_vpxdec \
libstagefright_soft_vpxenc \
+ libstagefright_softomx_plugin \
# service executable
include $(CLEAR_VARS)