diff options
Diffstat (limited to 'services')
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. |