Merge changes from topic 'b/62420820' into oc-dr1-dev
* changes:
Camera: Device 3: Ignore buffer limits when clearing request queue
Camera: fix status tracker race condition
diff --git a/media/libaaudio/src/utility/AAudioUtilities.h b/media/libaaudio/src/utility/AAudioUtilities.h
index f894bc0..efd663d 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.h
+++ b/media/libaaudio/src/utility/AAudioUtilities.h
@@ -17,6 +17,8 @@
#ifndef UTILITY_AAUDIO_UTILITIES_H
#define UTILITY_AAUDIO_UTILITIES_H
+#include <algorithm>
+#include <functional>
#include <stdint.h>
#include <sys/types.h>
@@ -211,4 +213,27 @@
*/
int32_t AAudioProperty_getHardwareBurstMinMicros();
+/**
+ * Try a function f until it returns true.
+ *
+ * The function is always called at least once.
+ *
+ * @param f the function to evaluate, which returns a bool.
+ * @param times the number of times to evaluate f.
+ * @param sleepMs the sleep time per check of f, if greater than 0.
+ * @return true if f() eventually returns true.
+ */
+static inline bool AAudio_tryUntilTrue(
+ std::function<bool()> f, int times, int sleepMs) {
+ static const useconds_t US_PER_MS = 1000;
+
+ sleepMs = std::max(sleepMs, 0);
+ for (;;) {
+ if (f()) return true;
+ if (times <= 1) return false;
+ --times;
+ usleep(sleepMs * US_PER_MS);
+ }
+}
+
#endif //UTILITY_AAUDIO_UTILITIES_H
diff --git a/media/libaaudio/src/utility/HandleTracker.cpp b/media/libaaudio/src/utility/HandleTracker.cpp
index f957234..d4202db 100644
--- a/media/libaaudio/src/utility/HandleTracker.cpp
+++ b/media/libaaudio/src/utility/HandleTracker.cpp
@@ -20,11 +20,15 @@
#include <utils/Log.h>
#include <assert.h>
+#include <functional>
+#include <iomanip>
#include <new>
+#include <sstream>
#include <stdint.h>
#include <utils/Mutex.h>
#include <aaudio/AAudio.h>
+#include "AAudioUtilities.h"
#include "HandleTracker.h"
using android::Mutex;
@@ -93,6 +97,46 @@
return mHandleAddresses != nullptr;
}
+
+
+std::string HandleTracker::dump() const {
+ if (!isInitialized()) {
+ return "HandleTracker is not initialized\n";
+ }
+
+ std::stringstream result;
+ const bool isLocked = AAudio_tryUntilTrue(
+ [this]()->bool { return mLock.tryLock(); } /* f */,
+ 50 /* times */,
+ 20 /* sleepMs */);
+ if (!isLocked) {
+ result << "HandleTracker may be deadlocked\n";
+ }
+
+ result << "Handles:\n";
+ // atLineStart() can be changed to support an arbitrary line breaking algorithm;
+ // it should return true when a new line starts.
+ // For simplicity, we will use a constant 16 items per line.
+ const auto atLineStart = [](int index) -> bool {
+ // Magic constant of 0xf used for mask to detect start every 16 items.
+ return (index & 0xf) == 0; };
+ const auto atLineEnd = [this, &atLineStart](int index) -> bool {
+ return atLineStart(index + 1) || index == mMaxHandleCount - 1; };
+
+ for (int i = 0; i < mMaxHandleCount; ++i) {
+ if (atLineStart(i)) {
+ result << " ";
+ }
+ result << std::hex << std::setw(4) << std::setfill('0') << mHandleHeaders[i]
+ << (atLineEnd(i) ? "\n" : " ");
+ }
+
+ if (isLocked) {
+ mLock.unlock();
+ }
+ return result.str();
+}
+
handle_tracker_slot_t HandleTracker::allocateSlot_l() {
void **allocated = mNextFreeAddress;
if (allocated == nullptr) {
diff --git a/media/libaaudio/src/utility/HandleTracker.h b/media/libaaudio/src/utility/HandleTracker.h
index 23a73ed..a4c51c0 100644
--- a/media/libaaudio/src/utility/HandleTracker.h
+++ b/media/libaaudio/src/utility/HandleTracker.h
@@ -18,6 +18,7 @@
#define UTILITY_HANDLE_TRACKER_H
#include <stdint.h>
+#include <string>
#include <utils/Mutex.h>
typedef int32_t aaudio_handle_t;
@@ -53,6 +54,18 @@
bool isInitialized() const;
/**
+ * Returns HandleTracker information.
+ *
+ * Will attempt to get the object lock, but will proceed
+ * even if it cannot.
+ *
+ * Each line of information ends with a newline.
+ *
+ * @return a string representing the HandleTracker info.
+ */
+ std::string dump() const;
+
+ /**
* Store a pointer and return a handle that can be used to retrieve the pointer.
*
* It is safe to call put() or remove() from multiple threads.
@@ -99,7 +112,7 @@
// This Mutex protects the linked list of free nodes.
// The list is managed using mHandleAddresses and mNextFreeAddress.
// The data in mHandleHeaders is only changed by put() and remove().
- android::Mutex mLock;
+ mutable android::Mutex mLock;
/**
* Pull slot off of a list of empty slots.
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index b509759..77b0182 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1815,6 +1815,40 @@
return true;
}
+// FIXME: remove when concurrent capture is ready. This is a hack to work around bug b/63083537.
+bool AudioPolicyManager::soundTriggerSupportsConcurrentCapture() {
+ if (!mHasComputedSoundTriggerSupportsConcurrentCapture) {
+ bool soundTriggerSupportsConcurrentCapture = false;
+ unsigned int numModules = 0;
+ struct sound_trigger_module_descriptor* nModules = NULL;
+
+ status_t status = SoundTrigger::listModules(nModules, &numModules);
+ if (status == NO_ERROR && numModules != 0) {
+ nModules = (struct sound_trigger_module_descriptor*) calloc(
+ numModules, sizeof(struct sound_trigger_module_descriptor));
+ if (nModules == NULL) {
+ // We failed to malloc the buffer, so just say no for now, and hope that we have more
+ // ram the next time this function is called.
+ ALOGE("Failed to allocate buffer for module descriptors");
+ return false;
+ }
+
+ status = SoundTrigger::listModules(nModules, &numModules);
+ if (status == NO_ERROR) {
+ soundTriggerSupportsConcurrentCapture = true;
+ for (size_t i = 0; i < numModules; ++i) {
+ soundTriggerSupportsConcurrentCapture &=
+ nModules[i].properties.concurrent_capture;
+ }
+ }
+ free(nModules);
+ }
+ mSoundTriggerSupportsConcurrentCapture = soundTriggerSupportsConcurrentCapture;
+ mHasComputedSoundTriggerSupportsConcurrentCapture = true;
+ }
+ return mSoundTriggerSupportsConcurrentCapture;
+}
+
status_t AudioPolicyManager::startInput(audio_io_handle_t input,
audio_session_t session,
@@ -1887,6 +1921,12 @@
}
}
+ // We only need to check if the sound trigger session supports concurrent capture if the
+ // input is also a sound trigger input. Otherwise, we should preempt any hotword stream
+ // that's running.
+ const bool allowConcurrentWithSoundTrigger =
+ inputDesc->isSoundTrigger() ? soundTriggerSupportsConcurrentCapture() : false;
+
// if capture is allowed, preempt currently active HOTWORD captures
for (size_t i = 0; i < activeInputs.size(); i++) {
sp<AudioInputDescriptor> activeDesc = activeInputs[i];
@@ -1895,6 +1935,10 @@
continue;
}
+ if (allowConcurrentWithSoundTrigger && activeDesc->isSoundTrigger()) {
+ continue;
+ }
+
audio_source_t activeSource = activeDesc->inputSource(true);
if (activeSource == AUDIO_SOURCE_HOTWORD) {
AudioSessionCollection activeSessions =
@@ -2165,7 +2209,8 @@
continue;
}
routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
- audio_devices_t curStreamDevice = getDeviceForStrategy(curStrategy, false /*fromCache*/);
+ audio_devices_t curStreamDevice = Volume::getDeviceForVolume(getDeviceForStrategy(
+ curStrategy, false /*fromCache*/));
if ((device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) &&
((curStreamDevice & device) == 0)) {
continue;
@@ -2176,7 +2221,7 @@
applyVolume = (curDevice & curStreamDevice) != 0;
} else {
applyVolume = !mVolumeCurves->hasVolumeIndexForDevice(
- stream, Volume::getDeviceForVolume(curStreamDevice));
+ stream, curStreamDevice);
}
if (applyVolume) {
@@ -3490,7 +3535,8 @@
mBeaconMuted(false),
mTtsOutputAvailable(false),
mMasterMono(false),
- mMusicEffectOutput(AUDIO_IO_HANDLE_NONE)
+ mMusicEffectOutput(AUDIO_IO_HANDLE_NONE),
+ mHasComputedSoundTriggerSupportsConcurrentCapture(false)
{
mUidCached = getuid();
mpClientInterface = clientInterface;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index e8cae79..82c4c35 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -671,6 +671,10 @@
param.addInt(String8(AudioParameter::keyMonoOutput), (int)mMasterMono);
mpClientInterface->setParameters(output, param.toString());
}
+
+ bool soundTriggerSupportsConcurrentCapture();
+ bool mSoundTriggerSupportsConcurrentCapture;
+ bool mHasComputedSoundTriggerSupportsConcurrentCapture;
};
};
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index c2b71a2..c175259 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -231,29 +231,33 @@
for (auto& cameraId : mCameraProviderManager->getCameraDeviceIds()) {
String8 id8 = String8(cameraId.c_str());
+ bool cameraFound = false;
{
+
Mutex::Autolock lock(mCameraStatesLock);
auto iter = mCameraStates.find(id8);
if (iter != mCameraStates.end()) {
- continue;
+ cameraFound = true;
}
}
- hardware::camera::common::V1_0::CameraResourceCost cost;
- res = mCameraProviderManager->getResourceCost(cameraId, &cost);
- if (res != OK) {
- ALOGE("Failed to query device resource cost: %s (%d)", strerror(-res), res);
- continue;
- }
- std::set<String8> conflicting;
- for (size_t i = 0; i < cost.conflictingDevices.size(); i++) {
- conflicting.emplace(String8(cost.conflictingDevices[i].c_str()));
- }
+ if (!cameraFound) {
+ hardware::camera::common::V1_0::CameraResourceCost cost;
+ res = mCameraProviderManager->getResourceCost(cameraId, &cost);
+ if (res != OK) {
+ ALOGE("Failed to query device resource cost: %s (%d)", strerror(-res), res);
+ continue;
+ }
+ std::set<String8> conflicting;
+ for (size_t i = 0; i < cost.conflictingDevices.size(); i++) {
+ conflicting.emplace(String8(cost.conflictingDevices[i].c_str()));
+ }
- {
- Mutex::Autolock lock(mCameraStatesLock);
- mCameraStates.emplace(id8,
- std::make_shared<CameraState>(id8, cost.resourceCost, conflicting));
+ {
+ Mutex::Autolock lock(mCameraStatesLock);
+ mCameraStates.emplace(id8,
+ std::make_shared<CameraState>(id8, cost.resourceCost, conflicting));
+ }
}
onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index 5c6825d..5f6d599 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -19,8 +19,11 @@
#include <utils/Log.h>
#include <assert.h>
+#include <functional>
#include <map>
#include <mutex>
+#include <sstream>
+#include <utility/AAudioUtilities.h>
#include "AAudioEndpointManager.h"
@@ -35,6 +38,34 @@
, mOutputs() {
}
+std::string AAudioEndpointManager::dump() const {
+ std::stringstream result;
+ const bool isLocked = AAudio_tryUntilTrue(
+ [this]()->bool { return mLock.try_lock(); } /* f */,
+ 50 /* times */,
+ 20 /* sleepMs */);
+ if (!isLocked) {
+ result << "EndpointManager may be deadlocked\n";
+ }
+
+ size_t inputs = mInputs.size();
+ result << "Inputs: " << inputs << "\n";
+ for (const auto &input : mInputs) {
+ result << " Input(" << input.first << ", " << input.second << ")\n";
+ }
+
+ size_t outputs = mOutputs.size();
+ result << "Outputs: " << outputs << "\n";
+ for (const auto &output : mOutputs) {
+ result << " Output(" << output.first << ", " << output.second << ")\n";
+ }
+
+ if (isLocked) {
+ mLock.unlock();
+ }
+ return result.str();
+}
+
AAudioServiceEndpoint *AAudioEndpointManager::openEndpoint(AAudioService &audioService, int32_t deviceId,
aaudio_direction_t direction) {
AAudioServiceEndpoint *endpoint = nullptr;
diff --git a/services/oboeservice/AAudioEndpointManager.h b/services/oboeservice/AAudioEndpointManager.h
index 899ea35..6dc5adf 100644
--- a/services/oboeservice/AAudioEndpointManager.h
+++ b/services/oboeservice/AAudioEndpointManager.h
@@ -34,6 +34,18 @@
~AAudioEndpointManager() = default;
/**
+ * Returns EndpointManager information.
+ *
+ * Will attempt to get the object lock, but will proceed
+ * even if it cannot.
+ *
+ * Each line of information ends with a newline.
+ *
+ * @return a string representing the EndpointManager info
+ */
+ std::string dump() const;
+
+ /**
* Find a service endpoint for the given deviceId and direction.
* If an endpoint does not already exist then try to create one.
*
@@ -49,7 +61,7 @@
private:
- std::mutex mLock;
+ mutable std::mutex mLock;
std::map<int32_t, AAudioServiceEndpointCapture *> mInputs;
std::map<int32_t, AAudioServiceEndpointPlay *> mOutputs;
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index b0e0a74..0841127 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -18,6 +18,7 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <sstream>
//#include <time.h>
//#include <pthread.h>
@@ -26,11 +27,13 @@
#include <utils/String16.h>
#include "binding/AAudioServiceMessage.h"
+#include "AAudioEndpointManager.h"
#include "AAudioService.h"
#include "AAudioServiceStreamMMAP.h"
#include "AAudioServiceStreamShared.h"
#include "AAudioServiceStreamMMAP.h"
#include "binding/IAAudioService.h"
+#include "ServiceUtilities.h"
#include "utility/HandleTracker.h"
using namespace android;
@@ -49,6 +52,23 @@
AAudioService::~AAudioService() {
}
+status_t AAudioService::dump(int fd, const Vector<String16>& args) {
+ std::string result;
+
+ if (!dumpAllowed()) {
+ std::stringstream ss;
+ ss << "Permission denial: can't dump AAudioService from pid="
+ << IPCThreadState::self()->getCallingPid() << ", uid="
+ << IPCThreadState::self()->getCallingUid() << "\n";
+ result = ss.str();
+ ALOGW("%s", result.c_str());
+ } else {
+ result = mHandleTracker.dump() + AAudioEndpointManager::getInstance().dump();
+ }
+ (void)write(fd, result.c_str(), result.size());
+ return NO_ERROR;
+}
+
aaudio_handle_t AAudioService::openStream(const aaudio::AAudioStreamRequest &request,
aaudio::AAudioStreamConfiguration &configurationOutput) {
aaudio_result_t result = AAUDIO_OK;
diff --git a/services/oboeservice/AAudioService.h b/services/oboeservice/AAudioService.h
index f5a7d2f..c622f5d 100644
--- a/services/oboeservice/AAudioService.h
+++ b/services/oboeservice/AAudioService.h
@@ -44,6 +44,8 @@
static const char* getServiceName() { return AAUDIO_SERVICE_NAME; }
+ virtual status_t dump(int fd, const Vector<String16>& args) override;
+
virtual aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
aaudio::AAudioStreamConfiguration &configuration);
diff --git a/services/oboeservice/Android.mk b/services/oboeservice/Android.mk
index 7f7d465..12f7e04 100644
--- a/services/oboeservice/Android.mk
+++ b/services/oboeservice/Android.mk
@@ -50,6 +50,7 @@
libbinder \
libcutils \
libmediautils \
+ libserviceutility \
libutils \
liblog