audio policy: implement uid state management for capture
Receive app state updates from ActivityManager and use it to implement
concurrent capture policy.
Bug: 111438757
Test: Manual test with solotester app concurrently with Camera, Duo and
Assistant
Change-Id: I979ad4ecc8b926abb64e1b321b43bd7bd442a8f1
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 018d9e3..78dbf5f 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -340,14 +340,41 @@
return NO_ERROR;
}
-void AudioPolicyService::setAppState(uid_t uid, app_state_t state)
+void AudioPolicyService::updateUidStates()
{
- {
- Mutex::Autolock _l(mLock);
- if (mAudioPolicyManager) {
- AutoCallerClear acc;
- mAudioPolicyManager->setAppState(uid, state);
- }
+ Mutex::Autolock _l(mLock);
+ updateUidStates_l();
+}
+
+void AudioPolicyService::updateUidStates_l()
+{
+ //TODO: implement real concurrent capture policy: for now just apply each app state directly
+ for (size_t i =0; i < mAudioRecordClients.size(); i++) {
+ sp<AudioRecordClient> current = mAudioRecordClients[i];
+ if (!current->active) continue;
+ setAppState_l(current->uid, apmStatFromAmState(mUidPolicy->getUidState(current->uid)));
+ }
+}
+
+/* static */
+app_state_t AudioPolicyService::apmStatFromAmState(int amState) {
+ switch (amState) {
+ case ActivityManager::PROCESS_STATE_UNKNOWN:
+ return APP_STATE_IDLE;
+ case ActivityManager::PROCESS_STATE_TOP:
+ return APP_STATE_TOP;
+ default:
+ break;
+ }
+ return APP_STATE_FOREGROUND;
+}
+
+void AudioPolicyService::setAppState_l(uid_t uid, app_state_t state)
+{
+ AutoCallerClear acc;
+
+ if (mAudioPolicyManager) {
+ mAudioPolicyManager->setAppState(uid, state);
}
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af) {
@@ -511,7 +538,8 @@
ActivityManager am;
am.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
| ActivityManager::UID_OBSERVER_IDLE
- | ActivityManager::UID_OBSERVER_ACTIVE,
+ | ActivityManager::UID_OBSERVER_ACTIVE
+ | ActivityManager::UID_OBSERVER_PROCSTATE,
ActivityManager::PROCESS_STATE_UNKNOWN,
String16("audioserver"));
status_t res = am.linkToDeath(this);
@@ -538,8 +566,7 @@
mObserverRegistered = false;
}
-bool AudioPolicyService::UidPolicy::isUidActive(uid_t uid) {
- if (isServiceUid(uid)) return true;
+void AudioPolicyService::UidPolicy::checkRegistered() {
bool needToReregister = false;
{
Mutex::Autolock _l(mLock);
@@ -549,91 +576,157 @@
// Looks like ActivityManager has died previously, attempt to re-register.
registerSelf();
}
+}
+
+bool AudioPolicyService::UidPolicy::isUidActive(uid_t uid) {
+ if (isServiceUid(uid)) return true;
+ checkRegistered();
{
Mutex::Autolock _l(mLock);
auto overrideIter = mOverrideUids.find(uid);
if (overrideIter != mOverrideUids.end()) {
- return overrideIter->second;
+ return overrideIter->second.first;
}
// In an absense of the ActivityManager, assume everything to be active.
if (!mObserverRegistered) return true;
auto cacheIter = mCachedUids.find(uid);
if (cacheIter != mCachedUids.end()) {
- return cacheIter->second;
+ return cacheIter->second.first;
}
}
ActivityManager am;
bool active = am.isUidActive(uid, String16("audioserver"));
{
Mutex::Autolock _l(mLock);
- mCachedUids.insert(std::pair<uid_t, bool>(uid, active));
+ mCachedUids.insert(std::pair<uid_t,
+ std::pair<bool, int>>(uid, std::pair<bool, int>(active,
+ ActivityManager::PROCESS_STATE_UNKNOWN)));
}
return active;
}
+int AudioPolicyService::UidPolicy::getUidState(uid_t uid) {
+ if (isServiceUid(uid)) {
+ return ActivityManager::PROCESS_STATE_TOP;
+ }
+ checkRegistered();
+ {
+ Mutex::Autolock _l(mLock);
+ auto overrideIter = mOverrideUids.find(uid);
+ if (overrideIter != mOverrideUids.end()) {
+ if (overrideIter->second.first) {
+ if (overrideIter->second.second != ActivityManager::PROCESS_STATE_UNKNOWN) {
+ return overrideIter->second.second;
+ } else {
+ auto cacheIter = mCachedUids.find(uid);
+ if (cacheIter != mCachedUids.end()) {
+ return cacheIter->second.second;
+ }
+ }
+ }
+ return ActivityManager::PROCESS_STATE_UNKNOWN;
+ }
+ // In an absense of the ActivityManager, assume everything to be active.
+ if (!mObserverRegistered) {
+ return ActivityManager::PROCESS_STATE_TOP;
+ }
+ auto cacheIter = mCachedUids.find(uid);
+ if (cacheIter != mCachedUids.end()) {
+ if (cacheIter->second.first) {
+ return cacheIter->second.second;
+ } else {
+ return ActivityManager::PROCESS_STATE_UNKNOWN;
+ }
+ }
+ }
+ ActivityManager am;
+ bool active = am.isUidActive(uid, String16("audioserver"));
+ int state = ActivityManager::PROCESS_STATE_UNKNOWN;
+ if (active) {
+ state = am.getUidProcessState(uid, String16("audioserver"));
+ }
+ {
+ Mutex::Autolock _l(mLock);
+ mCachedUids.insert(std::pair<uid_t,
+ std::pair<bool, int>>(uid, std::pair<bool, int>(active, state)));
+ }
+ return state;
+}
+
void AudioPolicyService::UidPolicy::onUidActive(uid_t uid) {
- updateUidCache(uid, true, true);
+ updateUid(&mCachedUids, uid, true, ActivityManager::PROCESS_STATE_UNKNOWN, true);
}
void AudioPolicyService::UidPolicy::onUidGone(uid_t uid, __unused bool disabled) {
- updateUidCache(uid, false, false);
+ updateUid(&mCachedUids, uid, false, ActivityManager::PROCESS_STATE_UNKNOWN, false);
}
void AudioPolicyService::UidPolicy::onUidIdle(uid_t uid, __unused bool disabled) {
- updateUidCache(uid, false, true);
+ updateUid(&mCachedUids, uid, false, ActivityManager::PROCESS_STATE_UNKNOWN, true);
}
-void AudioPolicyService::UidPolicy::notifyService(uid_t uid, bool active) {
- sp<AudioPolicyService> service = mService.promote();
- if (service != nullptr) {
- service->setAppState(uid, active ?
- APP_STATE_FOREGROUND :
- APP_STATE_IDLE);
+void AudioPolicyService::UidPolicy::onUidStateChanged(uid_t uid,
+ int32_t procState,
+ int64_t procStateSeq __unused) {
+ if (procState != ActivityManager::PROCESS_STATE_UNKNOWN) {
+ updateUid(&mCachedUids, uid, true, procState, true);
}
}
void AudioPolicyService::UidPolicy::updateOverrideUid(uid_t uid, bool active, bool insert) {
- if (isServiceUid(uid)) return;
- bool wasOverridden = false, wasActive = false;
- {
- Mutex::Autolock _l(mLock);
- updateUidLocked(&mOverrideUids, uid, active, insert, &wasOverridden, &wasActive);
- }
- if (!wasOverridden && insert) {
- notifyService(uid, active); // Started to override.
- } else if (wasOverridden && !insert) {
- notifyService(uid, isUidActive(uid)); // Override ceased, notify with ground truth.
- } else if (wasActive != active) {
- notifyService(uid, active); // Override updated.
+ updateUid(&mOverrideUids, uid, active, ActivityManager::PROCESS_STATE_UNKNOWN, insert);
+}
+
+void AudioPolicyService::UidPolicy::notifyService() {
+ sp<AudioPolicyService> service = mService.promote();
+ if (service != nullptr) {
+ service->updateUidStates();
}
}
-void AudioPolicyService::UidPolicy::updateUidCache(uid_t uid, bool active, bool insert) {
- if (isServiceUid(uid)) return;
- bool wasActive = false;
+void AudioPolicyService::UidPolicy::updateUid(std::unordered_map<uid_t,
+ std::pair<bool, int>> *uids,
+ uid_t uid,
+ bool active,
+ int state,
+ bool insert) {
+ if (isServiceUid(uid)) {
+ return;
+ }
+ bool wasActive = isUidActive(uid);
+ int previousState = getUidState(uid);
{
Mutex::Autolock _l(mLock);
- updateUidLocked(&mCachedUids, uid, active, insert, nullptr, &wasActive);
- // Do not notify service if currently overridden.
- if (mOverrideUids.find(uid) != mOverrideUids.end()) return;
+ updateUidLocked(uids, uid, active, state, insert);
}
- bool nowActive = active && insert;
- if (wasActive != nowActive) notifyService(uid, nowActive);
+ if (wasActive != isUidActive(uid) || state != previousState) {
+ notifyService();
+ }
}
-void AudioPolicyService::UidPolicy::updateUidLocked(std::unordered_map<uid_t, bool> *uids,
- uid_t uid, bool active, bool insert, bool *wasThere, bool *wasActive) {
+void AudioPolicyService::UidPolicy::updateUidLocked(std::unordered_map<uid_t,
+ std::pair<bool, int>> *uids,
+ uid_t uid,
+ bool active,
+ int state,
+ bool insert) {
auto it = uids->find(uid);
if (it != uids->end()) {
- if (wasThere != nullptr) *wasThere = true;
- if (wasActive != nullptr) *wasActive = it->second;
if (insert) {
- it->second = active;
+ if (state == ActivityManager::PROCESS_STATE_UNKNOWN) {
+ it->second.first = active;
+ }
+ if (it->second.first) {
+ it->second.second = state;
+ } else {
+ it->second.second = ActivityManager::PROCESS_STATE_UNKNOWN;
+ }
} else {
uids->erase(it);
}
- } else if (insert) {
- uids->insert(std::pair<uid_t, bool>(uid, active));
+ } else if (insert && (state == ActivityManager::PROCESS_STATE_UNKNOWN)) {
+ uids->insert(std::pair<uid_t, std::pair<bool, int>>(uid,
+ std::pair<bool, int>(active, state)));
}
}