diff options
Diffstat (limited to 'services')
18 files changed, 239 insertions, 83 deletions
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp index 01efc53..8a9a837 100644 --- a/services/audioflinger/AudioMixer.cpp +++ b/services/audioflinger/AudioMixer.cpp @@ -733,13 +733,9 @@ void AudioMixer::setParameter(int name, int target, int param, void *value) case PLAYBACK_RATE: { const AudioPlaybackRate *playbackRate = reinterpret_cast<AudioPlaybackRate*>(value); - ALOG_ASSERT(AUDIO_TIMESTRETCH_SPEED_MIN <= playbackRate->mSpeed - && playbackRate->mSpeed <= AUDIO_TIMESTRETCH_SPEED_MAX, - "bad speed %f", playbackRate->mSpeed); - ALOG_ASSERT(AUDIO_TIMESTRETCH_PITCH_MIN <= playbackRate->mPitch - && playbackRate->mPitch <= AUDIO_TIMESTRETCH_PITCH_MAX, - "bad pitch %f", playbackRate->mPitch); - //TODO: use function from AudioResamplerPublic.h to test validity. + ALOGW_IF(!isAudioPlaybackRateValid(*playbackRate), + "bad parameters speed %f, pitch %f",playbackRate->mSpeed, + playbackRate->mPitch); if (track.setPlaybackRate(*playbackRate)) { ALOGV("setParameter(TIMESTRETCH, PLAYBACK_RATE, STRETCH_MODE, FALLBACK_MODE " "%f %f %d %d", diff --git a/services/audioflinger/BufferProviders.cpp b/services/audioflinger/BufferProviders.cpp index 8a580e8..3566ee2 100644 --- a/services/audioflinger/BufferProviders.cpp +++ b/services/audioflinger/BufferProviders.cpp @@ -332,7 +332,8 @@ TimestretchBufferProvider::TimestretchBufferProvider(int32_t channelCount, mLocalBufferData(NULL), mRemaining(0), mSonicStream(sonicCreateStream(sampleRate, mChannelCount)), - mFallbackFailErrorShown(false) + mFallbackFailErrorShown(false), + mAudioPlaybackRateValid(false) { LOG_ALWAYS_FATAL_IF(mSonicStream == NULL, "TimestretchBufferProvider can't allocate Sonic stream"); @@ -460,6 +461,8 @@ status_t TimestretchBufferProvider::setPlaybackRate(const AudioPlaybackRate &pla sonicSetSpeed(mSonicStream, mPlaybackRate.mSpeed); //TODO: pitch is ignored for now //TODO: optimize: if parameters are the same, don't do any extra computation. + + mAudioPlaybackRateValid = isAudioPlaybackRateValid(mPlaybackRate); return OK; } @@ -479,8 +482,7 @@ void TimestretchBufferProvider::processFrames(void *dstBuffer, size_t *dstFrames *srcFrames = targetSrc + 1; } - if (mPlaybackRate.mSpeed< TIMESTRETCH_SONIC_SPEED_MIN || - mPlaybackRate.mSpeed > TIMESTRETCH_SONIC_SPEED_MAX ) { + if (!mAudioPlaybackRateValid) { //fallback mode if (*dstFrames > 0) { switch(mPlaybackRate.mFallbackMode) { diff --git a/services/audioflinger/BufferProviders.h b/services/audioflinger/BufferProviders.h index 4970b6c..4bc895c 100644 --- a/services/audioflinger/BufferProviders.h +++ b/services/audioflinger/BufferProviders.h @@ -188,6 +188,7 @@ private: sonicStream mSonicStream; // handle to sonic timestretch object //FIXME: this dependency should be abstracted out bool mFallbackFailErrorShown; // log fallback error only once + bool mAudioPlaybackRateValid; // flag for current parameters validity }; // ---------------------------------------------------------------------------- diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp index 9248bba..f6078a2 100644 --- a/services/audioflinger/PatchPanel.cpp +++ b/services/audioflinger/PatchPanel.cpp @@ -481,22 +481,31 @@ void AudioFlinger::PatchPanel::clearPatchConnections(Patch *patch) if (patch->mRecordThread != 0) { if (patch->mPatchRecord != 0) { patch->mRecordThread->deletePatchRecord(patch->mPatchRecord); - patch->mPatchRecord.clear(); } audioflinger->closeInputInternal_l(patch->mRecordThread); - patch->mRecordThread.clear(); } if (patch->mPlaybackThread != 0) { if (patch->mPatchTrack != 0) { patch->mPlaybackThread->deletePatchTrack(patch->mPatchTrack); - patch->mPatchTrack.clear(); } // if num sources == 2 we are reusing an existing playback thread so we do not close it if (patch->mAudioPatch.num_sources != 2) { audioflinger->closeOutputInternal_l(patch->mPlaybackThread); } + } + if (patch->mRecordThread != 0) { + if (patch->mPatchRecord != 0) { + patch->mPatchRecord.clear(); + } + patch->mRecordThread.clear(); + } + if (patch->mPlaybackThread != 0) { + if (patch->mPatchTrack != 0) { + patch->mPatchTrack.clear(); + } patch->mPlaybackThread.clear(); } + } /* Disconnect a patch */ diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 410fff5..d3ea9d8 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -375,6 +375,7 @@ String8 devicesToString(audio_devices_t devices) AUDIO_DEVICE_OUT_FM, "FM", AUDIO_DEVICE_OUT_AUX_LINE, "AUX_LINE", AUDIO_DEVICE_OUT_SPEAKER_SAFE, "SPEAKER_SAFE", + AUDIO_DEVICE_OUT_IP, "IP", AUDIO_DEVICE_NONE, "NONE", // must be last }, mappingsIn[] = { AUDIO_DEVICE_IN_COMMUNICATION, "COMMUNICATION", @@ -397,6 +398,7 @@ String8 devicesToString(audio_devices_t devices) AUDIO_DEVICE_IN_SPDIF, "SPDIF", AUDIO_DEVICE_IN_BLUETOOTH_A2DP, "BLUETOOTH_A2DP", AUDIO_DEVICE_IN_LOOPBACK, "LOOPBACK", + AUDIO_DEVICE_IN_IP, "IP", AUDIO_DEVICE_NONE, "NONE", // must be last }; String8 result; @@ -530,7 +532,7 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio // RecordThread::readInputParameters_l() //FIXME: mStandby should be true here. Is this some kind of hack? mStandby(false), mOutDevice(outDevice), mInDevice(inDevice), - mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id), + mPrevInDevice(AUDIO_DEVICE_NONE), mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id), // mName will be set by concrete (non-virtual) subclass mDeathRecipient(new PMDeathRecipient(this)), mSystemReady(systemReady) @@ -3131,6 +3133,7 @@ status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_pat for (size_t i = 0; i < mEffectChains.size(); i++) { mEffectChains[i]->setDevice_l(type); } + bool configChanged = mOutDevice != type; mOutDevice = type; mPatch = *patch; @@ -3159,7 +3162,9 @@ status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_pat param.toString().string()); *handle = AUDIO_PATCH_HANDLE_NONE; } - sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED); + if (configChanged) { + sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED); + } return status; } @@ -6796,6 +6801,9 @@ bool AudioFlinger::RecordThread::checkForNewParameter_l(const String8& keyValueP status = BAD_VALUE; } else { mInDevice = value; + if (value != AUDIO_DEVICE_NONE) { + mPrevInDevice = value; + } // disable AEC and NS if the device is a BT SCO headset supporting those // pre processings if (mTracks.size() > 0) { @@ -7079,7 +7087,10 @@ status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch *handle = AUDIO_PATCH_HANDLE_NONE; } - sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED); + if (mInDevice != mPrevInDevice) { + sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED); + mPrevInDevice = mInDevice; + } return status; } diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index b12b091..0783371 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -436,6 +436,7 @@ protected: bool mStandby; // Whether thread is currently in standby. audio_devices_t mOutDevice; // output device audio_devices_t mInDevice; // input device + audio_devices_t mPrevInDevice; // previous input device struct audio_patch mPatch; audio_source_t mAudioSource; diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h index 82e2c43..4fdf5b4 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h @@ -42,7 +42,7 @@ public: virtual void toAudioPort(struct audio_port *port) const; - void importAudioPort(const sp<AudioPort> port); + virtual void importAudioPort(const sp<AudioPort> port); void clearCapabilities(); void loadSamplingRates(char *name); diff --git a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h index a39006e..78d2cdf 100644 --- a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h +++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h @@ -73,6 +73,7 @@ const StringToEnum sDeviceTypeToEnumTable[] = { STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPDIF), STRING_TO_ENUM(AUDIO_DEVICE_OUT_FM), STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_LINE), + STRING_TO_ENUM(AUDIO_DEVICE_OUT_IP), STRING_TO_ENUM(AUDIO_DEVICE_IN_AMBIENT), STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC), STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET), @@ -94,6 +95,7 @@ const StringToEnum sDeviceTypeToEnumTable[] = { STRING_TO_ENUM(AUDIO_DEVICE_IN_SPDIF), STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP), STRING_TO_ENUM(AUDIO_DEVICE_IN_LOOPBACK), + STRING_TO_ENUM(AUDIO_DEVICE_IN_IP), }; const StringToEnum sDeviceNameToEnumTable[] = { @@ -124,6 +126,7 @@ const StringToEnum sDeviceNameToEnumTable[] = { NAME_TO_ENUM("S/PDIF Out", AUDIO_DEVICE_OUT_SPDIF), NAME_TO_ENUM("FM transceiver Out", AUDIO_DEVICE_OUT_FM), NAME_TO_ENUM("Aux Line Out", AUDIO_DEVICE_OUT_AUX_LINE), + NAME_TO_ENUM("IP Out", AUDIO_DEVICE_OUT_IP), NAME_TO_ENUM("Ambient Mic", AUDIO_DEVICE_IN_AMBIENT), NAME_TO_ENUM("Built-In Mic", AUDIO_DEVICE_IN_BUILTIN_MIC), NAME_TO_ENUM("BT SCO Headset Mic", AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET), @@ -145,6 +148,7 @@ const StringToEnum sDeviceNameToEnumTable[] = { NAME_TO_ENUM("S/PDIF In", AUDIO_DEVICE_IN_SPDIF), NAME_TO_ENUM("BT A2DP In", AUDIO_DEVICE_IN_BLUETOOTH_A2DP), NAME_TO_ENUM("Loopback In", AUDIO_DEVICE_IN_LOOPBACK), + NAME_TO_ENUM("IP In", AUDIO_DEVICE_IN_IP), }; const StringToEnum sOutputFlagNameToEnumTable[] = { @@ -156,11 +160,15 @@ const StringToEnum sOutputFlagNameToEnumTable[] = { STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING), STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC), STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_TTS), + STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_RAW), + STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_SYNC), }; const StringToEnum sInputFlagNameToEnumTable[] = { STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST), STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD), + STRING_TO_ENUM(AUDIO_INPUT_FLAG_RAW), + STRING_TO_ENUM(AUDIO_INPUT_FLAG_SYNC), }; const StringToEnum sFormatNameToEnumTable[] = { diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h index d1a2f4f..c42ece6 100644 --- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h @@ -44,6 +44,7 @@ public: virtual void attach(const sp<HwModule>& module); virtual void loadGains(cnode *root); virtual void toAudioPort(struct audio_port *port) const; + virtual void importAudioPort(const sp<AudioPort> port); audio_port_handle_t getId() const; audio_devices_t type() const { return mDeviceType; } diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp index afcd073..4e24f19 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp @@ -151,28 +151,12 @@ void AudioPort::importAudioPort(const sp<AudioPort> port) { } } } - for (size_t k = 0 ; k < port->mGains.size() ; k++) { - sp<AudioGain> gain = port->mGains.itemAt(k); - if (gain != 0) { - bool hasGain = false; - for (size_t l = 0 ; l < mGains.size() ; l++) { - if (gain == mGains.itemAt(l)) { - hasGain = true; - break; - } - } - if (!hasGain) { // never import a gain twice - mGains.add(gain); - } - } - } } void AudioPort::clearCapabilities() { mChannelMasks.clear(); mFormats.clear(); mSamplingRates.clear(); - mGains.clear(); } void AudioPort::loadSamplingRates(char *name) diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp index 797077a..1f1fca3 100644 --- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp @@ -301,6 +301,13 @@ void DeviceDescriptor::toAudioPort(struct audio_port *port) const strncpy(port->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN); } +void DeviceDescriptor::importAudioPort(const sp<AudioPort> port) { + AudioPort::importAudioPort(port); + mSamplingRate = port->pickSamplingRate(); + mFormat = port->pickFormat(); + mChannelMask = port->pickChannelMask(); +} + status_t DeviceDescriptor::dump(int fd, int spaces, int index) const { const size_t SIZE = 256; diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index a0de34d..6983b5c 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -427,7 +427,7 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state) /// Opens: can these line be executed after the switch of volume curves??? // if leaving call state, handle special case of active streams // pertaining to sonification strategy see handleIncallSonification() - if (isInCall()) { + if (isStateInCall(oldState)) { ALOGV("setPhoneState() in call state management: new state is %d", state); for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { if (stream == AUDIO_STREAM_PATCH) { @@ -436,7 +436,7 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state) handleIncallSonification((audio_stream_type_t)stream, false, true); } - // force reevaluating accessibility routing when call starts + // force reevaluating accessibility routing when call stops mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY); } @@ -514,6 +514,9 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state) } handleIncallSonification((audio_stream_type_t)stream, true, true); } + + // force reevaluating accessibility routing when call starts + mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY); } // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE @@ -3140,8 +3143,11 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de { audio_devices_t device = devDesc->type(); sp<SwAudioOutputDescriptor> desc; - // erase all current sample rates, formats and channel masks - devDesc->clearCapabilities(); + + if (audio_device_is_digital(device)) { + // erase all current sample rates, formats and channel masks + devDesc->clearCapabilities(); + } if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { // first list already open outputs that can be routed to this device @@ -3433,8 +3439,13 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor> dev const String8 address) { audio_devices_t device = devDesc->type(); - sp<AudioInputDescriptor> desc; + + if (audio_device_is_digital(device)) { + // erase all current sample rates, formats and channel masks + devDesc->clearCapabilities(); + } + if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { // first list already open inputs that can be routed to this device for (size_t input_index = 0; input_index < mInputs.size(); input_index++) { diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index c5f4fb7..eefff3d 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -166,6 +166,17 @@ void AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& cli } } +void AudioPolicyService::setAudioPortCallbacksEnabled(bool enabled) +{ + Mutex::Autolock _l(mNotificationClientsLock); + + uid_t uid = IPCThreadState::self()->getCallingUid(); + if (mNotificationClients.indexOfKey(uid) < 0) { + return; + } + mNotificationClients.valueFor(uid)->setAudioPortCallbacksEnabled(enabled); +} + // removeNotificationClient() is called when the client process dies. void AudioPolicyService::removeNotificationClient(uid_t uid) { @@ -246,7 +257,8 @@ status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_co AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service, const sp<IAudioPolicyServiceClient>& client, uid_t uid) - : mService(service), mUid(uid), mAudioPolicyServiceClient(client) + : mService(service), mUid(uid), mAudioPolicyServiceClient(client), + mAudioPortCallbacksEnabled(false) { } @@ -265,14 +277,14 @@ void AudioPolicyService::NotificationClient::binderDied(const wp<IBinder>& who _ void AudioPolicyService::NotificationClient::onAudioPortListUpdate() { - if (mAudioPolicyServiceClient != 0) { + if (mAudioPolicyServiceClient != 0 && mAudioPortCallbacksEnabled) { mAudioPolicyServiceClient->onAudioPortListUpdate(); } } void AudioPolicyService::NotificationClient::onAudioPatchListUpdate() { - if (mAudioPolicyServiceClient != 0) { + if (mAudioPolicyServiceClient != 0 && mAudioPortCallbacksEnabled) { mAudioPolicyServiceClient->onAudioPatchListUpdate(); } } @@ -285,6 +297,12 @@ void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate( } } +void AudioPolicyService::NotificationClient::setAudioPortCallbacksEnabled(bool enabled) +{ + mAudioPortCallbacksEnabled = enabled; +} + + void AudioPolicyService::binderDied(const wp<IBinder>& who) { ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(), IPCThreadState::self()->getCallingPid()); @@ -912,6 +930,7 @@ void AudioPolicyService::AudioCommandThread::insertCommand_l(sp<AudioCommand>& c patch2 = ((CreateAudioPatchData *)command2->mParam.get())->mPatch; } else { handle2 = ((ReleaseAudioPatchData *)command2->mParam.get())->mHandle; + memset(&patch2, 0, sizeof(patch2)); } if (handle != handle2) break; /* Filter CREATE_AUDIO_PATCH commands only when they are issued for diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h index eb50cdd..a0d5aa2 100644 --- a/services/audiopolicy/service/AudioPolicyService.h +++ b/services/audiopolicy/service/AudioPolicyService.h @@ -185,6 +185,8 @@ public: virtual void registerClient(const sp<IAudioPolicyServiceClient>& client); + virtual void setAudioPortCallbacksEnabled(bool enabled); + virtual status_t acquireSoundTriggerSession(audio_session_t *session, audio_io_handle_t *ioHandle, audio_devices_t *device); @@ -507,6 +509,7 @@ private: void onAudioPortListUpdate(); void onAudioPatchListUpdate(); void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state); + void setAudioPortCallbacksEnabled(bool enabled); // IBinder::DeathRecipient virtual void binderDied(const wp<IBinder>& who); @@ -518,6 +521,7 @@ private: const wp<AudioPolicyService> mService; const uid_t mUid; const sp<IAudioPolicyServiceClient> mAudioPolicyServiceClient; + bool mAudioPortCallbacksEnabled; }; // Internal dump utilities. diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp index 85d4488..1ae01ae 100644 --- a/services/camera/libcameraservice/common/CameraModule.cpp +++ b/services/camera/libcameraservice/common/CameraModule.cpp @@ -154,6 +154,18 @@ CameraModule::CameraModule(camera_module_t *module) { mCameraInfoMap.setCapacity(getNumberOfCameras()); } +CameraModule::~CameraModule() +{ + while (mCameraInfoMap.size() > 0) { + camera_info cameraInfo = mCameraInfoMap.editValueAt(0); + if (cameraInfo.static_camera_characteristics != NULL) { + free_camera_metadata( + const_cast<camera_metadata_t*>(cameraInfo.static_camera_characteristics)); + } + mCameraInfoMap.removeItemsAt(0); + } +} + int CameraModule::init() { if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 && mModule->init != NULL) { @@ -192,12 +204,9 @@ int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) { CameraMetadata m; m = rawInfo.static_camera_characteristics; deriveCameraCharacteristicsKeys(rawInfo.device_version, m); - mCameraCharacteristicsMap.add(cameraId, m); cameraInfo = rawInfo; - cameraInfo.static_camera_characteristics = - mCameraCharacteristicsMap.valueFor(cameraId).getAndLock(); - mCameraInfoMap.add(cameraId, cameraInfo); - index = mCameraInfoMap.indexOfKey(cameraId); + cameraInfo.static_camera_characteristics = m.release(); + index = mCameraInfoMap.add(cameraId, cameraInfo); } assert(index != NAME_NOT_FOUND); diff --git a/services/camera/libcameraservice/common/CameraModule.h b/services/camera/libcameraservice/common/CameraModule.h index c21092e..36822c7 100644 --- a/services/camera/libcameraservice/common/CameraModule.h +++ b/services/camera/libcameraservice/common/CameraModule.h @@ -33,6 +33,7 @@ namespace android { class CameraModule { public: CameraModule(camera_module_t *module); + virtual ~CameraModule(); // Must be called after construction // Returns OK on success, NO_INIT on failure @@ -60,7 +61,6 @@ private: camera_module_t *mModule; KeyedVector<int, camera_info> mCameraInfoMap; - KeyedVector<int, CameraMetadata> mCameraCharacteristicsMap; Mutex mCameraInfoLock; }; diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 9d725de..9e73b5c 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -164,9 +164,17 @@ status_t Camera3Device::initialize(CameraModule *module) return res; } - /** Start up request queue thread */ + bool aeLockAvailable = false; + camera_metadata_ro_entry aeLockAvailableEntry; + res = find_camera_metadata_ro_entry(info.static_camera_characteristics, + ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailableEntry); + if (res == OK && aeLockAvailableEntry.count > 0) { + aeLockAvailable = (aeLockAvailableEntry.data.u8[0] == + ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE); + } - mRequestThread = new RequestThread(this, mStatusTracker, device); + /** Start up request queue thread */ + mRequestThread = new RequestThread(this, mStatusTracker, device, aeLockAvailable); res = mRequestThread->run(String8::format("C3Dev-%d-ReqQueue", mId).string()); if (res != OK) { SET_ERR_L("Unable to start request queue thread: %s (%d)", @@ -1787,12 +1795,14 @@ void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) { */ status_t Camera3Device::registerInFlight(uint32_t frameNumber, - int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput) { + int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput, + const AeTriggerCancelOverride_t &aeTriggerCancelOverride) { ATRACE_CALL(); Mutex::Autolock l(mInFlightLock); ssize_t res; - res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput)); + res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput, + aeTriggerCancelOverride)); if (res < 0) return res; return OK; @@ -2036,7 +2046,8 @@ void Camera3Device::sendCaptureResult(CameraMetadata &pendingMetadata, CaptureResultExtras &resultExtras, CameraMetadata &collectedPartialResult, uint32_t frameNumber, - bool reprocess) { + bool reprocess, + const AeTriggerCancelOverride_t &aeTriggerCancelOverride) { if (pendingMetadata.isEmpty()) return; @@ -2091,6 +2102,8 @@ void Camera3Device::sendCaptureResult(CameraMetadata &pendingMetadata, return; } + overrideResultForPrecaptureCancel(&captureResult.mMetadata, aeTriggerCancelOverride); + // Valid result, insert into queue List<CaptureResult>::iterator queuedResult = mResultQueue.insert(mResultQueue.end(), CaptureResult(captureResult)); @@ -2269,7 +2282,8 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) { CameraMetadata metadata; metadata = result->result; sendCaptureResult(metadata, request.resultExtras, - collectedPartialResult, frameNumber, hasInputBufferInRequest); + collectedPartialResult, frameNumber, hasInputBufferInRequest, + request.aeTriggerCancelOverride); } } @@ -2432,7 +2446,7 @@ void Camera3Device::notifyShutter(const camera3_shutter_msg_t &msg, // send pending result and buffers sendCaptureResult(r.pendingMetadata, r.resultExtras, r.partialResult.collectedResult, msg.frame_number, - r.hasInputBuffer); + r.hasInputBuffer, r.aeTriggerCancelOverride); returnOutputBuffers(r.pendingOutputBuffers.array(), r.pendingOutputBuffers.size(), r.shutterTimestamp); r.pendingOutputBuffers.clear(); @@ -2466,7 +2480,8 @@ CameraMetadata Camera3Device::getLatestRequestLocked() { Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent, sp<StatusTracker> statusTracker, - camera3_device_t *hal3Device) : + camera3_device_t *hal3Device, + bool aeLockAvailable) : Thread(/*canCallJava*/false), mParent(parent), mStatusTracker(statusTracker), @@ -2479,7 +2494,8 @@ Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent, mLatestRequestId(NAME_NOT_FOUND), mCurrentAfTriggerId(0), mCurrentPreCaptureTriggerId(0), - mRepeatingLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES) { + mRepeatingLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES), + mAeLockAvailable(aeLockAvailable) { mStatusId = statusTracker->addComponent(); } @@ -2687,6 +2703,65 @@ void Camera3Device::RequestThread::requestExit() { mRequestSignal.signal(); } + +/** + * For devices <= CAMERA_DEVICE_API_VERSION_3_2, AE_PRECAPTURE_TRIGGER_CANCEL is not supported so + * we need to override AE_PRECAPTURE_TRIGGER_CANCEL to AE_PRECAPTURE_TRIGGER_IDLE and AE_LOCK_OFF + * to AE_LOCK_ON to start cancelling AE precapture. If AE lock is not available, it still overrides + * AE_PRECAPTURE_TRIGGER_CANCEL to AE_PRECAPTURE_TRIGGER_IDLE but doesn't add AE_LOCK_ON to the + * request. + */ +void Camera3Device::RequestThread::handleAePrecaptureCancelRequest(sp<CaptureRequest> request) { + request->mAeTriggerCancelOverride.applyAeLock = false; + request->mAeTriggerCancelOverride.applyAePrecaptureTrigger = false; + + if (mHal3Device->common.version > CAMERA_DEVICE_API_VERSION_3_2) { + return; + } + + camera_metadata_entry_t aePrecaptureTrigger = + request->mSettings.find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER); + if (aePrecaptureTrigger.count > 0 && + aePrecaptureTrigger.data.u8[0] == ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL) { + // Always override CANCEL to IDLE + uint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE; + request->mSettings.update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, &aePrecaptureTrigger, 1); + request->mAeTriggerCancelOverride.applyAePrecaptureTrigger = true; + request->mAeTriggerCancelOverride.aePrecaptureTrigger = + ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL; + + if (mAeLockAvailable == true) { + camera_metadata_entry_t aeLock = request->mSettings.find(ANDROID_CONTROL_AE_LOCK); + if (aeLock.count == 0 || aeLock.data.u8[0] == ANDROID_CONTROL_AE_LOCK_OFF) { + uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_ON; + request->mSettings.update(ANDROID_CONTROL_AE_LOCK, &aeLock, 1); + request->mAeTriggerCancelOverride.applyAeLock = true; + request->mAeTriggerCancelOverride.aeLock = ANDROID_CONTROL_AE_LOCK_OFF; + } + } + } +} + +/** + * Override result metadata for cancelling AE precapture trigger applied in + * handleAePrecaptureCancelRequest(). + */ +void Camera3Device::overrideResultForPrecaptureCancel( + CameraMetadata *result, const AeTriggerCancelOverride_t &aeTriggerCancelOverride) { + if (aeTriggerCancelOverride.applyAeLock) { + // Only devices <= v3.2 should have this override + assert(mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2); + result->update(ANDROID_CONTROL_AE_LOCK, &aeTriggerCancelOverride.aeLock, 1); + } + + if (aeTriggerCancelOverride.applyAePrecaptureTrigger) { + // Only devices <= v3.2 should have this override + assert(mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2); + result->update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, + &aeTriggerCancelOverride.aePrecaptureTrigger, 1); + } +} + bool Camera3Device::RequestThread::threadLoop() { status_t res; @@ -2826,7 +2901,8 @@ bool Camera3Device::RequestThread::threadLoop() { res = parent->registerInFlight(request.frame_number, totalNumBuffers, nextRequest->mResultExtras, - /*hasInput*/request.input_buffer != NULL); + /*hasInput*/request.input_buffer != NULL, + nextRequest->mAeTriggerCancelOverride); ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64 ", burstId = %" PRId32 ".", __FUNCTION__, @@ -3052,6 +3128,9 @@ sp<Camera3Device::CaptureRequest> } } } + + handleAePrecaptureCancelRequest(nextRequest); + mNextRequest = nextRequest; return nextRequest; @@ -3441,6 +3520,7 @@ void Camera3Device::sProcessCaptureResult(const camera3_callback_ops *cb, const camera3_capture_result *result) { Camera3Device *d = const_cast<Camera3Device*>(static_cast<const Camera3Device*>(cb)); + d->processCaptureResult(result); } diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index e2fd8d4..31b6132 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -234,6 +234,13 @@ class Camera3Device : /**** End scope for mLock ****/ + typedef struct AeTriggerCancelOverride { + bool applyAeLock; + uint8_t aeLock; + bool applyAePrecaptureTrigger; + uint8_t aePrecaptureTrigger; + } AeTriggerCancelOverride_t; + class CaptureRequest : public LightRefBase<CaptureRequest> { public: CameraMetadata mSettings; @@ -242,6 +249,9 @@ class Camera3Device : Vector<sp<camera3::Camera3OutputStreamInterface> > mOutputStreams; CaptureResultExtras mResultExtras; + // Used to cancel AE precapture trigger for devices doesn't support + // CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL + AeTriggerCancelOverride_t mAeTriggerCancelOverride; }; typedef List<sp<CaptureRequest> > RequestList; @@ -379,7 +389,8 @@ class Camera3Device : RequestThread(wp<Camera3Device> parent, sp<camera3::StatusTracker> statusTracker, - camera3_device_t *hal3Device); + camera3_device_t *hal3Device, + bool aeLockAvailable); void setNotificationListener(NotificationListener *listener); @@ -492,6 +503,9 @@ class Camera3Device : // If the input request is in mRepeatingRequests. Must be called with mRequestLock hold bool isRepeatingRequestLocked(const sp<CaptureRequest>); + // Handle AE precapture trigger cancel for devices <= CAMERA_DEVICE_API_VERSION_3_2. + void handleAePrecaptureCancelRequest(sp<CaptureRequest> request); + wp<Camera3Device> mParent; wp<camera3::StatusTracker> mStatusTracker; camera3_device_t *mHal3Device; @@ -540,6 +554,9 @@ class Camera3Device : uint32_t mCurrentPreCaptureTriggerId; int64_t mRepeatingLastFrameNumber; + + // Whether the device supports AE lock + bool mAeLockAvailable; }; sp<RequestThread> mRequestThread; @@ -562,7 +579,6 @@ class Camera3Device : // If this request has any input buffer bool hasInputBuffer; - // The last metadata that framework receives from HAL and // not yet send out because the shutter event hasn't arrived. // It's added by process_capture_result and sent when framework @@ -575,6 +591,10 @@ class Camera3Device : // the shutter event. Vector<camera3_stream_buffer_t> pendingOutputBuffers; + // Used to cancel AE precapture trigger for devices doesn't support + // CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL + AeTriggerCancelOverride_t aeTriggerCancelOverride; + // Fields used by the partial result only struct PartialResultInFlight { @@ -595,36 +615,20 @@ class Camera3Device : requestStatus(OK), haveResultMetadata(false), numBuffersLeft(0), - hasInputBuffer(false){ - } - - InFlightRequest(int numBuffers) : - shutterTimestamp(0), - sensorTimestamp(0), - requestStatus(OK), - haveResultMetadata(false), - numBuffersLeft(numBuffers), - hasInputBuffer(false){ + hasInputBuffer(false), + aeTriggerCancelOverride({false, 0, false, 0}){ } - InFlightRequest(int numBuffers, CaptureResultExtras extras) : + InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput, + AeTriggerCancelOverride aeTriggerCancelOverride) : shutterTimestamp(0), sensorTimestamp(0), requestStatus(OK), haveResultMetadata(false), numBuffersLeft(numBuffers), resultExtras(extras), - hasInputBuffer(false){ - } - - InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput) : - shutterTimestamp(0), - sensorTimestamp(0), - requestStatus(OK), - haveResultMetadata(false), - numBuffersLeft(numBuffers), - resultExtras(extras), - hasInputBuffer(hasInput){ + hasInputBuffer(hasInput), + aeTriggerCancelOverride(aeTriggerCancelOverride){ } }; @@ -635,7 +639,8 @@ class Camera3Device : InFlightMap mInFlightMap; status_t registerInFlight(uint32_t frameNumber, - int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput); + int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput, + const AeTriggerCancelOverride_t &aeTriggerCancelOverride); /** * For the partial result, check if all 3A state fields are available @@ -653,6 +658,14 @@ class Camera3Device : template<typename T> bool insert3AResult(CameraMetadata &result, int32_t tag, const T* value, uint32_t frameNumber); + + /** + * Override result metadata for cancelling AE precapture trigger applied in + * handleAePrecaptureCancelRequest(). + */ + void overrideResultForPrecaptureCancel(CameraMetadata* result, + const AeTriggerCancelOverride_t &aeTriggerCancelOverride); + /** * Tracking for idle detection */ @@ -738,7 +751,7 @@ class Camera3Device : void sendCaptureResult(CameraMetadata &pendingMetadata, CaptureResultExtras &resultExtras, CameraMetadata &collectedPartialResult, uint32_t frameNumber, - bool reprocess); + bool reprocess, const AeTriggerCancelOverride_t &aeTriggerCancelOverride); /**** Scope for mInFlightLock ****/ |