AudioRecord: Allow to share capture history.
Add the possibility for privileged applications to
share part of their audio capture history with another app.
Bug: 183705547
Test: regression on capture use cases
Change-Id: I2b6547eee1dcd840e06090f42f40beafa3facb46
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 7cdac30..20812bf 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -163,6 +163,33 @@
}
};
+// TODO b/182392769: use identity util
+/* static */
+media::permission::Identity AudioFlinger::checkIdentityPackage(
+ const media::permission::Identity& identity) {
+ Vector<String16> packages;
+ PermissionController{}.getPackagesForUid(identity.uid, packages);
+
+ Identity checkedIdentity = identity;
+ if (!identity.packageName.has_value() || identity.packageName.value().size() == 0) {
+ if (!packages.isEmpty()) {
+ checkedIdentity.packageName =
+ std::move(legacy2aidl_String16_string(packages[0]).value());
+ }
+ } else {
+ String16 opPackageLegacy = VALUE_OR_FATAL(
+ aidl2legacy_string_view_String16(identity.packageName.value_or("")));
+ if (std::find_if(packages.begin(), packages.end(),
+ [&opPackageLegacy](const auto& package) {
+ return opPackageLegacy == package; }) == packages.end()) {
+ ALOGW("The package name(%s) provided does not correspond to the uid %d",
+ identity.packageName.value_or("").c_str(), identity.uid);
+ checkedIdentity.packageName = std::optional<std::string>();
+ }
+ }
+ return checkedIdentity;
+}
+
// ----------------------------------------------------------------------------
std::string formatToString(audio_format_t format) {
@@ -2157,7 +2184,7 @@
&output.notificationFrameCount,
callingPid, adjIdentity, &output.flags,
input.clientInfo.clientTid,
- &lStatus, portId);
+ &lStatus, portId, input.maxSharedAudioHistoryMs);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (recordTrack == 0));
// lStatus == BAD_TYPE means FAST flag was rejected: request a new input from
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index a980752..c66ecb0 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -129,6 +129,9 @@
public:
static void instantiate() ANDROID_API;
+ static media::permission::Identity checkIdentityPackage(
+ const media::permission::Identity& identity);
+
status_t dump(int fd, const Vector<String16>& args) override;
// IAudioFlinger interface, in binder opcode order
@@ -673,6 +676,8 @@
virtual binder::Status setPreferredMicrophoneDirection(
int /*audio_microphone_direction_t*/ direction);
virtual binder::Status setPreferredMicrophoneFieldDimension(float zoom);
+ virtual binder::Status shareAudioHistory(const std::string& sharedAudioPackageName,
+ int64_t sharedAudioStartMs);
private:
const sp<RecordThread::RecordTrack> mRecordTrack;
@@ -978,6 +983,9 @@
std::vector<media::AudioVibratorInfo> mAudioVibratorInfos;
static inline constexpr const char *mMetricsId = AMEDIAMETRICS_KEY_AUDIO_FLINGER;
+
+ // Keep in sync with java definition in media/java/android/media/AudioRecord.java
+ static constexpr int32_t kMaxSharedAudioHistoryMs = 5000;
};
#undef INCLUDING_FROM_AUDIOFLINGER_H
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 5f248e1..b953c0b 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -69,7 +69,8 @@
const media::permission::Identity& identity,
audio_input_flags_t flags,
track_type type,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
+ int64_t startTimeMs = -1);
virtual ~RecordTrack();
virtual status_t initCheck() const;
@@ -107,6 +108,9 @@
status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
status_t setPreferredMicrophoneFieldDimension(float zoom);
+ status_t shareAudioHistory(const std::string& sharedAudioPackageName,
+ int64_t sharedAudioStartMs);
+ int64_t startTimeMs() { return mStartTimeMs; }
static bool checkServerLatencySupported(
audio_format_t format, audio_input_flags_t flags) {
@@ -146,8 +150,9 @@
bool mSilenced;
// used to enforce OP_RECORD_AUDIO
- uid_t mUid;
sp<OpRecordAudioMonitor> mOpRecordAudioMonitor;
+ std::string mSharedAudioPackageName = {};
+ int64_t mStartTimeMs = -1;
};
// playback track, used by PatchPanel
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 997f24a..6da4543 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -700,6 +700,13 @@
return sendConfigEvent_l(configEvent);
}
+void AudioFlinger::ThreadBase::sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs)
+{
+ ALOG_ASSERT(type() == RECORD, "sendResizeBufferConfigEvent_l() called on non record thread");
+ sp<ConfigEvent> configEvent =
+ (ConfigEvent *)new ResizeBufferConfigEvent(maxSharedAudioHistoryMs);
+ sendConfigEvent_l(configEvent);
+}
// post condition: mConfigEvents.isEmpty()
void AudioFlinger::ThreadBase::processConfigEvents_l()
@@ -758,6 +765,11 @@
(UpdateOutDevicesConfigEventData *)event->mData.get();
updateOutDevices(data->mOutDevices);
} break;
+ case CFG_EVENT_RESIZE_BUFFER: {
+ ResizeBufferConfigEventData *data =
+ (ResizeBufferConfigEventData *)event->mData.get();
+ resizeInputBuffer_l(data->mMaxSharedAudioHistoryMs);
+ } break;
default:
ALOG_ASSERT(false, "processConfigEvents_l() unknown event type %d", event->mType);
break;
@@ -1079,6 +1091,11 @@
ALOGE("%s should only be called in RecordThread", __func__);
}
+void AudioFlinger::ThreadBase::resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs __unused)
+{
+ ALOGE("%s should only be called in RecordThread", __func__);
+}
+
void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who __unused)
{
sp<ThreadBase> thread = mThread.promote();
@@ -7766,7 +7783,8 @@
audio_input_flags_t *flags,
pid_t tid,
status_t *status,
- audio_port_handle_t portId)
+ audio_port_handle_t portId,
+ int32_t maxSharedAudioHistoryMs)
{
size_t frameCount = *pFrameCount;
size_t notificationFrameCount = *pNotificationFrameCount;
@@ -7775,6 +7793,7 @@
audio_input_flags_t inputFlags = mInput->flags;
audio_input_flags_t requestedFlags = *flags;
uint32_t sampleRate;
+ Identity checkedIdentity = AudioFlinger::checkIdentityPackage(identity);
lStatus = initCheck();
if (lStatus != NO_ERROR) {
@@ -7788,6 +7807,23 @@
goto Exit;
}
+ if (maxSharedAudioHistoryMs != 0) {
+ if (!captureHotwordAllowed(checkedIdentity)) {
+ lStatus = PERMISSION_DENIED;
+ goto Exit;
+ }
+ //TODO: b/185972521 allow resampling buffer resizing on fast mixers by pausing
+ // the fast mixer thread while resizing the buffer in the normal thread
+ if (hasFastCapture()) {
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ if (maxSharedAudioHistoryMs < 0
+ || maxSharedAudioHistoryMs > AudioFlinger::kMaxSharedAudioHistoryMs) {
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ }
if (*pSampleRate == 0) {
*pSampleRate = mSampleRate;
}
@@ -7896,11 +7932,18 @@
{ // scope for mLock
Mutex::Autolock _l(mLock);
+ long startTimeMs = -1;
+ if (!mSharedAudioPackageName.empty()
+ && mSharedAudioPackageName == checkedIdentity.packageName
+ && mSharedAudioSessionId == sessionId
+ && captureHotwordAllowed(checkedIdentity)) {
+ startTimeMs = mSharedAudioStartMs;
+ }
track = new RecordTrack(this, client, attr, sampleRate,
format, channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, creatorPid,
- identity, *flags, TrackBase::TYPE_DEFAULT, portId);
+ checkedIdentity, *flags, TrackBase::TYPE_DEFAULT, portId, startTimeMs);
lStatus = track->initCheck();
if (lStatus != NO_ERROR) {
@@ -7916,6 +7959,11 @@
// so ask activity manager to do this on our behalf
sendPrioConfigEvent_l(callingPid, tid, kPriorityAudioApp, true /*forApp*/);
}
+
+ if (maxSharedAudioHistoryMs != 0) {
+ sendResizeBufferConfigEvent_l(maxSharedAudioHistoryMs);
+ }
+
}
lStatus = NO_ERROR;
@@ -8136,6 +8184,37 @@
return mInput->stream->setPreferredMicrophoneFieldDimension(zoom);
}
+status_t AudioFlinger::RecordThread::shareAudioHistory(
+ const std::string& sharedAudioPackageName, audio_session_t sharedSessionId,
+ int64_t sharedAudioStartMs) {
+ AutoMutex _l(mLock);
+ return shareAudioHistory_l(sharedAudioPackageName, sharedSessionId, sharedAudioStartMs);
+}
+
+status_t AudioFlinger::RecordThread::shareAudioHistory_l(
+ const std::string& sharedAudioPackageName, audio_session_t sharedSessionId,
+ int64_t sharedAudioStartMs) {
+ if (hasFastCapture()) {
+ return BAD_VALUE;
+ }
+ if ((hasAudioSession_l(sharedSessionId) & ThreadBase::TRACK_SESSION) == 0) {
+ return BAD_VALUE;
+ }
+ if (sharedAudioStartMs < 0 || sharedAudioStartMs * mSampleRate / 1000 > mRsmpInRear) {
+ return BAD_VALUE;
+ }
+
+ mSharedAudioPackageName = sharedAudioPackageName;
+ if (mSharedAudioPackageName.empty()) {
+ mSharedAudioSessionId = AUDIO_SESSION_NONE;
+ mSharedAudioStartMs = -1;
+ } else {
+ mSharedAudioSessionId = sharedSessionId;
+ mSharedAudioStartMs = sharedAudioStartMs;
+ }
+ return NO_ERROR;
+}
+
void AudioFlinger::RecordThread::updateMetadata_l()
{
if (mInput == nullptr || mInput->stream == nullptr ||
@@ -8167,6 +8246,7 @@
{
track->terminate();
track->mState = TrackBase::STOPPED;
+
// active tracks are removed by threadLoop()
if (mActiveTracks.indexOf(track) < 0) {
removeTrack_l(track);
@@ -8274,8 +8354,23 @@
{
sp<ThreadBase> threadBase = mRecordTrack->mThread.promote();
RecordThread *recordThread = (RecordThread *) threadBase.get();
- mRsmpInFront = recordThread->mRsmpInRear;
mRsmpInUnrel = 0;
+ const int32_t rear = recordThread->mRsmpInRear;
+ ssize_t deltaFrames = 0;
+ if (mRecordTrack->startTimeMs() >= 0) {
+ int32_t startFrames = mRecordTrack->startTimeMs() * recordThread->sampleRate() / 1000;
+ // start frame has to be in the past
+ //TODO: b/185972521 fix in case rear or startFrames wrap around
+ if (startFrames > rear) {
+ startFrames = rear;
+ }
+ deltaFrames = rear - startFrames;
+ // start frame cannot be further in the past than start of resampling buffer
+ if ((size_t) deltaFrames > recordThread->mRsmpInFrames) {
+ deltaFrames = recordThread->mRsmpInFrames;
+ }
+ }
+ mRsmpInFront = audio_utils::safe_sub_overflow(rear, static_cast<int32_t>(deltaFrames));
}
void AudioFlinger::RecordThread::ResamplerBufferProvider::sync(
@@ -8540,31 +8635,10 @@
ALOGV("%p RecordThread params: mChannelCount=%u, mFormat=%#x, mFrameSize=%zu, "
"mBufferSize=%zu, mFrameCount=%zu",
this, mChannelCount, mFormat, mFrameSize, mBufferSize, mFrameCount);
- // This is the formula for calculating the temporary buffer size.
- // With 7 HAL buffers, we can guarantee ability to down-sample the input by ratio of 6:1 to
- // 1 full output buffer, regardless of the alignment of the available input.
- // The value is somewhat arbitrary, and could probably be even larger.
- // A larger value should allow more old data to be read after a track calls start(),
- // without increasing latency.
- //
- // Note this is independent of the maximum downsampling ratio permitted for capture.
- mRsmpInFrames = mFrameCount * 7;
- mRsmpInFramesP2 = roundup(mRsmpInFrames);
- free(mRsmpInBuffer);
- mRsmpInBuffer = NULL;
- // TODO optimize audio capture buffer sizes ...
- // Here we calculate the size of the sliding buffer used as a source
- // for resampling. mRsmpInFramesP2 is currently roundup(mFrameCount * 7).
- // For current HAL frame counts, this is usually 2048 = 40 ms. It would
- // be better to have it derived from the pipe depth in the long term.
- // The current value is higher than necessary. However it should not add to latency.
-
- // Over-allocate beyond mRsmpInFramesP2 to permit a HAL read past end of buffer
- mRsmpInFramesOA = mRsmpInFramesP2 + mFrameCount - 1;
- (void)posix_memalign(&mRsmpInBuffer, 32, mRsmpInFramesOA * mFrameSize);
- // if posix_memalign fails, will segv here.
- memset(mRsmpInBuffer, 0, mRsmpInFramesOA * mFrameSize);
+ // mRsmpInFrames must be 0 before calling resizeInputBuffer_l for the first time
+ mRsmpInFrames = 0;
+ resizeInputBuffer_l();
// AudioRecord mSampleRate and mChannelCount are constant due to AudioRecord API constraints.
// But if thread's mSampleRate or mChannelCount changes, how will that affect active tracks?
@@ -8747,6 +8821,124 @@
}
}
+int32_t AudioFlinger::RecordThread::getOldestFront_l()
+{
+ if (mTracks.size() == 0) {
+ return 0;
+ }
+ //TODO: b/185972521 fix in case of wrap around on one track:
+ // want the max(rear - front) for all tracks.
+ int32_t front = INT_MAX;
+ for (size_t i = 0; i < mTracks.size(); i++) {
+ front = std::min(front, mTracks[i]->mResamplerBufferProvider->getFront());
+ }
+ // discard any audio past the buffer size
+ if (audio_utils::safe_add_overflow(front, (int32_t)mRsmpInFrames) < mRsmpInRear) {
+ front = audio_utils::safe_sub_overflow(mRsmpInRear, (int32_t)mRsmpInFrames);
+ }
+ return front;
+}
+
+void AudioFlinger::RecordThread::updateFronts_l(int32_t offset)
+{
+ if (offset == 0) {
+ return;
+ }
+ for (size_t i = 0; i < mTracks.size(); i++) {
+ int32_t front = mTracks[i]->mResamplerBufferProvider->getFront();
+ front = audio_utils::safe_sub_overflow(front, offset);
+ mTracks[i]->mResamplerBufferProvider->setFront(front);
+ }
+}
+
+void AudioFlinger::RecordThread::resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs)
+{
+ // This is the formula for calculating the temporary buffer size.
+ // With 7 HAL buffers, we can guarantee ability to down-sample the input by ratio of 6:1 to
+ // 1 full output buffer, regardless of the alignment of the available input.
+ // The value is somewhat arbitrary, and could probably be even larger.
+ // A larger value should allow more old data to be read after a track calls start(),
+ // without increasing latency.
+ //
+ // Note this is independent of the maximum downsampling ratio permitted for capture.
+ size_t minRsmpInFrames = mFrameCount * 7;
+
+ // maxSharedAudioHistoryMs != 0 indicates a request to possibly make some part of the audio
+ // capture history available to another client using the same session ID:
+ // dimension the resampler input buffer accordingly.
+
+ // Get oldest client read position: getOldestFront_l() must be called before altering
+ // mRsmpInRear, or mRsmpInFrames
+ int32_t previousFront = getOldestFront_l();
+ size_t previousRsmpInFramesP2 = mRsmpInFramesP2;
+ int32_t previousRear = mRsmpInRear;
+ mRsmpInRear = 0;
+
+ if (maxSharedAudioHistoryMs != 0) {
+ // resizeInputBuffer_l should never be called with a non zero shared history if the
+ // buffer was not already allocated
+ ALOG_ASSERT(mRsmpInBuffer != nullptr && mRsmpInFrames != 0,
+ "resizeInputBuffer_l() called with shared history and unallocated buffer");
+ size_t rsmpInFrames = (size_t)maxSharedAudioHistoryMs * mSampleRate / 1000;
+ // never reduce resampler input buffer size
+ if (rsmpInFrames < mRsmpInFrames) {
+ return;
+ }
+ mRsmpInFrames = rsmpInFrames;
+ }
+ // Note: mRsmpInFrames is 0 when called with maxSharedAudioHistoryMs equals to 0 so it is always
+ // initialized
+ if (mRsmpInFrames < minRsmpInFrames) {
+ mRsmpInFrames = minRsmpInFrames;
+ }
+ mRsmpInFramesP2 = roundup(mRsmpInFrames);
+
+ // TODO optimize audio capture buffer sizes ...
+ // Here we calculate the size of the sliding buffer used as a source
+ // for resampling. mRsmpInFramesP2 is currently roundup(mFrameCount * 7).
+ // For current HAL frame counts, this is usually 2048 = 40 ms. It would
+ // be better to have it derived from the pipe depth in the long term.
+ // The current value is higher than necessary. However it should not add to latency.
+
+ // Over-allocate beyond mRsmpInFramesP2 to permit a HAL read past end of buffer
+ mRsmpInFramesOA = mRsmpInFramesP2 + mFrameCount - 1;
+
+ void *rsmpInBuffer;
+ (void)posix_memalign(&rsmpInBuffer, 32, mRsmpInFramesOA * mFrameSize);
+ // if posix_memalign fails, will segv here.
+ memset(rsmpInBuffer, 0, mRsmpInFramesOA * mFrameSize);
+
+ // Copy audio history if any from old buffer before freeing it
+ if (previousRear != 0) {
+ ALOG_ASSERT(mRsmpInBuffer != nullptr,
+ "resizeInputBuffer_l() called with null buffer but frames already read from HAL");
+
+ ssize_t unread = audio_utils::safe_sub_overflow(previousRear, previousFront);
+ previousFront &= previousRsmpInFramesP2 - 1;
+ size_t part1 = previousRsmpInFramesP2 - previousFront;
+ if (part1 > (size_t) unread) {
+ part1 = unread;
+ }
+ if (part1 != 0) {
+ memcpy(rsmpInBuffer, (const uint8_t*)mRsmpInBuffer + previousFront * mFrameSize,
+ part1 * mFrameSize);
+ mRsmpInRear = part1;
+ part1 = unread - part1;
+ if (part1 != 0) {
+ memcpy((uint8_t*)rsmpInBuffer + mRsmpInRear * mFrameSize,
+ (const uint8_t*)mRsmpInBuffer, part1 * mFrameSize);
+ mRsmpInRear += part1;
+ }
+ }
+ // Update front for all clients according to new rear
+ updateFronts_l(audio_utils::safe_sub_overflow(previousRear, mRsmpInRear));
+ } else {
+ mRsmpInRear = 0;
+ }
+ free(mRsmpInBuffer);
+ mRsmpInBuffer = rsmpInBuffer;
+}
+
void AudioFlinger::RecordThread::addPatchTrack(const sp<PatchRecord>& record)
{
Mutex::Autolock _l(mLock);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index e63642b..03ed6fd 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -53,6 +53,7 @@
CFG_EVENT_CREATE_AUDIO_PATCH,
CFG_EVENT_RELEASE_AUDIO_PATCH,
CFG_EVENT_UPDATE_OUT_DEVICE,
+ CFG_EVENT_RESIZE_BUFFER
};
class ConfigEventData: public RefBase {
@@ -242,6 +243,28 @@
virtual ~UpdateOutDevicesConfigEvent();
};
+ class ResizeBufferConfigEventData : public ConfigEventData {
+ public:
+ explicit ResizeBufferConfigEventData(int32_t maxSharedAudioHistoryMs) :
+ mMaxSharedAudioHistoryMs(maxSharedAudioHistoryMs) {}
+
+ virtual void dump(char *buffer, size_t size) {
+ snprintf(buffer, size, "mMaxSharedAudioHistoryMs: %d", mMaxSharedAudioHistoryMs);
+ }
+
+ int32_t mMaxSharedAudioHistoryMs;
+ };
+
+ class ResizeBufferConfigEvent : public ConfigEvent {
+ public:
+ explicit ResizeBufferConfigEvent(int32_t maxSharedAudioHistoryMs) :
+ ConfigEvent(CFG_EVENT_RESIZE_BUFFER) {
+ mData = new ResizeBufferConfigEventData(maxSharedAudioHistoryMs);
+ }
+
+ virtual ~ResizeBufferConfigEvent() {}
+ };
+
class PMDeathRecipient : public IBinder::DeathRecipient {
public:
explicit PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
@@ -306,6 +329,7 @@
status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle);
status_t sendUpdateOutDeviceConfigEvent(
const DeviceDescriptorBaseVector& outDevices);
+ void sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs);
void processConfigEvents_l();
virtual void cacheParameters_l() = 0;
virtual status_t createAudioPatch_l(const struct audio_patch *patch,
@@ -314,6 +338,9 @@
virtual void updateOutDevices(const DeviceDescriptorBaseVector& outDevices);
virtual void toAudioPortConfig(struct audio_port_config *config) = 0;
+ virtual void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs = 0);
+
+
// see note at declaration of mStandby, mOutDevice and mInDevice
bool standby() const { return mStandby; }
@@ -1613,6 +1640,9 @@
// AudioBufferProvider interface
virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+
+ int32_t getFront() const { return mRsmpInFront; }
+ void setFront(int32_t front) { mRsmpInFront = front; }
private:
RecordTrack * const mRecordTrack;
size_t mRsmpInUnrel; // unreleased frames remaining from
@@ -1662,7 +1692,8 @@
audio_input_flags_t *flags,
pid_t tid,
status_t *status /*non-NULL*/,
- audio_port_handle_t portId);
+ audio_port_handle_t portId,
+ int32_t maxSharedAudioHistoryMs);
status_t start(RecordTrack* recordTrack,
AudioSystem::sync_event_t event,
@@ -1686,6 +1717,7 @@
audio_patch_handle_t *handle);
virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle);
void updateOutDevices(const DeviceDescriptorBaseVector& outDevices) override;
+ void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs = 0) override;
void addPatchTrack(const sp<PatchRecord>& record);
void deletePatchTrack(const sp<PatchRecord>& record);
@@ -1741,6 +1773,13 @@
&& inDeviceType() == mTimestampCorrectedDevice;
}
+ status_t shareAudioHistory(const std::string& sharedAudioPackageName,
+ audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
+ int64_t sharedAudioStartMs = -1);
+ status_t shareAudioHistory_l(const std::string& sharedAudioPackageName,
+ audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
+ int64_t sharedAudioStartMs = -1);
+
protected:
void dumpInternals_l(int fd, const Vector<String16>& args) override;
void dumpTracks_l(int fd, const Vector<String16>& args) override;
@@ -1754,6 +1793,9 @@
void checkBtNrec_l();
+ int32_t getOldestFront_l();
+ void updateFronts_l(int32_t offset);
+
AudioStreamIn *mInput;
Source *mSource;
SortedVector < sp<RecordTrack> > mTracks;
@@ -1819,6 +1861,10 @@
int64_t mFramesRead = 0; // continuous running counter.
DeviceDescriptorBaseVector mOutDevices;
+
+ std::string mSharedAudioPackageName = {};
+ long mSharedAudioStartMs = 0;
+ audio_session_t mSharedAudioSessionId = AUDIO_SESSION_NONE;
};
class MmapThread : public ThreadBase
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 21651af..6549236 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -525,31 +525,8 @@
return nullptr;
}
- // TODO b/182392769: use identity util
- std::optional<std::string> opPackageNameStr = identity.packageName;
- if (!identity.packageName.has_value()) {
- // If no package name is provided by the client, use the first associated with the uid
- if (!packages.isEmpty()) {
- opPackageNameStr =
- VALUE_OR_FATAL(legacy2aidl_String16_string(packages[0]));
- }
- } else {
- // If the provided package name is invalid, we force app ops denial by clearing the package
- // name passed to OpPlayAudioMonitor
- String16 opPackageLegacy = VALUE_OR_FATAL(
- aidl2legacy_string_view_String16(opPackageNameStr.value_or("")));
- if (std::find_if(packages.begin(), packages.end(),
- [&opPackageLegacy](const auto& package) {
- return opPackageLegacy == package; }) == packages.end()) {
- ALOGW("The package name(%s) provided does not correspond to the uid %d, "
- "force muting the track", opPackageNameStr.value().c_str(), uid);
- // Set null package name so hasOpPlayAudio will always return false.
- opPackageNameStr = std::optional<std::string>();
- }
- }
- Identity adjIdentity = identity;
- adjIdentity.packageName = opPackageNameStr;
- return new OpPlayAudioMonitor(adjIdentity, attr.usage, id);
+ Identity checkedIdentity = AudioFlinger::checkIdentityPackage(identity);
+ return new OpPlayAudioMonitor(checkedIdentity, attr.usage, id);
}
AudioFlinger::PlaybackThread::OpPlayAudioMonitor::OpPlayAudioMonitor(
@@ -2243,24 +2220,12 @@
return nullptr;
}
- if (!identity.packageName.has_value() || identity.packageName.value().size() == 0) {
- Vector<String16> packages;
- // no package name, happens with SL ES clients
- // query package manager to find one
- PermissionController permissionController;
- permissionController.getPackagesForUid(identity.uid, packages);
- if (packages.isEmpty()) {
- return nullptr;
- } else {
- Identity adjIdentity = identity;
- adjIdentity.packageName =
- VALUE_OR_FATAL(legacy2aidl_String16_string(packages[0]));
- ALOGV("using identity:%s", adjIdentity.toString().c_str());
- return new OpRecordAudioMonitor(adjIdentity);
- }
+ Identity checkedIdentity = AudioFlinger::checkIdentityPackage(identity);
+ if (!checkedIdentity.packageName.has_value()
+ || checkedIdentity.packageName.value().size() == 0) {
+ return nullptr;
}
-
- return new OpRecordAudioMonitor(identity);
+ return new OpRecordAudioMonitor(checkedIdentity);
}
AudioFlinger::RecordThread::OpRecordAudioMonitor::OpRecordAudioMonitor(
@@ -2386,6 +2351,12 @@
return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
}
+binder::Status AudioFlinger::RecordHandle::shareAudioHistory(
+ const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
+ return binderStatusFromStatusT(
+ mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
+}
+
// ----------------------------------------------------------------------------
#undef LOG_TAG
#define LOG_TAG "AF::RecordTrack"
@@ -2406,7 +2377,8 @@
const Identity& identity,
audio_input_flags_t flags,
track_type type,
- audio_port_handle_t portId)
+ audio_port_handle_t portId,
+ int64_t startTimeMs)
: TrackBase(thread, client, attr, sampleRate, format,
channelMask, frameCount, buffer, bufferSize, sessionId,
creatorPid,
@@ -2423,7 +2395,8 @@
mRecordBufferConverter(NULL),
mFlags(flags),
mSilenced(false),
- mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(identity, attr))
+ mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(identity, attr)),
+ mStartTimeMs(startTimeMs)
{
if (mCblk == NULL) {
return;
@@ -2533,6 +2506,9 @@
Mutex::Autolock _l(thread->mLock);
RecordThread *recordThread = (RecordThread *) thread.get();
priorState = mState;
+ if (!mSharedAudioPackageName.empty()) {
+ recordThread->shareAudioHistory_l("");
+ }
recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
}
// APM portid/client management done outside of lock.
@@ -2719,6 +2695,37 @@
}
}
+status_t AudioFlinger::RecordThread::RecordTrack::shareAudioHistory(
+ const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
+
+ const uid_t callingUid = IPCThreadState::self()->getCallingUid();
+ const pid_t callingPid = IPCThreadState::self()->getCallingPid();
+ if (callingUid != mUid || callingPid != mCreatorPid) {
+ return PERMISSION_DENIED;
+ }
+
+ Identity identity{};
+ identity.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
+ identity.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
+ if (!captureHotwordAllowed(identity)) {
+ return PERMISSION_DENIED;
+ }
+
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ RecordThread *recordThread = (RecordThread *)thread.get();
+ status_t status = recordThread->shareAudioHistory(
+ sharedAudioPackageName, mSessionId, sharedAudioStartMs);
+ if (status == NO_ERROR) {
+ mSharedAudioPackageName = sharedAudioPackageName;
+ }
+ return status;
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+
// ----------------------------------------------------------------------------
#undef LOG_TAG
#define LOG_TAG "AF::PatchRecord"