Merge "Conditional start the media.transcoding service." into sc-dev
diff --git a/apex/mediatranscoding.rc b/apex/mediatranscoding.rc
index ae9f8ba..24306a2 100644
--- a/apex/mediatranscoding.rc
+++ b/apex/mediatranscoding.rc
@@ -8,5 +8,4 @@
ioprio rt 4
# Restrict to little cores only with system-background cpuset.
writepid /dev/cpuset/system-background/tasks
- interface aidl media.transcoding
disabled
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index e2c8f8f..daa923e 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -127,7 +127,7 @@
if ((as == AUDIO_SOURCE_FM_TUNER
&& !(captureAudioOutputAllowed(mIdentity) || captureTunerAudioInputAllowed(mIdentity)))
- || !recordingAllowed(mIdentity)) {
+ || !recordingAllowed(mIdentity, (audio_source_t)as)) {
return PERMISSION_DENIED;
}
Mutex::Autolock lock(mLock);
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index e3931b1..214a174 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -67,7 +67,7 @@
return packages[0];
}
-static int32_t getOpForSource(audio_source_t source) {
+int32_t getOpForSource(audio_source_t source) {
switch (source) {
case AUDIO_SOURCE_HOTWORD:
return AppOpsManager::OP_RECORD_AUDIO_HOTWORD;
@@ -133,8 +133,8 @@
return true;
}
-bool recordingAllowed(const Identity& identity) {
- return checkRecordingInternal(identity, String16(), /*start*/ false, AUDIO_SOURCE_DEFAULT);
+bool recordingAllowed(const Identity& identity, audio_source_t source) {
+ return checkRecordingInternal(identity, String16(), /*start*/ false, source);
}
bool startRecording(const Identity& identity, const String16& msg, audio_source_t source) {
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 6e75746..e7132b8 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -80,7 +80,8 @@
}
}
-bool recordingAllowed(const media::permission::Identity& identity);
+bool recordingAllowed(const media::permission::Identity& identity,
+ audio_source_t source = AUDIO_SOURCE_DEFAULT);
bool startRecording(const media::permission::Identity& identity,
const String16& msg, audio_source_t source);
void finishRecording(const media::permission::Identity& identity, audio_source_t source);
@@ -98,6 +99,7 @@
bool modifyPhoneStateAllowed(const media::permission::Identity& identity);
bool bypassInterruptionPolicyAllowed(const media::permission::Identity& identity);
void purgePermissionCache();
+int32_t getOpForSource(audio_source_t source);
media::permission::Identity getCallingIdentity();
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 2436248..0af4c7b 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -148,14 +148,6 @@
void setFinalVolume(float volume);
float getFinalVolume() const { return mFinalVolume; }
- /** @return true if the track has changed (metadata or volume) since
- * the last time this function was called,
- * true if this function was never called since the track creation,
- * false otherwise.
- * Thread safe.
- */
- bool readAndClearHasChanged() { return !mChangeNotified.test_and_set(); }
-
using SourceMetadatas = std::vector<playback_track_metadata_v7_t>;
using MetadataInserter = std::back_insert_iterator<SourceMetadatas>;
/** Copy the track metadata in the provided iterator. Thread safe. */
@@ -234,8 +226,6 @@
bool presentationComplete(int64_t framesWritten, size_t audioHalFrames);
void signalClientFlag(int32_t flag);
- /** Set that a metadata has changed and needs to be notified to backend. Thread safe. */
- void setMetadataHasChanged() { mChangeNotified.clear(); }
public:
void triggerEvents(AudioSystem::sync_event_t type);
virtual void invalidate();
@@ -320,8 +310,6 @@
bool mFlushHwPending; // track requests for thread flush
bool mPauseHwPending = false; // direct/offload track request for thread pause
audio_output_flags_t mFlags;
- // If the last track change was notified to the client with readAndClearHasChanged
- std::atomic_flag mChangeNotified = ATOMIC_FLAG_INIT;
TeePatches mTeePatches;
}; // end of Track
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 451c198..a1c2de7 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -19,17 +19,18 @@
#error This header file should only be included from AudioFlinger.h
#endif
-// Checks and monitors OP_RECORD_AUDIO
+// Checks and monitors app ops for audio record
class OpRecordAudioMonitor : public RefBase {
public:
~OpRecordAudioMonitor() override;
- bool hasOpRecordAudio() const;
+ bool hasOp() const;
+ int32_t getOp() const { return mAppOp; }
static sp<OpRecordAudioMonitor> createIfNeeded
(const media::permission::Identity& identity, const audio_attributes_t& attr);
private:
- explicit OpRecordAudioMonitor(const media::permission::Identity& identity);
+ OpRecordAudioMonitor(const media::permission::Identity& identity, int32_t appOp);
void onFirstRef() override;
AppOpsManager mAppOpsManager;
@@ -44,12 +45,13 @@
};
sp<RecordAudioOpCallback> mOpCallback;
- // called by RecordAudioOpCallback when OP_RECORD_AUDIO is updated in AppOp callback
- // and in onFirstRef()
- void checkRecordAudio();
+ // called by RecordAudioOpCallback when the app op for this OpRecordAudioMonitor is updated
+ // in AppOp callback and in onFirstRef()
+ void checkOp();
- std::atomic_bool mHasOpRecordAudio;
+ std::atomic_bool mHasOp;
const media::permission::Identity mIdentity;
+ const int32_t mAppOp;
};
// record track
@@ -149,7 +151,7 @@
bool mSilenced;
- // used to enforce OP_RECORD_AUDIO
+ // used to enforce the audio record app op corresponding to this track's audio source
sp<OpRecordAudioMonitor> mOpRecordAudioMonitor;
std::string mSharedAudioPackageName = {};
int32_t mStartFrames = -1;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index d42a6ca..d878611 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1798,8 +1798,14 @@
template <typename T>
bool AudioFlinger::ThreadBase::ActiveTracks<T>::readAndClearHasChanged() {
- const bool hasChanged = mHasChanged;
+ bool hasChanged = mHasChanged;
mHasChanged = false;
+
+ for (const sp<T> &track : mActiveTracks) {
+ // Do not short-circuit as all hasChanged states must be reset
+ // as all the metadata are going to be sent
+ hasChanged |= track->readAndClearHasChanged();
+ }
return hasChanged;
}
@@ -1986,7 +1992,7 @@
void AudioFlinger::PlaybackThread::onFirstRef()
{
- if (mOutput == nullptr || mOutput->stream == nullptr) {
+ if (!isStreamInitialized()) {
ALOGE("The stream is not open yet"); // This should not happen.
} else {
// setEventCallback will need a strong pointer as a parameter. Calling it
@@ -2695,7 +2701,7 @@
status_t AudioFlinger::DirectOutputThread::selectPresentation(int presentationId, int programId) {
Mutex::Autolock _l(mLock);
- if (mOutput == nullptr || mOutput->stream == nullptr) {
+ if (!isStreamInitialized()) {
return NO_INIT;
}
return mOutput->stream->selectPresentation(presentationId, programId);
@@ -2992,16 +2998,7 @@
void AudioFlinger::PlaybackThread::updateMetadata_l()
{
- if (mOutput == nullptr || mOutput->stream == nullptr ) {
- return; // That should not happen
- }
- bool hasChanged = mActiveTracks.readAndClearHasChanged();
- for (const sp<Track> &track : mActiveTracks) {
- // Do not short-circuit as all hasChanged states must be reset
- // as all the metadata are going to be sent
- hasChanged |= track->readAndClearHasChanged();
- }
- if (!hasChanged) {
+ if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
return; // nothing to do
}
StreamOutHalInterface::SourceMetadata metadata;
@@ -8186,7 +8183,7 @@
{
ALOGV("RecordThread::getActiveMicrophones");
AutoMutex _l(mLock);
- if (mInput == nullptr || mInput->stream == nullptr) {
+ if (!isStreamInitialized()) {
return NO_INIT;
}
status_t status = mInput->stream->getActiveMicrophones(activeMicrophones);
@@ -8198,7 +8195,7 @@
{
ALOGV("setPreferredMicrophoneDirection(%d)", direction);
AutoMutex _l(mLock);
- if (mInput == nullptr || mInput->stream == nullptr) {
+ if (!isStreamInitialized()) {
return NO_INIT;
}
return mInput->stream->setPreferredMicrophoneDirection(direction);
@@ -8208,7 +8205,7 @@
{
ALOGV("setPreferredMicrophoneFieldDimension(%f)", zoom);
AutoMutex _l(mLock);
- if (mInput == nullptr || mInput->stream == nullptr) {
+ if (!isStreamInitialized()) {
return NO_INIT;
}
return mInput->stream->setPreferredMicrophoneFieldDimension(zoom);
@@ -8259,9 +8256,8 @@
void AudioFlinger::RecordThread::updateMetadata_l()
{
- if (mInput == nullptr || mInput->stream == nullptr ||
- !mActiveTracks.readAndClearHasChanged()) {
- return;
+ if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
+ return; // nothing to do
}
StreamInHalInterface::SinkMetadata metadata;
for (const sp<RecordTrack> &track : mActiveTracks) {
@@ -9959,14 +9955,16 @@
}
}
}
+ for (const sp<MmapTrack> &track : mActiveTracks) {
+ track->setMetadataHasChanged();
+ }
}
}
void AudioFlinger::MmapPlaybackThread::updateMetadata_l()
{
- if (mOutput == nullptr || mOutput->stream == nullptr ||
- !mActiveTracks.readAndClearHasChanged()) {
- return;
+ if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
+ return; // nothing to do
}
StreamOutHalInterface::SourceMetadata metadata;
for (const sp<MmapTrack> &track : mActiveTracks) {
@@ -10093,9 +10091,8 @@
void AudioFlinger::MmapCaptureThread::updateMetadata_l()
{
- if (mInput == nullptr || mInput->stream == nullptr ||
- !mActiveTracks.readAndClearHasChanged()) {
- return;
+ if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
+ return; // nothing to do
}
StreamInHalInterface::SinkMetadata metadata;
for (const sp<MmapTrack> &track : mActiveTracks) {
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 65db986..17acb16 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -527,6 +527,8 @@
}
}
+ virtual bool isStreamInitialized() = 0;
+
protected:
// entry describing an effect being suspended in mSuspendedSessions keyed vector
@@ -741,7 +743,9 @@
void updatePowerState(sp<ThreadBase> thread, bool force = false);
/** @return true if one or move active tracks was added or removed since the
- * last time this function was called or the vector was created. */
+ * last time this function was called or the vector was created.
+ * true if volume of one of active tracks was changed.
+ */
bool readAndClearHasChanged();
private:
@@ -993,6 +997,10 @@
&& outDeviceTypes().count(mTimestampCorrectedDevice) != 0;
}
+ virtual bool isStreamInitialized() {
+ return !(mOutput == nullptr || mOutput->stream == nullptr);
+ }
+
audio_channel_mask_t hapticChannelMask() const override {
return mHapticChannelMask;
}
@@ -1780,6 +1788,10 @@
audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
int64_t sharedAudioStartMs = -1);
+ virtual bool isStreamInitialized() {
+ return !(mInput == nullptr || mInput->stream == nullptr);
+ }
+
protected:
void dumpInternals_l(int fd, const Vector<String16>& args) override;
void dumpTracks_l(int fd, const Vector<String16>& args) override;
@@ -1949,6 +1961,8 @@
virtual void setRecordSilenced(audio_port_handle_t portId __unused,
bool silenced __unused) {}
+ virtual bool isStreamInitialized() { return false; }
+
protected:
void dumpInternals_l(int fd, const Vector<String16>& args) override;
void dumpTracks_l(int fd, const Vector<String16>& args) override;
@@ -2011,6 +2025,10 @@
status_t getExternalPosition(uint64_t *position, int64_t *timeNanos) override;
+ virtual bool isStreamInitialized() {
+ return !(mOutput == nullptr || mOutput->stream == nullptr);
+ }
+
protected:
void dumpInternals_l(int fd, const Vector<String16>& args) override;
@@ -2043,6 +2061,10 @@
status_t getExternalPosition(uint64_t *position, int64_t *timeNanos) override;
+ virtual bool isStreamInitialized() {
+ return !(mInput == nullptr || mInput->stream == nullptr);
+ }
+
protected:
AudioStreamIn* mInput;
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 38dab5b..92f129c 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -255,6 +255,17 @@
audio_channel_mask_t channelMask() const { return mChannelMask; }
+ /** @return true if the track has changed (metadata or volume) since
+ * the last time this function was called,
+ * true if this function was never called since the track creation,
+ * false otherwise.
+ * Thread safe.
+ */
+ bool readAndClearHasChanged() { return !mChangeNotified.test_and_set(); }
+
+ /** Set that a metadata has changed and needs to be notified to backend. Thread safe. */
+ void setMetadataHasChanged() { mChangeNotified.clear(); }
+
protected:
DISALLOW_COPY_AND_ASSIGN(TrackBase);
@@ -391,6 +402,9 @@
std::atomic<FrameTime> mKernelFrameTime{}; // last frame time on kernel side.
const pid_t mCreatorPid; // can be different from mclient->pid() for instance
// when created by NuPlayer on behalf of a client
+
+ // If the last track change was notified to the client with readAndClearHasChanged
+ std::atomic_flag mChangeNotified = ATOMIC_FLAG_INIT;
};
// PatchProxyBufferProvider interface is implemented by PatchTrack and PatchRecord.
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 3258689..8be7c86 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -2215,7 +2215,7 @@
return nullptr;
}
- // Capturing from FM TUNER output is not controlled by OP_RECORD_AUDIO
+ // Capturing from FM TUNER output is not controlled by an app op
// because it does not affect users privacy as does capturing from an actual microphone.
if (attr.source == AUDIO_SOURCE_FM_TUNER) {
ALOGV("not muting FM TUNER capture for uid %d", identity.uid);
@@ -2227,12 +2227,12 @@
|| checkedIdentity.packageName.value().size() == 0) {
return nullptr;
}
- return new OpRecordAudioMonitor(checkedIdentity);
+ return new OpRecordAudioMonitor(checkedIdentity, getOpForSource(attr.source));
}
AudioFlinger::RecordThread::OpRecordAudioMonitor::OpRecordAudioMonitor(
- const Identity& identity)
- : mHasOpRecordAudio(true), mIdentity(identity)
+ const Identity& identity, int32_t appOp)
+ : mHasOp(true), mIdentity(identity), mAppOp(appOp)
{
}
@@ -2246,36 +2246,36 @@
void AudioFlinger::RecordThread::OpRecordAudioMonitor::onFirstRef()
{
- checkRecordAudio();
+ checkOp();
mOpCallback = new RecordAudioOpCallback(this);
- ALOGV("start watching OP_RECORD_AUDIO for %s", mIdentity.toString().c_str());
- mAppOpsManager.startWatchingMode(AppOpsManager::OP_RECORD_AUDIO,
+ ALOGV("start watching op %d for %s", mAppOp, mIdentity.toString().c_str());
+ mAppOpsManager.startWatchingMode(mAppOp,
VALUE_OR_FATAL(aidl2legacy_string_view_String16(mIdentity.packageName.value_or(""))),
mOpCallback);
}
-bool AudioFlinger::RecordThread::OpRecordAudioMonitor::hasOpRecordAudio() const {
- return mHasOpRecordAudio.load();
+bool AudioFlinger::RecordThread::OpRecordAudioMonitor::hasOp() const {
+ return mHasOp.load();
}
-// Called by RecordAudioOpCallback when OP_RECORD_AUDIO is updated in AppOp callback
-// and in onFirstRef()
+// Called by RecordAudioOpCallback when the app op corresponding to this OpRecordAudioMonitor
+// is updated in AppOp callback and in onFirstRef()
// Note this method is never called (and never to be) for audio server / root track
// due to the UID in createIfNeeded(). As a result for those record track, it's:
// - not called from constructor,
// - not called from RecordAudioOpCallback because the callback is not installed in this case
-void AudioFlinger::RecordThread::OpRecordAudioMonitor::checkRecordAudio()
+void AudioFlinger::RecordThread::OpRecordAudioMonitor::checkOp()
{
- const int32_t mode = mAppOpsManager.checkOp(AppOpsManager::OP_RECORD_AUDIO,
+ const int32_t mode = mAppOpsManager.checkOp(mAppOp,
mIdentity.uid, VALUE_OR_FATAL(aidl2legacy_string_view_String16(
mIdentity.packageName.value_or(""))));
const bool hasIt = (mode == AppOpsManager::MODE_ALLOWED);
// verbose logging only log when appOp changed
- ALOGI_IF(hasIt != mHasOpRecordAudio.load(),
- "OP_RECORD_AUDIO missing, %ssilencing record %s",
- hasIt ? "un" : "", mIdentity.toString().c_str());
- mHasOpRecordAudio.store(hasIt);
+ ALOGI_IF(hasIt != mHasOp.load(),
+ "App op %d missing, %ssilencing record %s",
+ mAppOp, hasIt ? "un" : "", mIdentity.toString().c_str());
+ mHasOp.store(hasIt);
}
@@ -2286,12 +2286,12 @@
void AudioFlinger::RecordThread::OpRecordAudioMonitor::RecordAudioOpCallback::opChanged(int32_t op,
const String16& packageName) {
UNUSED(packageName);
- if (op != AppOpsManager::OP_RECORD_AUDIO) {
- return;
- }
sp<OpRecordAudioMonitor> monitor = mMonitor.promote();
if (monitor != NULL) {
- monitor->checkRecordAudio();
+ if (op != monitor->getOp()) {
+ return;
+ }
+ monitor->checkOp();
}
}
@@ -2661,7 +2661,7 @@
return true;
}
// The monitor is only created for record tracks that can be silenced.
- return mOpRecordAudioMonitor ? !mOpRecordAudioMonitor->hasOpRecordAudio() : false;
+ return mOpRecordAudioMonitor ? !mOpRecordAudioMonitor->hasOp() : false;
}
status_t AudioFlinger::RecordThread::RecordTrack::getActiveMicrophones(
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 551013f..b9c715e 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -580,7 +580,7 @@
// Capturing from FM_TUNER source is controlled by captureTunerAudioInputAllowed() and
// captureAudioOutputAllowed() (deprecated) as this does not affect users privacy
// as does capturing from an actual microphone.
- if (!(recordingAllowed(adjIdentity) || attr.source == AUDIO_SOURCE_FM_TUNER)) {
+ if (!(recordingAllowed(adjIdentity, attr.source) || attr.source == AUDIO_SOURCE_FM_TUNER)) {
ALOGE("%s permission denied: recording not allowed for %s",
__func__, adjIdentity.toString().c_str());
return binderStatusFromStatusT(PERMISSION_DENIED);
diff --git a/services/mediatranscoding/MediaTranscodingService.cpp b/services/mediatranscoding/MediaTranscodingService.cpp
index b80fe57..8b64134 100644
--- a/services/mediatranscoding/MediaTranscodingService.cpp
+++ b/services/mediatranscoding/MediaTranscodingService.cpp
@@ -131,10 +131,10 @@
void MediaTranscodingService::instantiate() {
std::shared_ptr<MediaTranscodingService> service =
::ndk::SharedRefBase::make<MediaTranscodingService>();
- if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
- // Once service is started, we want it to stay even is client side perished.
- AServiceManager_forceLazyServicesPersist(true /*persist*/);
- (void)AServiceManager_registerLazyService(service->asBinder().get(), getServiceName());
+ binder_status_t status =
+ AServiceManager_addService(service->asBinder().get(), getServiceName());
+ if (status != STATUS_OK) {
+ return;
}
}
diff --git a/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h b/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
index 0cb2fad..20e4bfb 100644
--- a/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
+++ b/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
@@ -481,7 +481,7 @@
// Need thread pool to receive callbacks, otherwise oneway callbacks are
// silently ignored.
ABinderProcess_startThreadPool();
- ::ndk::SpAIBinder binder(AServiceManager_waitForService("media.transcoding"));
+ ::ndk::SpAIBinder binder(AServiceManager_getService("media.transcoding"));
mService = IMediaTranscodingService::fromBinder(binder);
if (mService == nullptr) {
ALOGE("Failed to connect to the media.trascoding service.");