summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/audiopolicy/AudioPolicyInterface.h1
-rw-r--r--services/audiopolicy/managerdefault/AudioPolicyManager.cpp19
-rw-r--r--services/audiopolicy/managerdefault/AudioPolicyManager.h1
-rw-r--r--services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp2
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.cpp106
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.h16
6 files changed, 114 insertions, 31 deletions
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 8523fc5..c1e7bc0 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -64,6 +64,7 @@ public:
API_INPUT_MIX_EXT_POLICY_REROUTE,// used for platform audio rerouting, where mixes are
// handled by external and dynamically installed
// policies which reroute audio mixes
+ API_INPUT_TELEPHONY_RX, // used for capture from telephony RX path
} input_type_t;
public:
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index fc27789..b1d7b13 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1066,7 +1066,7 @@ status_t AudioPolicyManager::startSource(sp<AudioOutputDescriptor> outputDesc,
*delayMs = 0;
if (stream == AUDIO_STREAM_TTS) {
ALOGV("\t found BEACON stream");
- if (mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
+ if (!mTtsOutputAvailable && mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
return INVALID_OPERATION;
} else {
beaconMuteLatency = handleEventForBeacon(STARTING_BEACON);
@@ -1351,6 +1351,8 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
} else if (audio_is_remote_submix_device(device)) {
address = String8("0");
*inputType = API_INPUT_MIX_CAPTURE;
+ } else if (device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
+ *inputType = API_INPUT_TELEPHONY_RX;
} else {
*inputType = API_INPUT_LEGACY;
}
@@ -1998,6 +2000,9 @@ status_t AudioPolicyManager::dump(int fd)
snprintf(buffer, SIZE, " Force use for hdmi system audio %d\n",
mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO));
result.append(buffer);
+ snprintf(buffer, SIZE, " TTS output %s\n", mTtsOutputAvailable ? "available" : "not available");
+ result.append(buffer);
+
write(fd, result.string(), result.size());
mAvailableOutputDevices.dump(fd, String8("output"));
@@ -2678,7 +2683,8 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
- mBeaconMuted(false)
+ mBeaconMuted(false),
+ mTtsOutputAvailable(false)
{
audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
if (!engineInstance) {
@@ -2735,6 +2741,9 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
ALOGW("Output profile contains no device on module %s", mHwModules[i]->mName);
continue;
}
+ if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_TTS) != 0) {
+ mTtsOutputAvailable = true;
+ }
if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
continue;
@@ -4034,6 +4043,12 @@ void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t
}
uint32_t AudioPolicyManager::handleEventForBeacon(int event) {
+
+ // skip beacon mute management if a dedicated TTS output is available
+ if (mTtsOutputAvailable) {
+ return 0;
+ }
+
switch(event) {
case STARTING_OUTPUT:
mBeaconMuteRefCount++;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index bf3ae4a..bbdf396 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -548,6 +548,7 @@ protected:
uint32_t mBeaconMuteRefCount; // ref count for stream that would mute beacon
uint32_t mBeaconPlayingRefCount;// ref count for the playing beacon streams
bool mBeaconMuted; // has STREAM_TTS been muted
+ bool mTtsOutputAvailable; // true if a dedicated output for TTS stream is available
AudioPolicyMixCollection mPolicyMixes; // list of registered mixes
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 65639c3..793c26a 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -303,6 +303,8 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
switch (inputType) {
case AudioPolicyInterface::API_INPUT_LEGACY:
break;
+ case AudioPolicyInterface::API_INPUT_TELEPHONY_RX:
+ // FIXME: use the same permission as for remote submix for now.
case AudioPolicyInterface::API_INPUT_MIX_CAPTURE:
if (!captureAudioOutputAllowed()) {
ALOGE("getInputForAttr() permission denied: capture not allowed");
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 3afbd89..0c941fb 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -60,6 +60,7 @@ Camera3Device::Camera3Device(int id):
mIsConstrainedHighSpeedConfiguration(false),
mHal3Device(NULL),
mStatus(STATUS_UNINITIALIZED),
+ mStatusWaiters(0),
mUsePartialResult(false),
mNumPartialResults(1),
mNextResultFrameNumber(0),
@@ -191,7 +192,8 @@ status_t Camera3Device::initialize(CameraModule *module)
mDeviceVersion = device->common.version;
mDeviceInfo = info.static_camera_characteristics;
mHal3Device = device;
- mStatus = STATUS_UNCONFIGURED;
+
+ internalUpdateStatusLocked(STATUS_UNCONFIGURED);
mNextStreamId = 0;
mDummyStreamId = NO_STREAM;
mNeedConfig = true;
@@ -296,7 +298,7 @@ status_t Camera3Device::disconnect() {
mHal3Device = NULL;
}
- mStatus = STATUS_UNINITIALIZED;
+ internalUpdateStatusLocked(STATUS_UNINITIALIZED);
}
ALOGV("%s: X", __FUNCTION__);
@@ -370,7 +372,7 @@ ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const
// Get max jpeg size (area-wise).
Size maxJpegResolution = getMaxJpegResolution();
if (maxJpegResolution.width == 0) {
- ALOGE("%s: Camera %d: Can't find find valid available jpeg sizes in static metadata!",
+ ALOGE("%s: Camera %d: Can't find valid available jpeg sizes in static metadata!",
__FUNCTION__, mId);
return BAD_VALUE;
}
@@ -397,6 +399,21 @@ ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const
return jpegBufferSize;
}
+ssize_t Camera3Device::getPointCloudBufferSize() const {
+ const int FLOATS_PER_POINT=4;
+ camera_metadata_ro_entry maxPointCount = mDeviceInfo.find(ANDROID_DEPTH_MAX_DEPTH_SAMPLES);
+ if (maxPointCount.count == 0) {
+ ALOGE("%s: Camera %d: Can't find maximum depth point cloud size in static metadata!",
+ __FUNCTION__, mId);
+ return BAD_VALUE;
+ }
+ ssize_t maxBytesForPointCloud = sizeof(android_depth_points) +
+ maxPointCount.data.i32[0] * sizeof(float) * FLOATS_PER_POINT;
+ return maxBytesForPointCloud;
+}
+
+
+
status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
ATRACE_CALL();
(void)args;
@@ -865,14 +882,22 @@ status_t Camera3Device::createStream(sp<Surface> consumer,
sp<Camera3OutputStream> newStream;
if (format == HAL_PIXEL_FORMAT_BLOB) {
- ssize_t jpegBufferSize = getJpegBufferSize(width, height);
- if (jpegBufferSize <= 0) {
- SET_ERR_L("Invalid jpeg buffer size %zd", jpegBufferSize);
- return BAD_VALUE;
+ ssize_t blobBufferSize;
+ if (dataSpace != HAL_DATASPACE_DEPTH) {
+ blobBufferSize = getJpegBufferSize(width, height);
+ if (blobBufferSize <= 0) {
+ SET_ERR_L("Invalid jpeg buffer size %zd", blobBufferSize);
+ return BAD_VALUE;
+ }
+ } else {
+ blobBufferSize = getPointCloudBufferSize();
+ if (blobBufferSize <= 0) {
+ SET_ERR_L("Invalid point cloud buffer size %zd", blobBufferSize);
+ return BAD_VALUE;
+ }
}
-
newStream = new Camera3OutputStream(mNextStreamId, consumer,
- width, height, jpegBufferSize, format, dataSpace, rotation);
+ width, height, blobBufferSize, format, dataSpace, rotation);
} else {
newStream = new Camera3OutputStream(mNextStreamId, consumer,
width, height, format, dataSpace, rotation);
@@ -1143,6 +1168,13 @@ status_t Camera3Device::waitUntilDrainedLocked() {
return res;
}
+
+void Camera3Device::internalUpdateStatusLocked(Status status) {
+ mStatus = status;
+ mRecentStatusUpdates.add(mStatus);
+ mStatusChanged.broadcast();
+}
+
// Pause to reconfigure
status_t Camera3Device::internalPauseAndWaitLocked() {
mRequestThread->setPaused(true);
@@ -1173,23 +1205,40 @@ status_t Camera3Device::internalResumeLocked() {
return OK;
}
-status_t Camera3Device::waitUntilStateThenRelock(bool active,
- nsecs_t timeout) {
+status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) {
status_t res = OK;
- if (active == (mStatus == STATUS_ACTIVE)) {
- // Desired state already reached
- return res;
+
+ size_t startIndex = 0;
+ if (mStatusWaiters == 0) {
+ // Clear the list of recent statuses if there are no existing threads waiting on updates to
+ // this status list
+ mRecentStatusUpdates.clear();
+ } else {
+ // If other threads are waiting on updates to this status list, set the position of the
+ // first element that this list will check rather than clearing the list.
+ startIndex = mRecentStatusUpdates.size();
}
+ mStatusWaiters++;
+
bool stateSeen = false;
do {
- mRecentStatusUpdates.clear();
+ if (active == (mStatus == STATUS_ACTIVE)) {
+ // Desired state is current
+ break;
+ }
res = mStatusChanged.waitRelative(mLock, timeout);
if (res != OK) break;
- // Check state change history during wait
- for (size_t i = 0; i < mRecentStatusUpdates.size(); i++) {
+ // This is impossible, but if not, could result in subtle deadlocks and invalid state
+ // transitions.
+ LOG_ALWAYS_FATAL_IF(startIndex > mRecentStatusUpdates.size(),
+ "%s: Skipping status updates in Camera3Device, may result in deadlock.",
+ __FUNCTION__);
+
+ // Encountered desired state since we began waiting
+ for (size_t i = startIndex; i < mRecentStatusUpdates.size(); i++) {
if (active == (mRecentStatusUpdates[i] == STATUS_ACTIVE) ) {
stateSeen = true;
break;
@@ -1197,6 +1246,8 @@ status_t Camera3Device::waitUntilStateThenRelock(bool active,
}
} while (!stateSeen);
+ mStatusWaiters--;
+
return res;
}
@@ -1438,9 +1489,7 @@ void Camera3Device::notifyStatus(bool idle) {
}
ALOGV("%s: Camera %d: Now %s", __FUNCTION__, mId,
idle ? "idle" : "active");
- mStatus = idle ? STATUS_CONFIGURED : STATUS_ACTIVE;
- mRecentStatusUpdates.add(mStatus);
- mStatusChanged.signal();
+ internalUpdateStatusLocked(idle ? STATUS_CONFIGURED : STATUS_ACTIVE);
// Skip notifying listener if we're doing some user-transparent
// state changes
@@ -1649,7 +1698,7 @@ status_t Camera3Device::configureStreamsLocked() {
// Return state to that at start of call, so that future configures
// properly clean things up
- mStatus = STATUS_UNCONFIGURED;
+ internalUpdateStatusLocked(STATUS_UNCONFIGURED);
mNeedConfig = true;
ALOGV("%s: Camera %d: Stream configuration failed", __FUNCTION__, mId);
@@ -1696,11 +1745,8 @@ status_t Camera3Device::configureStreamsLocked() {
mNeedConfig = false;
- if (mDummyStreamId == NO_STREAM) {
- mStatus = STATUS_CONFIGURED;
- } else {
- mStatus = STATUS_UNCONFIGURED;
- }
+ internalUpdateStatusLocked((mDummyStreamId == NO_STREAM) ?
+ STATUS_CONFIGURED : STATUS_UNCONFIGURED);
ALOGV("%s: Camera %d: Stream configuration complete", __FUNCTION__, mId);
@@ -1808,7 +1854,7 @@ void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
mErrorCause = errorCause;
mRequestThread->setPaused(true);
- mStatus = STATUS_ERROR;
+ internalUpdateStatusLocked(STATUS_ERROR);
// Notify upstream about a device error
if (mListener != NULL) {
@@ -2067,8 +2113,12 @@ void Camera3Device::removeInFlightRequestIfReadyLocked(int idx) {
// Sanity check - if we have too many in-flight frames, something has
// likely gone wrong
- if (mInFlightMap.size() > kInFlightWarnLimit) {
+ if (!mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() > kInFlightWarnLimit) {
CLOGE("In-flight list too large: %zu", mInFlightMap.size());
+ } else if (mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() >
+ kInFlightWarnLimitHighSpeed) {
+ CLOGE("In-flight list too large for high speed configuration: %zu",
+ mInFlightMap.size());
}
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 140da98..5287058 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -146,6 +146,7 @@ class Camera3Device :
virtual uint32_t getDeviceVersion();
virtual ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const;
+ ssize_t getPointCloudBufferSize() const;
// Methods called by subclasses
void notifyStatus(bool idle); // updates from StatusTracker
@@ -153,9 +154,11 @@ class Camera3Device :
private:
static const size_t kDumpLockAttempts = 10;
static const size_t kDumpSleepDuration = 100000; // 0.10 sec
- static const size_t kInFlightWarnLimit = 20;
static const nsecs_t kShutdownTimeout = 5000000000; // 5 sec
static const nsecs_t kActiveTimeout = 500000000; // 500 ms
+ static const size_t kInFlightWarnLimit = 20;
+ static const size_t kInFlightWarnLimitHighSpeed = 256; // batch size 32 * pipe depth 8
+
struct RequestTrigger;
// minimal jpeg buffer size: 256KB + blob header
static const ssize_t kMinJpegBufferSize = 256 * 1024 + sizeof(camera3_jpeg_blob);
@@ -204,7 +207,11 @@ class Camera3Device :
STATUS_CONFIGURED,
STATUS_ACTIVE
} mStatus;
+
+ // Only clear mRecentStatusUpdates, mStatusWaiters from waitUntilStateThenRelock
Vector<Status> mRecentStatusUpdates;
+ int mStatusWaiters;
+
Condition mStatusChanged;
// Tracking cause of fatal errors when in STATUS_ERROR
@@ -275,6 +282,13 @@ class Camera3Device :
virtual CameraMetadata getLatestRequestLocked();
/**
+ * Update the current device status and wake all waiting threads.
+ *
+ * Must be called with mLock held.
+ */
+ void internalUpdateStatusLocked(Status status);
+
+ /**
* Pause processing and flush everything, but don't tell the clients.
* This is for reconfiguring outputs transparently when according to the
* CameraDeviceBase interface we shouldn't need to.