Merge "Camera: Support new provider callback version in camera service"
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
index f164f28..3ecf6d5 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
@@ -136,6 +136,8 @@
return Void();
}
+ base = static_cast<uint8_t *>(static_cast<void *>(destBase->getPointer()));
+
if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
_hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "invalid buffer size");
return Void();
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index 942ea7d..546eb3e 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -829,6 +829,12 @@
// and the drm service. The clearkey implementation consists of:
// count - number of secure stops
// list of fixed length secure stops
+ size_t countBufferSize = sizeof(uint32_t);
+ if (input.size() < countBufferSize) {
+ // SafetyNet logging
+ android_errorWriteLog(0x534e4554, "144766455");
+ return Status::BAD_VALUE;
+ }
uint32_t count = 0;
sscanf(reinterpret_cast<char*>(input.data()), "%04" PRIu32, &count);
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index f814cba..2f43b22 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -1021,10 +1021,26 @@
// Stream Control
// ============================================================
+#if __ANDROID_API__ >= 30
/**
- * Free the resources associated with a stream created by AAudioStreamBuilder_openStream()
+ * Free the audio resources associated with a stream created by
+ * AAudioStreamBuilder_openStream().
+ * AAudioStream_close() should be called at some point after calling
+ * this function.
*
- * Available since API level 26.
+ * After this call, the stream will be in {@link #AAUDIO_STREAM_STATE_CLOSING}
+ *
+ * @param stream reference provided by AAudioStreamBuilder_openStream()
+ * @return {@link #AAUDIO_OK} or a negative error.
+ */
+AAUDIO_API aaudio_result_t AAudioStream_release(AAudioStream* stream) __INTRODUCED_IN(30);
+#endif // __ANDROID_API__
+
+/**
+ * Delete the internal data structures associated with the stream created
+ * by AAudioStreamBuilder_openStream().
+ *
+ * If AAudioStream_release() has not been called then it will be called automatically.
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
* @return {@link #AAUDIO_OK} or a negative error.
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index bfad254..b6548e6 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -258,18 +258,17 @@
return result;
error:
- close();
+ releaseCloseFinal();
return result;
}
// This must be called under mStreamLock.
-aaudio_result_t AudioStreamInternal::close() {
+aaudio_result_t AudioStreamInternal::release_l() {
aaudio_result_t result = AAUDIO_OK;
ALOGV("%s(): mServiceStreamHandle = 0x%08X", __func__, mServiceStreamHandle);
if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) {
- // Don't close a stream while it is running.
aaudio_stream_state_t currentState = getState();
- // Don't close a stream while it is running. Stop it first.
+ // Don't release a stream while it is running. Stop it first.
// If DISCONNECTED then we should still try to stop in case the
// error callback is still running.
if (isActive() || currentState == AAUDIO_STREAM_STATE_DISCONNECTED) {
@@ -282,10 +281,8 @@
mServiceInterface.closeStream(serviceStreamHandle);
delete[] mCallbackBuffer;
mCallbackBuffer = nullptr;
-
- setState(AAUDIO_STREAM_STATE_CLOSED);
result = mEndPointParcelable.close();
- aaudio_result_t result2 = AudioStream::close();
+ aaudio_result_t result2 = AudioStream::release_l();
return (result != AAUDIO_OK) ? result : result2;
} else {
return AAUDIO_ERROR_INVALID_HANDLE;
diff --git a/media/libaaudio/src/client/AudioStreamInternal.h b/media/libaaudio/src/client/AudioStreamInternal.h
index 596d37f..8843a8a 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.h
+++ b/media/libaaudio/src/client/AudioStreamInternal.h
@@ -58,7 +58,7 @@
aaudio_result_t open(const AudioStreamBuilder &builder) override;
- aaudio_result_t close() override;
+ aaudio_result_t release_l() override;
aaudio_result_t setBufferSize(int32_t requestedFrames) override;
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index dc9f48c..536009a 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -49,7 +49,7 @@
getDeviceChannelCount());
if (result != AAUDIO_OK) {
- close();
+ releaseCloseFinal();
}
// Sample rate is constrained to common values by now and should not overflow.
int32_t numFrames = kRampMSec * getSampleRate() / AAUDIO_MILLIS_PER_SECOND;
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 184e9cb..8965875 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -25,7 +25,6 @@
#include <aaudio/AAudio.h>
#include <aaudio/AAudioTesting.h>
-
#include "AudioClock.h"
#include "AudioGlobal.h"
#include "AudioStreamBuilder.h"
@@ -231,21 +230,42 @@
return AAUDIO_ERROR_NULL;
}
-AAUDIO_API aaudio_result_t AAudioStream_close(AAudioStream* stream)
-{
+AAUDIO_API aaudio_result_t AAudioStream_release(AAudioStream* stream) {
aaudio_result_t result = AAUDIO_ERROR_NULL;
- AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
+ AudioStream* audioStream = convertAAudioStreamToAudioStream(stream);
if (audioStream != nullptr) {
aaudio_stream_id_t id = audioStream->getId();
ALOGD("%s(s#%u) called ---------------", __func__, id);
- result = audioStream->safeClose();
- // Close will only fail if called illegally, for example, from a callback.
+ result = audioStream->safeRelease();
+ // safeRelease() will only fail if called illegally, for example, from a callback.
+ // That would result in the release of an active stream, which would cause a crash.
+ if (result != AAUDIO_OK) {
+ ALOGW("%s(s#%u) failed. Release it from another thread.",
+ __func__, id);
+ }
+ ALOGD("%s(s#%u) returned %d %s ---------", __func__,
+ id, result, AAudio_convertResultToText(result));
+ }
+ return result;
+}
+
+AAUDIO_API aaudio_result_t AAudioStream_close(AAudioStream* stream) {
+ aaudio_result_t result = AAUDIO_ERROR_NULL;
+ AudioStream* audioStream = convertAAudioStreamToAudioStream(stream);
+ if (audioStream != nullptr) {
+ aaudio_stream_id_t id = audioStream->getId();
+ ALOGD("%s(s#%u) called ---------------", __func__, id);
+ result = audioStream->safeRelease();
+ // safeRelease will only fail if called illegally, for example, from a callback.
// That would result in deleting an active stream, which would cause a crash.
- if (result == AAUDIO_OK) {
- audioStream->unregisterPlayerBase();
- delete audioStream;
+ if (result != AAUDIO_OK) {
+ ALOGW("%s(s#%u) failed. Close it from another thread.",
+ __func__, id);
} else {
- ALOGW("%s attempt to close failed. Close it from another thread.", __func__);
+ audioStream->unregisterPlayerBase();
+ // Mark CLOSED to keep destructors from asserting.
+ audioStream->closeFinal();
+ delete audioStream;
}
ALOGD("%s(s#%u) returned %d ---------", __func__, id, result);
}
diff --git a/media/libaaudio/src/core/AudioGlobal.cpp b/media/libaaudio/src/core/AudioGlobal.cpp
index e6d9a0d..d299761 100644
--- a/media/libaaudio/src/core/AudioGlobal.cpp
+++ b/media/libaaudio/src/core/AudioGlobal.cpp
@@ -87,9 +87,9 @@
AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHED);
AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPING);
AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPED);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_DISCONNECTED);
AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSING);
AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSED);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_DISCONNECTED);
}
return "Unrecognized AAudio state.";
}
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 1560e0c..f51db70 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -249,25 +249,29 @@
return requestStop();
}
-aaudio_result_t AudioStream::safeClose() {
- // This get temporarily unlocked in the close when joining callback threads.
+aaudio_result_t AudioStream::safeRelease() {
+ // This get temporarily unlocked in the release() when joining callback threads.
std::lock_guard<std::mutex> lock(mStreamLock);
if (collidesWithCallback()) {
ALOGE("%s cannot be called from a callback!", __func__);
return AAUDIO_ERROR_INVALID_STATE;
}
- return close();
+ if (getState() == AAUDIO_STREAM_STATE_CLOSING) {
+ return AAUDIO_OK;
+ }
+ return release_l();
}
void AudioStream::setState(aaudio_stream_state_t state) {
- ALOGV("%s(%d) from %d to %d", __func__, getId(), mState, state);
+ ALOGD("%s(s#%d) from %d to %d", __func__, getId(), mState, state);
// CLOSED is a final state
if (mState == AAUDIO_STREAM_STATE_CLOSED) {
ALOGE("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
- // Once DISCONNECTED, we can only move to CLOSED state.
+ // Once DISCONNECTED, we can only move to CLOSING or CLOSED state.
} else if (mState == AAUDIO_STREAM_STATE_DISCONNECTED
- && state != AAUDIO_STREAM_STATE_CLOSED) {
+ && !(state == AAUDIO_STREAM_STATE_CLOSING
+ || state == AAUDIO_STREAM_STATE_CLOSED)) {
ALOGE("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);
} else {
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index b4ffcf2..9bda41b 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -115,13 +115,32 @@
virtual aaudio_result_t open(const AudioStreamBuilder& builder);
/**
- * Close the stream and deallocate any resources from the open() call.
- * It is safe to call close() multiple times.
+ * Free any hardware or system resources from the open() call.
+ * It is safe to call release_l() multiple times.
*/
- virtual aaudio_result_t close() {
+ virtual aaudio_result_t release_l() {
+ setState(AAUDIO_STREAM_STATE_CLOSING);
return AAUDIO_OK;
}
+ aaudio_result_t closeFinal() {
+ // State is checked by destructor.
+ setState(AAUDIO_STREAM_STATE_CLOSED);
+ return AAUDIO_OK;
+ }
+
+ /**
+ * Release then close the stream.
+ * @return AAUDIO_OK or negative error.
+ */
+ aaudio_result_t releaseCloseFinal() {
+ aaudio_result_t result = release_l(); // TODO review locking
+ if (result == AAUDIO_OK) {
+ result = closeFinal();
+ }
+ return result;
+ }
+
// This is only used to identify a stream in the logs without
// revealing any pointers.
aaudio_stream_id_t getId() {
@@ -373,7 +392,7 @@
*/
aaudio_result_t systemStopFromCallback();
- aaudio_result_t safeClose();
+ aaudio_result_t safeRelease();
protected:
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 54af580..2ed82d2 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -182,7 +182,7 @@
// Did we get a valid track?
status_t status = mAudioRecord->initCheck();
if (status != OK) {
- close();
+ releaseCloseFinal();
ALOGE("open(), initCheck() returned %d", status);
return AAudioConvert_androidToAAudioResult(status);
}
@@ -278,16 +278,17 @@
return AAUDIO_OK;
}
-aaudio_result_t AudioStreamRecord::close()
-{
- // TODO add close() or release() to AudioRecord API then call it from here
- if (getState() != AAUDIO_STREAM_STATE_CLOSED) {
+aaudio_result_t AudioStreamRecord::release_l() {
+ // TODO add close() or release() to AudioFlinger's AudioRecord API.
+ // Then call it from here
+ if (getState() != AAUDIO_STREAM_STATE_CLOSING) {
mAudioRecord->removeAudioDeviceCallback(mDeviceCallback);
mAudioRecord.clear();
- setState(AAUDIO_STREAM_STATE_CLOSED);
+ mFixedBlockWriter.close();
+ return AudioStream::release_l();
+ } else {
+ return AAUDIO_OK; // already released
}
- mFixedBlockWriter.close();
- return AudioStream::close();
}
const void * AudioStreamRecord::maybeConvertDeviceData(const void *audioData, int32_t numFrames) {
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.h b/media/libaaudio/src/legacy/AudioStreamRecord.h
index 2f41d34..c5944c7 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.h
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.h
@@ -38,7 +38,7 @@
virtual ~AudioStreamRecord();
aaudio_result_t open(const AudioStreamBuilder & builder) override;
- aaudio_result_t close() override;
+ aaudio_result_t release_l() override;
aaudio_result_t requestStart() override;
aaudio_result_t requestStop() override;
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 094cdd1..00963d6 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -176,7 +176,7 @@
// Did we get a valid track?
status_t status = mAudioTrack->initCheck();
if (status != NO_ERROR) {
- close();
+ releaseCloseFinal();
ALOGE("open(), initCheck() returned %d", status);
return AAudioConvert_androidToAAudioResult(status);
}
@@ -239,14 +239,18 @@
return AAUDIO_OK;
}
-aaudio_result_t AudioStreamTrack::close()
-{
- if (getState() != AAUDIO_STREAM_STATE_CLOSED) {
+aaudio_result_t AudioStreamTrack::release_l() {
+ if (getState() != AAUDIO_STREAM_STATE_CLOSING) {
mAudioTrack->removeAudioDeviceCallback(mDeviceCallback);
- setState(AAUDIO_STREAM_STATE_CLOSED);
+ // TODO Investigate why clear() causes a hang in test_various.cpp
+ // if I call close() from a data callback.
+ // But the same thing in AudioRecord is OK!
+ // mAudioTrack.clear();
+ mFixedBlockReader.close();
+ return AudioStream::release_l();
+ } else {
+ return AAUDIO_OK; // already released
}
- mFixedBlockReader.close();
- return AAUDIO_OK;
}
void AudioStreamTrack::processCallback(int event, void *info) {
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.h b/media/libaaudio/src/legacy/AudioStreamTrack.h
index 68608de..550f693 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.h
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.h
@@ -41,7 +41,7 @@
aaudio_result_t open(const AudioStreamBuilder & builder) override;
- aaudio_result_t close() override;
+ aaudio_result_t release_l() override;
aaudio_result_t requestStart() override;
aaudio_result_t requestPause() override;
diff --git a/media/libaaudio/src/libaaudio.map.txt b/media/libaaudio/src/libaaudio.map.txt
index 4605e82..2e00aa5 100644
--- a/media/libaaudio/src/libaaudio.map.txt
+++ b/media/libaaudio/src/libaaudio.map.txt
@@ -58,6 +58,7 @@
AAudioStream_getTimestamp;
AAudioStream_isMMapUsed;
AAudioStream_isPrivacySensitive; # introduced=30
+ AAudioStream_release; # introduced=30
local:
*;
};
diff --git a/media/libaaudio/tests/test_various.cpp b/media/libaaudio/tests/test_various.cpp
index 935d88b..5bb1046 100644
--- a/media/libaaudio/tests/test_various.cpp
+++ b/media/libaaudio/tests/test_various.cpp
@@ -40,10 +40,62 @@
return AAUDIO_CALLBACK_RESULT_CONTINUE;
}
-// Test AAudioStream_setBufferSizeInFrames()
-
constexpr int64_t NANOS_PER_MILLISECOND = 1000 * 1000;
+void checkReleaseThenClose(aaudio_performance_mode_t perfMode,
+ aaudio_sharing_mode_t sharingMode) {
+ AAudioStreamBuilder* aaudioBuilder = nullptr;
+ AAudioStream* aaudioStream = nullptr;
+
+ // Use an AAudioStreamBuilder to contain requested parameters.
+ ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
+
+ // Request stream properties.
+ AAudioStreamBuilder_setDataCallback(aaudioBuilder,
+ NoopDataCallbackProc,
+ nullptr);
+ AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
+ AAudioStreamBuilder_setSharingMode(aaudioBuilder, sharingMode);
+
+ // Create an AAudioStream using the Builder.
+ ASSERT_EQ(AAUDIO_OK,
+ AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
+ AAudioStreamBuilder_delete(aaudioBuilder);
+
+ ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
+
+ sleep(1);
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_release(aaudioStream));
+ aaudio_stream_state_t state = AAudioStream_getState(aaudioStream);
+ EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, state);
+
+ // We should be able to call this again without crashing.
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_release(aaudioStream));
+ state = AAudioStream_getState(aaudioStream);
+ EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, state);
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
+}
+
+TEST(test_various, aaudio_release_close_none) {
+ checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_NONE,
+ AAUDIO_SHARING_MODE_SHARED);
+ // No EXCLUSIVE streams with MODE_NONE.
+}
+
+TEST(test_various, aaudio_release_close_low_shared) {
+ checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+ AAUDIO_SHARING_MODE_SHARED);
+}
+
+TEST(test_various, aaudio_release_close_low_exclusive) {
+ checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+ AAUDIO_SHARING_MODE_EXCLUSIVE);
+}
+
enum FunctionToCall {
CALL_START, CALL_STOP, CALL_PAUSE, CALL_FLUSH
};
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index 06fc23c..d468239 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -53,6 +53,10 @@
case RULE_EXCLUDE_UID:
mValue.mUid = (uid_t) parcel->readInt32();
break;
+ case RULE_MATCH_USERID:
+ case RULE_EXCLUDE_USERID:
+ mValue.mUserId = (int) parcel->readInt32();
+ break;
default:
ALOGE("Trying to build AudioMixMatchCriterion from unknown rule %d", mRule);
return BAD_VALUE;
@@ -163,9 +167,50 @@
return false;
}
+void AudioMix::setExcludeUserId(int userId) const {
+ AudioMixMatchCriterion crit;
+ crit.mRule = RULE_EXCLUDE_USERID;
+ crit.mValue.mUserId = userId;
+ mCriteria.add(crit);
+}
+
+void AudioMix::setMatchUserId(int userId) const {
+ AudioMixMatchCriterion crit;
+ crit.mRule = RULE_MATCH_USERID;
+ crit.mValue.mUserId = userId;
+ mCriteria.add(crit);
+}
+
+bool AudioMix::hasUserIdRule(bool match, int userId) const {
+ const uint32_t rule = match ? RULE_MATCH_USERID : RULE_EXCLUDE_USERID;
+ for (size_t i = 0; i < mCriteria.size(); i++) {
+ if (mCriteria[i].mRule == rule
+ && mCriteria[i].mValue.mUserId == userId) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool AudioMix::hasMatchUserIdRule() const {
+ for (size_t i = 0; i < mCriteria.size(); i++) {
+ if (mCriteria[i].mRule == RULE_MATCH_USERID) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool AudioMix::isDeviceAffinityCompatible() const {
return ((mMixType == MIX_TYPE_PLAYERS)
&& (mRouteFlags == MIX_ROUTE_FLAG_RENDER));
}
+bool AudioMix::hasMatchingRuleForUsage(std::function<bool (audio_usage_t)>const& func) const {
+ return std::any_of(mCriteria.begin(), mCriteria.end(), [func](auto& criterion) {
+ return criterion.mRule == RULE_MATCH_ATTRIBUTE_USAGE
+ && func(criterion.mValue.mUsage);
+ });
+}
+
} // namespace android
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 6914d5a..1769062 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1359,6 +1359,21 @@
return aps->removeUidDeviceAffinities(uid);
}
+status_t AudioSystem::setUserIdDeviceAffinities(int userId,
+ const Vector<AudioDeviceTypeAddr>& devices)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->setUserIdDeviceAffinities(userId, devices);
+}
+
+status_t AudioSystem::removeUserIdDeviceAffinities(int userId)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->removeUserIdDeviceAffinities(userId);
+}
+
status_t AudioSystem::startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId)
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index ce8b33c..ce38414 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -97,6 +97,8 @@
IS_HAPTIC_PLAYBACK_SUPPORTED,
SET_UID_DEVICE_AFFINITY,
REMOVE_UID_DEVICE_AFFINITY,
+ SET_USERID_DEVICE_AFFINITY,
+ REMOVE_USERID_DEVICE_AFFINITY,
GET_OFFLOAD_FORMATS_A2DP,
LIST_AUDIO_PRODUCT_STRATEGIES,
GET_STRATEGY_FOR_ATTRIBUTES,
@@ -1197,6 +1199,52 @@
return status;
}
+ virtual status_t setUserIdDeviceAffinities(int userId,
+ const Vector<AudioDeviceTypeAddr>& devices)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+ data.writeInt32((int32_t) userId);
+ size_t size = devices.size();
+ size_t sizePosition = data.dataPosition();
+ data.writeInt32((int32_t) size);
+ size_t finalSize = size;
+ for (size_t i = 0; i < size; i++) {
+ size_t position = data.dataPosition();
+ if (devices[i].writeToParcel(&data) != NO_ERROR) {
+ data.setDataPosition(position);
+ finalSize--;
+ }
+ }
+ if (size != finalSize) {
+ size_t position = data.dataPosition();
+ data.setDataPosition(sizePosition);
+ data.writeInt32(finalSize);
+ data.setDataPosition(position);
+ }
+
+ status_t status = remote()->transact(SET_USERID_DEVICE_AFFINITY, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t)reply.readInt32();
+ }
+ return status;
+ }
+
+ virtual status_t removeUserIdDeviceAffinities(int userId) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+ data.writeInt32((int32_t) userId);
+
+ status_t status =
+ remote()->transact(REMOVE_USERID_DEVICE_AFFINITY, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t) reply.readInt32();
+ }
+ return status;
+ }
+
virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies)
{
Parcel data, reply;
@@ -1457,6 +1505,8 @@
case SET_A11Y_SERVICES_UIDS:
case SET_UID_DEVICE_AFFINITY:
case REMOVE_UID_DEVICE_AFFINITY:
+ case SET_USERID_DEVICE_AFFINITY:
+ case REMOVE_USERID_DEVICE_AFFINITY:
case GET_OFFLOAD_FORMATS_A2DP:
case LIST_AUDIO_VOLUME_GROUPS:
case GET_VOLUME_GROUP_FOR_ATTRIBUTES:
@@ -2379,6 +2429,30 @@
return NO_ERROR;
}
+ case SET_USERID_DEVICE_AFFINITY: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ const int userId = (int) data.readInt32();
+ Vector<AudioDeviceTypeAddr> devices;
+ size_t size = (size_t)data.readInt32();
+ for (size_t i = 0; i < size; i++) {
+ AudioDeviceTypeAddr device;
+ if (device.readFromParcel((Parcel*)&data) == NO_ERROR) {
+ devices.add(device);
+ }
+ }
+ status_t status = setUserIdDeviceAffinities(userId, devices);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+
+ case REMOVE_USERID_DEVICE_AFFINITY: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ const int userId = (int) data.readInt32();
+ status_t status = removeUserIdDeviceAffinities(userId);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+
case LIST_AUDIO_PRODUCT_STRATEGIES: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
AudioProductStrategyVector strategies;
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index 0ab1c9d..20d2c0b 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -18,12 +18,14 @@
#ifndef ANDROID_AUDIO_POLICY_H
#define ANDROID_AUDIO_POLICY_H
+#include <functional>
#include <binder/Parcel.h>
#include <media/AudioDeviceTypeAddr.h>
#include <system/audio.h>
#include <system/audio_policy.h>
#include <utils/String8.h>
#include <utils/Vector.h>
+#include <cutils/multiuser.h>
namespace android {
@@ -32,10 +34,12 @@
#define RULE_MATCH_ATTRIBUTE_USAGE 0x1
#define RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET (0x1 << 1)
#define RULE_MATCH_UID (0x1 << 2)
+#define RULE_MATCH_USERID (0x1 << 3)
#define RULE_EXCLUDE_ATTRIBUTE_USAGE (RULE_EXCLUSION_MASK|RULE_MATCH_ATTRIBUTE_USAGE)
#define RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET \
(RULE_EXCLUSION_MASK|RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET)
#define RULE_EXCLUDE_UID (RULE_EXCLUSION_MASK|RULE_MATCH_UID)
+#define RULE_EXCLUDE_USERID (RULE_EXCLUSION_MASK|RULE_MATCH_USERID)
#define MIX_TYPE_INVALID (-1)
#define MIX_TYPE_PLAYERS 0
@@ -73,6 +77,7 @@
audio_usage_t mUsage;
audio_source_t mSource;
uid_t mUid;
+ int mUserId;
} mValue;
uint32_t mRule;
};
@@ -98,9 +103,23 @@
bool hasUidRule(bool match, uid_t uid) const;
/** returns true if this mix has a rule for uid match (any uid) */
bool hasMatchUidRule() const;
+
+ void setExcludeUserId(int userId) const;
+ void setMatchUserId(int userId) const;
+ /** returns true if this mix has a rule to match or exclude the given userId */
+ bool hasUserIdRule(bool match, int userId) const;
+ /** returns true if this mix has a rule for userId match (any userId) */
+ bool hasMatchUserIdRule() const;
/** returns true if this mix can be used for uid-device affinity routing */
bool isDeviceAffinityCompatible() const;
+ /**
+ * returns true if the mix has a capture rule for a usage that
+ * matches the given predicate
+ */
+ bool hasMatchingRuleForUsage(
+ std::function<bool (audio_usage_t)>const& func) const;
+
mutable Vector<AudioMixMatchCriterion> mCriteria;
uint32_t mMixType;
audio_config_t mFormat;
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 691755f..9d3f8b6 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -364,6 +364,10 @@
static status_t removeUidDeviceAffinities(uid_t uid);
+ static status_t setUserIdDeviceAffinities(int userId, const Vector<AudioDeviceTypeAddr>& devices);
+
+ static status_t removeUserIdDeviceAffinities(int userId);
+
static status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId);
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 402fdcf..caa1d13 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -195,6 +195,11 @@
virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
+ virtual status_t setUserIdDeviceAffinities(int userId,
+ const Vector<AudioDeviceTypeAddr>& devices) = 0;
+
+ virtual status_t removeUserIdDeviceAffinities(int userId) = 0;
+
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId) = 0;
diff --git a/media/libstagefright/FrameCaptureProcessor.cpp b/media/libstagefright/FrameCaptureProcessor.cpp
index c517e33..96c1195 100644
--- a/media/libstagefright/FrameCaptureProcessor.cpp
+++ b/media/libstagefright/FrameCaptureProcessor.cpp
@@ -136,7 +136,7 @@
status_t FrameCaptureProcessor::onCapture(const sp<Layer> &layer,
const Rect &sourceCrop, const sp<GraphicBuffer> &buffer) {
renderengine::DisplaySettings clientCompositionDisplay;
- std::vector<renderengine::LayerSettings> clientCompositionLayers;
+ std::vector<const renderengine::LayerSettings*> clientCompositionLayers;
clientCompositionDisplay.physicalDisplay = sourceCrop;
clientCompositionDisplay.clip = sourceCrop;
@@ -150,7 +150,7 @@
layer->getLayerSettings(sourceCrop, mTextureName, &layerSettings);
- clientCompositionLayers.push_back(layerSettings);
+ clientCompositionLayers.push_back(&layerSettings);
// Use an empty fence for the buffer fence, since we just created the buffer so
// there is no need for synchronization with the GPU.
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index e1c3916..2f69f45 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -492,6 +492,12 @@
}
case OMX_StateLoaded:
+ {
+ if (mActiveBuffers.size() > 0) {
+ freeActiveBuffers();
+ }
+ FALLTHROUGH_INTENDED;
+ }
case OMX_StateInvalid:
break;
diff --git a/media/tests/benchmark/src/native/common/BenchmarkC2Common.cpp b/media/tests/benchmark/src/native/common/BenchmarkC2Common.cpp
index 622a0e1..e09f468 100644
--- a/media/tests/benchmark/src/native/common/BenchmarkC2Common.cpp
+++ b/media/tests/benchmark/src/native/common/BenchmarkC2Common.cpp
@@ -22,6 +22,9 @@
int32_t BenchmarkC2Common::setupCodec2() {
ALOGV("In %s", __func__);
mClient = android::Codec2Client::CreateFromService("default");
+ if (!mClient) {
+ mClient = android::Codec2Client::CreateFromService("software");
+ }
if (!mClient) return -1;
std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 343ec05..87ea084 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -145,6 +145,15 @@
return ok;
}
+bool captureVoiceCommunicationOutputAllowed(pid_t pid, uid_t uid) {
+ if (isAudioServerOrRootUid(uid)) return true;
+ static const String16 sCaptureVoiceCommOutput(
+ "android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT");
+ bool ok = PermissionCache::checkPermission(sCaptureVoiceCommOutput, pid, uid);
+ if (!ok) ALOGE("Request requires android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT");
+ return ok;
+}
+
bool captureHotwordAllowed(const String16& opPackageName, pid_t pid, uid_t uid) {
// CAPTURE_AUDIO_HOTWORD permission implies RECORD_AUDIO permission
bool ok = recordingAllowed(opPackageName, pid, uid);
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 4925cdb..212599a 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -83,6 +83,7 @@
void finishRecording(const String16& opPackageName, uid_t uid);
bool captureAudioOutputAllowed(pid_t pid, uid_t uid);
bool captureMediaOutputAllowed(pid_t pid, uid_t uid);
+bool captureVoiceCommunicationOutputAllowed(pid_t pid, uid_t uid);
bool captureHotwordAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
bool settingsAllowed();
bool modifyAudioRoutingAllowed();
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index dd0cd9b..4d53be4 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -250,6 +250,10 @@
= 0;
virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
+ virtual status_t setUserIdDeviceAffinities(int userId,
+ const Vector<AudioDeviceTypeAddr>& devices) = 0;
+ virtual status_t removeUserIdDeviceAffinities(int userId) = 0;
+
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId,
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index fc79ab1..a757551 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -105,12 +105,27 @@
status_t removeUidDeviceAffinities(uid_t uid);
status_t getDevicesForUid(uid_t uid, Vector<AudioDeviceTypeAddr>& devices) const;
+ /**
+ * Updates the mix rules in order to make streams associated with the given user
+ * be routed to the given audio devices.
+ * @param userId the userId for which the device affinity is set
+ * @param devices the vector of devices that this userId may be routed to. A typical
+ * use is to pass the devices associated with a given zone in a multi-zone setup.
+ * @return NO_ERROR if the update was successful, INVALID_OPERATION otherwise.
+ * An example of failure is when there are already rules in place to restrict
+ * a mix to the given userId (i.e. when a MATCH_USERID rule was set for it).
+ */
+ status_t setUserIdDeviceAffinities(int userId, const Vector<AudioDeviceTypeAddr>& devices);
+ status_t removeUserIdDeviceAffinities(int userId);
+ status_t getDevicesForUserId(int userId, Vector<AudioDeviceTypeAddr>& devices) const;
+
void dump(String8 *dst) const;
private:
enum class MixMatchStatus { MATCH, NO_MATCH, INVALID_MIX };
MixMatchStatus mixMatch(const AudioMix* mix, size_t mixIndex,
- const audio_attributes_t& attributes, uid_t uid);
+ const audio_attributes_t& attributes,
+ uid_t uid);
};
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index b1103ab..11660f0 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -60,6 +60,9 @@
case RULE_MATCH_UID:
ruleValue = std::to_string(criterion.mValue.mUid);
break;
+ case RULE_MATCH_USERID:
+ ruleValue = std::to_string(criterion.mValue.mUserId);
+ break;
default:
unknownRule = true;
}
@@ -223,10 +226,14 @@
}
if (!(attributes.usage == AUDIO_USAGE_UNKNOWN ||
attributes.usage == AUDIO_USAGE_MEDIA ||
- attributes.usage == AUDIO_USAGE_GAME)) {
+ attributes.usage == AUDIO_USAGE_GAME ||
+ attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION)) {
return MixMatchStatus::NO_MATCH;
}
}
+
+ int userId = (int) multiuser_get_user_id(uid);
+
// TODO if adding more player rules (currently only 2), make rule handling "generic"
// as there is no difference in the treatment of usage- or uid-based rules
bool hasUsageMatchRules = false;
@@ -239,6 +246,12 @@
bool uidMatchFound = false;
bool uidExclusionFound = false;
+ bool hasUserIdExcludeRules = false;
+ bool userIdExclusionFound = false;
+ bool hasUserIdMatchRules = false;
+ bool userIdMatchFound = false;
+
+
bool hasAddrMatch = false;
// iterate over all mix criteria to list what rules this mix contains
@@ -290,6 +303,24 @@
uidExclusionFound = true;
}
break;
+ case RULE_MATCH_USERID:
+ ALOGV("\tmix has RULE_MATCH_USERID for userId %d",
+ mix->mCriteria[j].mValue.mUserId);
+ hasUserIdMatchRules = true;
+ if (mix->mCriteria[j].mValue.mUserId == userId) {
+ // found one userId match against all allowed userIds
+ userIdMatchFound = true;
+ }
+ break;
+ case RULE_EXCLUDE_USERID:
+ ALOGV("\tmix has RULE_EXCLUDE_USERID for userId %d",
+ mix->mCriteria[j].mValue.mUserId);
+ hasUserIdExcludeRules = true;
+ if (mix->mCriteria[j].mValue.mUserId == userId) {
+ // found this userId is to be excluded
+ userIdExclusionFound = true;
+ }
+ break;
default:
break;
}
@@ -306,20 +337,27 @@
" and RULE_EXCLUDE_UID in mix %zu", mixIndex);
return MixMatchStatus::INVALID_MIX;
}
-
- if ((hasUsageExcludeRules && usageExclusionFound)
- || (hasUidExcludeRules && uidExclusionFound)) {
- break; // stop iterating on criteria because an exclusion was found (will fail)
+ if (hasUserIdMatchRules && hasUserIdExcludeRules) {
+ ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_USERID"
+ " and RULE_EXCLUDE_USERID in mix %zu", mixIndex);
+ return MixMatchStatus::INVALID_MIX;
}
+ if ((hasUsageExcludeRules && usageExclusionFound)
+ || (hasUidExcludeRules && uidExclusionFound)
+ || (hasUserIdExcludeRules && userIdExclusionFound)) {
+ break; // stop iterating on criteria because an exclusion was found (will fail)
+ }
}//iterate on mix criteria
// determine if exiting on success (or implicit failure as desc is 0)
if (hasAddrMatch ||
!((hasUsageExcludeRules && usageExclusionFound) ||
+ (hasUserIdExcludeRules && userIdExclusionFound) ||
(hasUsageMatchRules && !usageMatchFound) ||
(hasUidExcludeRules && uidExclusionFound) ||
- (hasUidMatchRules && !uidMatchFound))) {
+ (hasUidMatchRules && !uidMatchFound)) ||
+ (hasUserIdMatchRules && !userIdMatchFound)) {
ALOGV("\tgetOutputForAttr will use mix %zu", mixIndex);
return MixMatchStatus::MATCH;
}
@@ -530,6 +568,109 @@
return NO_ERROR;
}
+status_t AudioPolicyMixCollection::setUserIdDeviceAffinities(int userId,
+ const Vector<AudioDeviceTypeAddr>& devices) {
+ // verify feasibility: for each player mix: if it already contains a
+ // "match userId" rule for this userId, return an error
+ // (adding a userId-device affinity would result in contradictory rules)
+ for (size_t i = 0; i < size(); i++) {
+ const AudioPolicyMix* mix = itemAt(i).get();
+ if (!mix->isDeviceAffinityCompatible()) {
+ continue;
+ }
+ if (mix->hasUserIdRule(true /*match*/, userId)) {
+ return INVALID_OPERATION;
+ }
+ }
+
+ // remove existing rules for this userId
+ removeUserIdDeviceAffinities(userId);
+
+ // for each player mix:
+ // IF device is not a target for the mix,
+ // AND it doesn't have a "match userId" rule
+ // THEN add a rule to exclude the userId
+ for (size_t i = 0; i < size(); i++) {
+ const AudioPolicyMix *mix = itemAt(i).get();
+ if (!mix->isDeviceAffinityCompatible()) {
+ continue;
+ }
+ // check if this mix goes to a device in the list of devices
+ bool deviceMatch = false;
+ const AudioDeviceTypeAddr mixDevice(mix->mDeviceType, mix->mDeviceAddress.string());
+ for (size_t j = 0; j < devices.size(); j++) {
+ if (mixDevice.equals(devices[j])) {
+ deviceMatch = true;
+ break;
+ }
+ }
+ if (!deviceMatch && !mix->hasMatchUserIdRule()) {
+ // this mix doesn't go to one of the listed devices for the given userId,
+ // and it's not already restricting the mix on a userId,
+ // modify its rules to exclude the userId
+ if (!mix->hasUserIdRule(false /*match*/, userId)) {
+ // no need to do it again if userId is already excluded
+ mix->setExcludeUserId(userId);
+ }
+ }
+ }
+
+ return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::removeUserIdDeviceAffinities(int userId) {
+ // for each player mix: remove existing rules that match or exclude this userId
+ for (size_t i = 0; i < size(); i++) {
+ bool foundUserIdRule = false;
+ const AudioPolicyMix *mix = itemAt(i).get();
+ if (!mix->isDeviceAffinityCompatible()) {
+ continue;
+ }
+ std::vector<size_t> criteriaToRemove;
+ for (size_t j = 0; j < mix->mCriteria.size(); j++) {
+ const uint32_t rule = mix->mCriteria[j].mRule;
+ // is this rule excluding the userId? (not considering userId match rules
+ // as those are not used for userId-device affinity)
+ if (rule == RULE_EXCLUDE_USERID
+ && userId == mix->mCriteria[j].mValue.mUserId) {
+ foundUserIdRule = true;
+ criteriaToRemove.insert(criteriaToRemove.begin(), j);
+ }
+ }
+ if (foundUserIdRule) {
+ for (size_t j = 0; j < criteriaToRemove.size(); j++) {
+ mix->mCriteria.removeAt(criteriaToRemove[j]);
+ }
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::getDevicesForUserId(int userId,
+ Vector<AudioDeviceTypeAddr>& devices) const {
+ // for each player mix:
+ // find rules that don't exclude this userId, and add the device to the list
+ for (size_t i = 0; i < size(); i++) {
+ bool ruleAllowsUserId = true;
+ const AudioPolicyMix *mix = itemAt(i).get();
+ if (mix->mMixType != MIX_TYPE_PLAYERS) {
+ continue;
+ }
+ for (size_t j = 0; j < mix->mCriteria.size(); j++) {
+ const uint32_t rule = mix->mCriteria[j].mRule;
+ if (rule == RULE_EXCLUDE_USERID
+ && userId == mix->mCriteria[j].mValue.mUserId) {
+ ruleAllowsUserId = false;
+ break;
+ }
+ }
+ if (ruleAllowsUserId) {
+ devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string()));
+ }
+ }
+ return NO_ERROR;
+}
+
void AudioPolicyMixCollection::dump(String8 *dst) const
{
dst->append("\nAudio Policy Mix:\n");
diff --git a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
index 2b5455e..c5b3546 100644
--- a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
@@ -55,9 +55,11 @@
MAKE_STRING_FROM_ENUM(RULE_MATCH_ATTRIBUTE_USAGE),
MAKE_STRING_FROM_ENUM(RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET),
MAKE_STRING_FROM_ENUM(RULE_MATCH_UID),
+ MAKE_STRING_FROM_ENUM(RULE_MATCH_USERID),
MAKE_STRING_FROM_ENUM(RULE_EXCLUDE_ATTRIBUTE_USAGE),
MAKE_STRING_FROM_ENUM(RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET),
MAKE_STRING_FROM_ENUM(RULE_EXCLUDE_UID),
+ MAKE_STRING_FROM_ENUM(RULE_EXCLUDE_USERID),
TERMINATOR
};
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 175e40d..c3b1b9d 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -3150,6 +3150,49 @@
return mEngine->getPreferredDeviceForStrategy(strategy, device);
}
+status_t AudioPolicyManager::setUserIdDeviceAffinities(int userId,
+ const Vector<AudioDeviceTypeAddr>& devices) {
+ ALOGI("%s() userId=%d num devices %zu", __FUNCTION__, userId, devices.size());
+ // userId/device affinity is only for output devices
+ for (size_t i = 0; i < devices.size(); i++) {
+ if (!audio_is_output_device(devices[i].mType)) {
+ ALOGE("%s() device=%08x is NOT an output device",
+ __FUNCTION__,
+ devices[i].mType);
+ return BAD_VALUE;
+ }
+ }
+
+ status_t status = mPolicyMixes.setUserIdDeviceAffinities(userId, devices);
+ if (status != NO_ERROR) {
+ ALOGE("%s() could not set device affinity for userId %d",
+ __FUNCTION__, userId);
+ return status;
+ }
+
+ // reevaluate outputs for all devices
+ checkForDeviceAndOutputChanges();
+ updateCallAndOutputRouting();
+
+ return NO_ERROR;
+}
+
+status_t AudioPolicyManager::removeUserIdDeviceAffinities(int userId) {
+ ALOGI("%s() userId=%d", __FUNCTION__, userId);
+ status_t status = mPolicyMixes.removeUserIdDeviceAffinities(userId);
+ if (status != NO_ERROR) {
+ ALOGE("%s() Could not remove all device affinities fo userId = %d",
+ __FUNCTION__, userId);
+ return status;
+ }
+
+ // reevaluate outputs for all devices
+ checkForDeviceAndOutputChanges();
+ updateCallAndOutputRouting();
+
+ return NO_ERROR;
+}
+
void AudioPolicyManager::dump(String8 *dst) const
{
dst->appendFormat("\nAudioPolicyManager Dump: %p\n", this);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 7e0e16f..10adeb4 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -262,6 +262,9 @@
virtual status_t setUidDeviceAffinities(uid_t uid,
const Vector<AudioDeviceTypeAddr>& devices);
virtual status_t removeUidDeviceAffinities(uid_t uid);
+ virtual status_t setUserIdDeviceAffinities(int userId,
+ const Vector<AudioDeviceTypeAddr>& devices);
+ virtual status_t removeUserIdDeviceAffinities(int userId);
virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device);
diff --git a/services/audiopolicy/service/Android.mk b/services/audiopolicy/service/Android.mk
index 80f4eab..d34dbe3 100644
--- a/services/audiopolicy/service/Android.mk
+++ b/services/audiopolicy/service/Android.mk
@@ -26,6 +26,7 @@
libaudioutils \
libaudiofoundation \
libhardware_legacy \
+ libaudiopolicy \
libaudiopolicymanager \
libmedia_helper \
libmediametrics \
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index c865063..ee32afe 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1220,14 +1220,39 @@
return PERMISSION_DENIED;
}
+ // Require CAPTURE_VOICE_COMMUNICATION_OUTPUT if one of the
+ // mixes is a render|loopback mix that aim to capture audio played with
+ // USAGE_VOICE_COMMUNICATION.
+ bool needCaptureVoiceCommunicationOutput =
+ std::any_of(mixes.begin(), mixes.end(), [](auto& mix) {
+ return is_mix_loopback_render(mix.mRouteFlags) &&
+ mix.hasMatchingRuleForUsage([] (auto usage) {
+ return usage == AUDIO_USAGE_VOICE_COMMUNICATION;});
+ });
+
+ // Require CAPTURE_MEDIA_OUTPUT if there is a mix for priveliged capture
+ // which is trying to capture any usage which is not USAGE_VOICE_COMMUNICATION.
+ // (If USAGE_VOICE_COMMUNICATION should be captured, then CAPTURE_VOICE_COMMUNICATION_OUTPUT
+ // is required, even if it is not privileged capture).
bool needCaptureMediaOutput = std::any_of(mixes.begin(), mixes.end(), [](auto& mix) {
- return mix.mAllowPrivilegedPlaybackCapture; });
+ return mix.mAllowPrivilegedPlaybackCapture &&
+ mix.hasMatchingRuleForUsage([] (auto usage) {
+ return usage != AUDIO_USAGE_VOICE_COMMUNICATION;
+ });
+ });
+
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
const pid_t callingPid = IPCThreadState::self()->getCallingPid();
+
if (needCaptureMediaOutput && !captureMediaOutputAllowed(callingPid, callingUid)) {
return PERMISSION_DENIED;
}
+ if (needCaptureVoiceCommunicationOutput &&
+ !captureVoiceCommunicationOutputAllowed(callingPid, callingUid)) {
+ return PERMISSION_DENIED;
+ }
+
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
@@ -1264,6 +1289,31 @@
return mAudioPolicyManager->removeUidDeviceAffinities(uid);
}
+status_t AudioPolicyService::setUserIdDeviceAffinities(int userId,
+ const Vector<AudioDeviceTypeAddr>& devices) {
+ Mutex::Autolock _l(mLock);
+ if(!modifyAudioRoutingAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ AutoCallerClear acc;
+ return mAudioPolicyManager->setUserIdDeviceAffinities(userId, devices);
+}
+
+status_t AudioPolicyService::removeUserIdDeviceAffinities(int userId) {
+ Mutex::Autolock _l(mLock);
+ if(!modifyAudioRoutingAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ AutoCallerClear acc;
+ return mAudioPolicyManager->removeUserIdDeviceAffinities(userId);
+}
+
status_t AudioPolicyService::startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId)
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index d9fec9a..e297f34 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -235,6 +235,9 @@
virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device);
+ virtual status_t setUserIdDeviceAffinities(int userId, const Vector<AudioDeviceTypeAddr>& devices);
+
+ virtual status_t removeUserIdDeviceAffinities(int userId);
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index a1fc0ea..82cc90e 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -284,7 +284,7 @@
serviceEndpoint->close();
mSharedCloseCount++;
- ALOGV("%s() %p for device %d",
+ ALOGV("%s(%p) closed for device %d",
__func__, serviceEndpoint.get(), serviceEndpoint->getDeviceId());
}
}
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index 0a415fd..9b3b3b8 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -85,7 +85,7 @@
}
aaudio_result_t AAudioServiceEndpointShared::close() {
- return getStreamInternal()->close();
+ return getStreamInternal()->releaseCloseFinal();
}
// Glue between C and C++ callbacks.
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 880a3d7..39e90b1 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -56,7 +56,8 @@
LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
|| getState() == AAUDIO_STREAM_STATE_UNINITIALIZED
|| getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
- "service stream still open, state = %d", getState());
+ "service stream %p still open, state = %d",
+ this, getState());
}
std::string AAudioServiceStreamBase::dumpHeader() {
@@ -126,13 +127,13 @@
}
aaudio_result_t AAudioServiceStreamBase::close() {
- aaudio_result_t result = AAUDIO_OK;
if (getState() == AAUDIO_STREAM_STATE_CLOSED) {
return AAUDIO_OK;
}
stop();
+ aaudio_result_t result = AAUDIO_OK;
sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
if (endpoint == nullptr) {
result = AAUDIO_ERROR_INVALID_STATE;
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.cpp b/services/oboeservice/AAudioServiceStreamMMAP.cpp
index 837b080..f4e72b7 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.cpp
+++ b/services/oboeservice/AAudioServiceStreamMMAP.cpp
@@ -49,16 +49,6 @@
, mInService(inService) {
}
-aaudio_result_t AAudioServiceStreamMMAP::close() {
- if (getState() == AAUDIO_STREAM_STATE_CLOSED) {
- return AAUDIO_OK;
- }
-
- stop();
-
- return AAudioServiceStreamBase::close();
-}
-
// Open stream on HAL and pass information about the shared memory buffer back to the client.
aaudio_result_t AAudioServiceStreamMMAP::open(const aaudio::AAudioStreamRequest &request) {
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.h b/services/oboeservice/AAudioServiceStreamMMAP.h
index 1509f7d..3d56623 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.h
+++ b/services/oboeservice/AAudioServiceStreamMMAP.h
@@ -67,8 +67,6 @@
aaudio_result_t stopClient(audio_port_handle_t clientHandle) override;
- aaudio_result_t close() override;
-
const char *getTypeText() const override { return "MMAP"; }
protected: