diff options
70 files changed, 950 insertions, 75 deletions
diff --git a/camera/Android.bp b/camera/Android.bp index c76ae507fd..58cc622c3f 100644 --- a/camera/Android.bp +++ b/camera/Android.bp @@ -14,6 +14,26 @@ subdirs = ["ndk"] +bootstrap_go_package { + name: "soong-camera-parameters", + pkgPath: "android/soong/camera_parameters", + deps: [ + "blueprint", + "blueprint-pathtools", + "soong", + "soong-android", + "soong-cc", + ], + srcs: [ + "parameters.go", + ], + pluginFor: ["soong_build"], +} + +camera_parameters_defaults { + name: "camera_parameters_defaults", +} + cc_library_shared { name: "libcamera_client", @@ -39,7 +59,6 @@ cc_library_shared { // Source for camera interface parcelables, and manually-written interfaces "Camera.cpp", "CameraMetadata.cpp", - "CameraParameters.cpp", "CaptureResult.cpp", "CameraParameters2.cpp", "ICamera.cpp", @@ -54,6 +73,17 @@ cc_library_shared { "VendorTagDescriptor.cpp", ], + product_variables: { + lineage: { + uses_generic_camera_parameter_library: { + srcs: [ + "CameraParameters.cpp", + ], + }, + }, + }, + defaults: ["camera_parameters_defaults"], + shared_libs: [ "libcutils", "libutils", diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp index 68969cf649..de8ac2ffce 100644 --- a/camera/CameraParameters.cpp +++ b/camera/CameraParameters.cpp @@ -237,6 +237,9 @@ void CameraParameters::unflatten(const String8 ¶ms) void CameraParameters::set(const char *key, const char *value) { + if (key == NULL || value == NULL) + return; + // XXX i think i can do this with strspn() if (strchr(key, '=') || strchr(key, ';')) { //XXX ALOGE("Key \"%s\"contains invalid character (= or ;)", key); diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp index 8620f36022..d07a8d5f37 100644 --- a/camera/ICameraClient.cpp +++ b/camera/ICameraClient.cpp @@ -51,7 +51,11 @@ public: data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); data.writeInt32(msgType); data.writeInt32(ext1); - data.writeInt32(ext2); + if ((msgType == CAMERA_MSG_PREVIEW_FRAME) && (ext1 == CAMERA_FRAME_DATA_FD)) { + data.writeFileDescriptor(ext2); + } else { + data.writeInt32(ext2); + } remote()->transact(NOTIFY_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); } @@ -129,8 +133,13 @@ status_t BnCameraClient::onTransact( ALOGV("NOTIFY_CALLBACK"); CHECK_INTERFACE(ICameraClient, data, reply); int32_t msgType = data.readInt32(); - int32_t ext1 = data.readInt32(); - int32_t ext2 = data.readInt32(); + int32_t ext1 = data.readInt32(); + int32_t ext2 = 0; + if ((msgType == CAMERA_MSG_PREVIEW_FRAME) && (ext1 == CAMERA_FRAME_DATA_FD)) { + ext2 = data.readFileDescriptor(); + } else { + ext2 = data.readInt32(); + } notifyCallback(msgType, ext1, ext2); return NO_ERROR; } break; diff --git a/camera/cameraserver/Android.mk b/camera/cameraserver/Android.mk index b8c94e64e3..b41656f01d 100644 --- a/camera/cameraserver/Android.mk +++ b/camera/cameraserver/Android.mk @@ -14,6 +14,9 @@ LOCAL_PATH:= $(call my-dir) +ifeq ($(TARGET_HAS_LEGACY_CAMERA_HAL1),true) +$(warning Target has integrated cameraserver into mediaserver. This is weakening security measures introduced in 7.0) +else include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ @@ -32,6 +35,12 @@ LOCAL_SHARED_LIBRARIES := \ android.hardware.camera.device@1.0 \ android.hardware.camera.device@3.2 +ifeq ($(TARGET_USES_QTI_CAMERA_DEVICE), true) +LOCAL_CFLAGS += -DQTI_CAMERA_DEVICE +LOCAL_SHARED_LIBRARIES += \ + vendor.qti.hardware.camera.device@1.0 +endif + LOCAL_MODULE:= cameraserver LOCAL_32_BIT_ONLY := true @@ -40,3 +49,4 @@ LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-parameter LOCAL_INIT_RC := cameraserver.rc include $(BUILD_EXECUTABLE) +endif diff --git a/camera/include/camera/CameraMetadata.h b/camera/include/camera/CameraMetadata.h index d28447784f..e2b743db54 100644 --- a/camera/include/camera/CameraMetadata.h +++ b/camera/include/camera/CameraMetadata.h @@ -222,6 +222,7 @@ class CameraMetadata: public Parcelable { private: camera_metadata_t *mBuffer; + volatile char mReserved[3] __attribute__ ((unused)); mutable bool mLocked; /** diff --git a/camera/include/camera/CameraParameters2.h b/camera/include/camera/CameraParameters2.h index f691cd6ea0..5fae079376 100644 --- a/camera/include/camera/CameraParameters2.h +++ b/camera/include/camera/CameraParameters2.h @@ -19,7 +19,7 @@ #include <utils/Vector.h> #include <utils/String8.h> -#include "CameraParameters.h" +#include <camera/CameraParameters.h> namespace android { diff --git a/camera/parameters.go b/camera/parameters.go new file mode 100644 index 0000000000..dfaa278190 --- /dev/null +++ b/camera/parameters.go @@ -0,0 +1,52 @@ +// Copyright (C) 2017 The LineageOS Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package lineage + +import ( + "android/soong/android" + "android/soong/cc" +) + +func init() { + android.RegisterModuleType("camera_parameters_defaults", cameraParametersFactory) +} + +func cameraParametersFactory() android.Module { + module := cc.DefaultsFactory() + android.AddLoadHook(module, cameraParameters) + + return module +} + +func cameraParameters(ctx android.LoadHookContext) { + type props struct { + Whole_static_libs []string + } + + p := &props{} + p.Whole_static_libs = globalDefaults(ctx) + + ctx.AppendProperties(p) +} + +func globalDefaults(ctx android.BaseContext) []string { + var staticLibs []string + + device_camera_parameters_lib := ctx.DeviceConfig().SpecificCameraParametersLibrary() + if len(device_camera_parameters_lib) > 0 { + staticLibs = append(staticLibs, device_camera_parameters_lib) + } + + return staticLibs +} diff --git a/include/media/AudioSession.h b/include/media/AudioSession.h new file mode 120000 index 0000000000..005e48e7ed --- /dev/null +++ b/include/media/AudioSession.h @@ -0,0 +1 @@ +../../media/libaudioclient/include/media/AudioSession.h
\ No newline at end of file diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp index cdc75ace66..19b377fa8f 100644 --- a/media/libaudioclient/AudioSystem.cpp +++ b/media/libaudioclient/AudioSystem.cpp @@ -39,7 +39,7 @@ sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient; audio_error_callback AudioSystem::gAudioErrorCallback = NULL; dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL; record_config_callback AudioSystem::gRecordConfigCallback = NULL; - +audio_session_callback AudioSystem::gAudioSessionCallback = NULL; // establish binder interface to AudioFlinger service const sp<IAudioFlinger> AudioSystem::get_audio_flinger() @@ -706,6 +706,17 @@ status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback( gRecordConfigCallback = cb; } +/*static*/ status_t AudioSystem::setAudioSessionCallback(audio_session_callback cb) +{ + const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + + Mutex::Autolock _l(gLock); + gAudioSessionCallback = cb; + + return NO_ERROR; +} + // client singleton for AudioPolicyService binder interface // protected by gLockAPS sp<IAudioPolicyService> AudioSystem::gAudioPolicyService; @@ -1333,6 +1344,32 @@ void AudioSystem::AudioPolicyServiceClient::onRecordingConfigurationUpdate( } } +// --------------------------------------------------------------------------- + +status_t AudioSystem::listAudioSessions(audio_stream_type_t stream, + Vector< sp<AudioSessionInfo>> &sessions) +{ + const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->listAudioSessions(stream, sessions); +} + +void AudioSystem::AudioPolicyServiceClient::onOutputSessionEffectsUpdate( + sp<AudioSessionInfo>& info, bool added) +{ + ALOGV("AudioPolicyServiceClient::onOutputSessionEffectsUpdate(%d, %d, %d)", + info->mStream, info->mSessionId, added); + audio_session_callback cb = NULL; + { + Mutex::Autolock _l(AudioSystem::gLock); + cb = gAudioSessionCallback; + } + + if (cb != NULL) { + cb(AUDIO_OUTPUT_SESSION_EFFECTS_UPDATE, info, added); + } +} + void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused) { { diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp index f071a020b1..ac1c71003e 100644 --- a/media/libaudioclient/IAudioPolicyService.cpp +++ b/media/libaudioclient/IAudioPolicyService.cpp @@ -78,7 +78,8 @@ enum { SET_AUDIO_PORT_CALLBACK_ENABLED, SET_MASTER_MONO, GET_MASTER_MONO, - GET_STREAM_VOLUME_DB + GET_STREAM_VOLUME_DB, + LIST_AUDIO_SESSIONS }; #define MAX_ITEMS_PER_LIST 1024 @@ -842,6 +843,29 @@ public: } return reply.readFloat(); } + + virtual status_t listAudioSessions(audio_stream_type_t streams, + Vector< sp<AudioSessionInfo>> &sessions) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.writeInt32(streams); + status_t status = remote()->transact(LIST_AUDIO_SESSIONS, data, &reply); + if (status != NO_ERROR) { + return status; + } + + status = reply.readInt32(); + if (status == NO_ERROR) { + size_t size = (size_t)reply.readUint32(); + for (size_t i = 0; i < size && reply.dataAvail() > 0; i++) { + sp<AudioSessionInfo> info = new AudioSessionInfo(); + info->readFromParcel(reply); + sessions.push_back(info); + } + } + return status; + } }; IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService"); @@ -1351,6 +1375,23 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case LIST_AUDIO_SESSIONS: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_stream_type_t streams = (audio_stream_type_t)data.readInt32(); + + Vector< sp<AudioSessionInfo>> sessions; + status_t status = listAudioSessions(streams, sessions); + + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->writeUint32(static_cast<uint32_t>(sessions.size())); + for (size_t i = 0; i < sessions.size(); i++) { + sessions[i]->writeToParcel(reply); + } + } + return NO_ERROR; + } + case ACQUIRE_SOUNDTRIGGER_SESSION: { CHECK_INTERFACE(IAudioPolicyService, data, reply); sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>( diff --git a/media/libaudioclient/IAudioPolicyServiceClient.cpp b/media/libaudioclient/IAudioPolicyServiceClient.cpp index ad7f1dea55..2f7026f0a5 100644 --- a/media/libaudioclient/IAudioPolicyServiceClient.cpp +++ b/media/libaudioclient/IAudioPolicyServiceClient.cpp @@ -31,7 +31,8 @@ enum { PORT_LIST_UPDATE = IBinder::FIRST_CALL_TRANSACTION, PATCH_LIST_UPDATE, MIX_STATE_UPDATE, - RECORDING_CONFIGURATION_UPDATE + RECORDING_CONFIGURATION_UPDATE, + OUTPUT_SESSION_EFFECTS_UPDATE }; // ---------------------------------------------------------------------- @@ -104,6 +105,19 @@ public: data.writeInt32(patchHandle); remote()->transact(RECORDING_CONFIGURATION_UPDATE, data, &reply, IBinder::FLAG_ONEWAY); } + + void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor()); + data.writeInt32(info->mStream); + data.writeInt32(info->mSessionId); + data.writeInt32(info->mFlags); + data.writeInt32(info->mChannelMask); + data.writeInt32(info->mUid); + data.writeInt32(added ? 1 : 0); + remote()->transact(OUTPUT_SESSION_EFFECTS_UPDATE, data, &reply, IBinder::FLAG_ONEWAY); + } }; IMPLEMENT_META_INTERFACE(AudioPolicyServiceClient, "android.media.IAudioPolicyServiceClient"); @@ -145,6 +159,20 @@ status_t BnAudioPolicyServiceClient::onTransact( patchHandle); return NO_ERROR; } break; + case OUTPUT_SESSION_EFFECTS_UPDATE: { + CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply); + audio_stream_type_t stream = static_cast<audio_stream_type_t>(data.readInt32()); + audio_session_t sessionId = static_cast<audio_session_t>(data.readInt32()); + audio_output_flags_t flags = static_cast<audio_output_flags_t>(data.readInt32()); + audio_channel_mask_t channelMask = static_cast<audio_channel_mask_t>(data.readInt32()); + uid_t uid = static_cast<uid_t>(data.readInt32()); + bool added = data.readInt32() > 0; + + sp<AudioSessionInfo> info = new AudioSessionInfo( + sessionId, stream, flags, channelMask, uid); + onOutputSessionEffectsUpdate(info, added); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h index 8da0069ccb..ba814a31d5 100644 --- a/media/libaudioclient/include/media/AudioPolicy.h +++ b/media/libaudioclient/include/media/AudioPolicy.h @@ -23,6 +23,7 @@ #include <binder/Parcel.h> #include <utils/String8.h> #include <utils/Vector.h> +#include <media/AudioSession.h> namespace android { @@ -44,6 +45,7 @@ namespace android { // AudioSystem's implementation of the AudioPolicyClient interface // keep in sync with AudioSystem.java #define DYNAMIC_POLICY_EVENT_MIX_STATE_UPDATE 0 +#define AUDIO_OUTPUT_SESSION_EFFECTS_UPDATE 10 #define MIX_STATE_DISABLED (-1) #define MIX_STATE_IDLE 0 diff --git a/media/libaudioclient/include/media/AudioSession.h b/media/libaudioclient/include/media/AudioSession.h new file mode 100644 index 0000000000..2bae5212cf --- /dev/null +++ b/media/libaudioclient/include/media/AudioSession.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_AUDIOSESSION_H +#define ANDROID_AUDIOSESSION_H + +#include <stdint.h> +#include <sys/types.h> + +#include <system/audio.h> + +#include <utils/RefBase.h> +#include <utils/Errors.h> +#include <binder/Parcel.h> + +namespace android { + +// class to store streaminfo +class AudioSessionInfo : public RefBase { +public: + AudioSessionInfo(audio_session_t session, audio_stream_type_t stream, audio_output_flags_t flags, + audio_channel_mask_t channelMask, uid_t uid) : + mSessionId(session), mStream(stream), mFlags(flags), mChannelMask(channelMask), + mUid(uid), mRefCount(0) {} + + AudioSessionInfo() : mSessionId((audio_session_t) 0), mStream(AUDIO_STREAM_DEFAULT), mFlags(AUDIO_OUTPUT_FLAG_NONE), mChannelMask(AUDIO_CHANNEL_NONE), mUid(0) {} + + /*virtual*/ ~AudioSessionInfo() {} + + audio_session_t mSessionId; + audio_stream_type_t mStream; + audio_output_flags_t mFlags; + audio_channel_mask_t mChannelMask; + uid_t mUid; + + // AudioPolicyManager keeps mLock, no need for lock on reference count here + int mRefCount; + + void readFromParcel(const Parcel &parcel) { + mSessionId = (audio_session_t) parcel.readInt32(); + mStream = static_cast<audio_stream_type_t>(parcel.readInt32()); + mFlags = static_cast<audio_output_flags_t>(parcel.readInt32()); + mChannelMask = static_cast<audio_channel_mask_t>(parcel.readInt32()); + mUid = static_cast<uid_t>(parcel.readInt32()); + } + + void writeToParcel(Parcel *parcel) const { + parcel->writeInt32(mSessionId); + parcel->writeInt32(mStream); + parcel->writeInt32(mFlags); + parcel->writeInt32(mChannelMask); + parcel->writeInt32(mUid); + } +}; + +}; // namespace android + +#endif // ANDROID_AUDIOSESSION_H diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h index 5a81d835dc..feea961843 100644 --- a/media/libaudioclient/include/media/AudioSystem.h +++ b/media/libaudioclient/include/media/AudioSystem.h @@ -36,6 +36,8 @@ typedef void (*dynamic_policy_callback)(int event, String8 regId, int val); typedef void (*record_config_callback)(int event, const record_client_info_t *clientInfo, const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle); +typedef void (*audio_session_callback)(int event, + sp<AudioSessionInfo>& session, bool added); class IAudioFlinger; class IAudioPolicyService; @@ -100,6 +102,7 @@ public: static void setErrorCallback(audio_error_callback cb); static void setDynPolicyCallback(dynamic_policy_callback cb); static void setRecordConfigCallback(record_config_callback); + static status_t setAudioSessionCallback(audio_session_callback cb); // helper function to obtain AudioFlinger service handle static const sp<IAudioFlinger> get_audio_flinger(); @@ -341,6 +344,9 @@ public: static float getStreamVolumeDB( audio_stream_type_t stream, int index, audio_devices_t device); + static status_t listAudioSessions(audio_stream_type_t streams, + Vector< sp<AudioSessionInfo>> &sessions); + // ---------------------------------------------------------------------------- class AudioPortCallback : public RefBase @@ -444,6 +450,7 @@ private: const record_client_info_t *clientInfo, const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle); + virtual void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added); private: Mutex mLock; @@ -464,6 +471,7 @@ private: static audio_error_callback gAudioErrorCallback; static dynamic_policy_callback gDynPolicyCallback; static record_config_callback gRecordConfigCallback; + static audio_session_callback gAudioSessionCallback; static size_t gInBuffSize; // previous parameters for recording buffer size queries diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h index eec3e881da..c01d7d042f 100644 --- a/media/libaudioclient/include/media/IAudioPolicyService.h +++ b/media/libaudioclient/include/media/IAudioPolicyService.h @@ -171,6 +171,9 @@ public: virtual status_t getMasterMono(bool *mono) = 0; virtual float getStreamVolumeDB( audio_stream_type_t stream, int index, audio_devices_t device) = 0; + + virtual status_t listAudioSessions(audio_stream_type_t streams, + Vector< sp<AudioSessionInfo>> &sessions) = 0; }; diff --git a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h index e0d2495fad..fb7d7be2a0 100644 --- a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h +++ b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h @@ -21,6 +21,7 @@ #include <utils/RefBase.h> #include <binder/IInterface.h> #include <system/audio.h> +#include <media/AudioSession.h> namespace android { @@ -53,6 +54,8 @@ public: const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle) = 0; + // Notifies when a default effect set is attached to a session/stream + virtual void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added) = 0; }; diff --git a/media/libmedia/omx/1.0/WOmxNode.cpp b/media/libmedia/omx/1.0/WOmxNode.cpp index 0b40e8d467..2cd8b760d1 100644 --- a/media/libmedia/omx/1.0/WOmxNode.cpp +++ b/media/libmedia/omx/1.0/WOmxNode.cpp @@ -151,7 +151,8 @@ status_t LWOmxNode::allocateSecureBuffer( hidl_handle const& outNativeHandle) { fnStatus = toStatusT(status); *buffer = outBuffer; - *native_handle = NativeHandle::create( + *native_handle = outNativeHandle.getNativeHandle() == nullptr ? + nullptr : NativeHandle::create( native_handle_clone(outNativeHandle), true); })); return transStatus == NO_ERROR ? fnStatus : transStatus; diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 89354d6d09..c58dcb9b08 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -1566,7 +1566,7 @@ status_t StagefrightRecorder::setupCameraSource( Size videoSize; videoSize.width = mVideoWidth; videoSize.height = mVideoHeight; - if (mCaptureFpsEnable) { + if (mCaptureFpsEnable && mCaptureFps != mFrameRate) { if (!(mCaptureFps > 0.)) { ALOGE("Invalid mCaptureFps value: %lf", mCaptureFps); return BAD_VALUE; @@ -1706,6 +1706,7 @@ status_t StagefrightRecorder::setupVideoEncoder( preferBFrames = false; tsLayers = 2; // use at least two layers as resulting video will likely be sped up } else if (mCaptureFps > maxPlaybackFps) { // slow-mo + format->setInt32("high-frame-rate", 1); maxPlaybackFps = mCaptureFps; // assume video will be played back at full capture speed preferBFrames = false; } @@ -1952,7 +1953,7 @@ status_t StagefrightRecorder::resume() { mPauseStartTimeUs = bufferStartTimeUs; } // 30 ms buffer to avoid timestamp overlap - mTotalPausedDurationUs += resumeStartTimeUs - mPauseStartTimeUs - 30000; + mTotalPausedDurationUs += (systemTime() / 1000) - mPauseStartTimeUs - 30000; } double timeOffset = -mTotalPausedDurationUs; if (mCaptureFpsEnable) { diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index df360462d6..7e10631dc1 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -2200,9 +2200,6 @@ void NuPlayer::performDecoderFlush(FlushCommand audio, FlushCommand video) { void NuPlayer::performReset() { ALOGV("performReset"); - CHECK(mAudioDecoder == NULL); - CHECK(mVideoDecoder == NULL); - cancelPollDuration(); ++mScanSourcesGeneration; diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index a2eb9a8c6b..def8ada3c3 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -7517,6 +7517,7 @@ status_t ACodec::setVendorParameters(const sp<AMessage> ¶ms) { // don't bother component if we don't have vendor extensions as they may not have implemented // the android vendor extension support, which will lead to unnecessary OMX failure logs. if (vendorKeys.empty()) { + mVendorExtensionsStatus = kExtensionsNone; return OK; } diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index 6ed0d0eb43..399199e381 100644 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -162,6 +162,10 @@ static int32_t getColorFormat(const char* colorFormat) { return OMX_COLOR_FormatAndroidOpaque; } + if (!strcmp(colorFormat, "YVU420SemiPlanar")) { + return OMX_QCOM_COLOR_FormatYVU420SemiPlanar; + } + ALOGE("Uknown color format (%s), please add it to " "CameraSource::getColorFormat", colorFormat); @@ -337,6 +341,12 @@ status_t CameraSource::isCameraColorFormatSupported( return OK; } +static int32_t getHighSpeedFrameRate(const CameraParameters& params) { + const char* hsr = params.get("video-hsr"); + int32_t rate = (hsr != NULL && strncmp(hsr, "off", 3)) ? strtol(hsr, NULL, 10) : 0; + return std::min(rate, 240); +} + /* * Configure the camera to use the requested video size * (width and height) and/or frame rate. If both width and @@ -384,11 +394,15 @@ status_t CameraSource::configureCamera( } if (frameRate != -1) { - CHECK(frameRate > 0 && frameRate <= 120); + CHECK(frameRate > 0 && frameRate <= 240); const char* supportedFrameRates = params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES); CHECK(supportedFrameRates != NULL); ALOGV("Supported frame rates: %s", supportedFrameRates); + if (getHighSpeedFrameRate(*params)) { + ALOGI("Use default 30fps for HighSpeed %dfps", frameRate); + frameRate = 30; + } char buf[4]; snprintf(buf, 4, "%d", frameRate); if (strstr(supportedFrameRates, buf) == NULL) { @@ -490,6 +504,8 @@ status_t CameraSource::checkFrameRate( ALOGE("Failed to retrieve preview frame rate (%d)", frameRateActual); return UNKNOWN_ERROR; } + int32_t highSpeedRate = getHighSpeedFrameRate(params); + frameRateActual = highSpeedRate ? highSpeedRate : frameRateActual; // Check the actual video frame rate against the target/requested // video frame rate. diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp index 970526af66..492ecfe03e 100644 --- a/media/libstagefright/CameraSourceTimeLapse.cpp +++ b/media/libstagefright/CameraSourceTimeLapse.cpp @@ -281,7 +281,8 @@ bool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) { // The first 2 output frames from the encoder are: decoder specific info and // the compressed video frame data for the first input video frame. if (mNumFramesEncoded >= 1 && *timestampUs < - (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenFrameCaptureUs)) { + (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenFrameCaptureUs) && + (mTimeBetweenFrameCaptureUs > mTimeBetweenTimeLapseVideoFramesUs + 1)) { // Skip all frames from last encoded frame until // sufficient time (mTimeBetweenFrameCaptureUs) has passed. // Tell the camera to release its recording frame and return. @@ -296,6 +297,12 @@ bool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) { mLastTimeLapseFrameRealTimestampUs = *timestampUs; *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs; + // Update start-time once the captured-time reaches the expected start-time. + // Not doing so will result in CameraSource always dropping frames since + // updated-timestamp will never intersect start-timestamp + if ((mNumFramesReceived == 0 && mLastTimeLapseFrameRealTimestampUs >= mStartTimeUs)) { + mStartTimeUs = *timestampUs; + } return false; } return false; diff --git a/media/libstagefright/FLACExtractor.cpp b/media/libstagefright/FLACExtractor.cpp index 1b88e5d25d..a96b3c3a19 100644 --- a/media/libstagefright/FLACExtractor.cpp +++ b/media/libstagefright/FLACExtractor.cpp @@ -585,6 +585,8 @@ status_t FLACParser::init() case 48000: case 88200: case 96000: + case 176400: + case 192000: break; default: ALOGE("unsupported sample rate %u", getSampleRate()); diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 9c777b31c6..b710b81daa 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -317,8 +317,13 @@ static const char *FourCC2MIME(uint32_t fourcc) { case FOURCC('h', 'e', 'v', '1'): return MEDIA_MIMETYPE_VIDEO_HEVC; default: - CHECK(!"should not be here."); - return NULL; + ALOGW("Unknown fourcc: %c%c%c%c", + (fourcc >> 24) & 0xff, + (fourcc >> 16) & 0xff, + (fourcc >> 8) & 0xff, + fourcc & 0xff + ); + return "application/octet-stream"; } } diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp index d808e5bb46..7d52d41b19 100644 --- a/media/libstagefright/MediaCodecSource.cpp +++ b/media/libstagefright/MediaCodecSource.cpp @@ -748,8 +748,8 @@ status_t MediaCodecSource::feedEncoderInputBuffers() { } status_t MediaCodecSource::onStart(MetaData *params) { - if (mStopping) { - ALOGE("Failed to start while we're stopping"); + if (mStopping || mOutput.lock()->mEncoderReachedEOS) { + ALOGE("Failed to start while we're stopping or encoder already stopped due to EOS error"); return INVALID_OPERATION; } int64_t startTimeUs; diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp index 4ff2bfe189..9925dbf420 100644 --- a/media/libstagefright/StagefrightMediaScanner.cpp +++ b/media/libstagefright/StagefrightMediaScanner.cpp @@ -40,7 +40,8 @@ static bool FileHasAcceptableExtension(const char *extension) { ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac", ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota", ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf", - ".avi", ".mpeg", ".mpg", ".awb", ".mpga", ".mov" + ".avi", ".mpeg", ".mpg", ".awb", ".mpga", ".mov", ".opus", + ".m4v", ".oga" }; static const size_t kNumValidExtensions = sizeof(kValidExtensions) / sizeof(kValidExtensions[0]); @@ -62,6 +63,11 @@ MediaScanResult StagefrightMediaScanner::processFile( client.setLocale(locale()); client.beginFile(); MediaScanResult result = processFileInternal(path, mimeType, client); + ALOGV("result: %d", result); + if (mimeType == NULL && result != MEDIA_SCAN_RESULT_OK) { + ALOGW("media scan failed for %s", path); + client.setMimeType("application/octet-stream"); + } client.endFile(); return result; } diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp index ccce170913..e8c3dd38a7 100644 --- a/media/libstagefright/StagefrightMetadataRetriever.cpp +++ b/media/libstagefright/StagefrightMetadataRetriever.cpp @@ -494,13 +494,18 @@ static VideoFrame *extractVideoFrame( ALOGV("Timed-out waiting for output.. retries left = %zu", retriesLeft); err = OK; } else if (err == OK) { + if (outputFormat == NULL) { + decoder->releaseOutputBuffer(index); + err = ERROR_MALFORMED; + break; + } + // If we're seeking with CLOSEST option and obtained a valid targetTimeUs // from the extractor, decode to the specified frame. Otherwise we're done. ALOGV("Received an output buffer, timeUs=%lld", (long long)timeUs); sp<MediaCodecBuffer> videoFrameBuffer = outputBuffers.itemAt(index); int32_t width, height; - CHECK(outputFormat != NULL); CHECK(outputFormat->findInt32("width", &width)); CHECK(outputFormat->findInt32("height", &height)); diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp index d14e86b1f2..c1ef653c15 100644 --- a/media/libstagefright/SurfaceMediaSource.cpp +++ b/media/libstagefright/SurfaceMediaSource.cpp @@ -389,7 +389,7 @@ void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) { buffer_handle_t bufferHandle = getMediaBufferHandle(buffer); for (size_t i = 0; i < mCurrentBuffers.size(); i++) { - if (mCurrentBuffers[i]->handle == bufferHandle) { + if ((buffer_handle_t)mCurrentBuffers[i]->getNativeBuffer() == bufferHandle) { mCurrentBuffers.removeAt(i); foundBuffer = true; break; @@ -405,7 +405,7 @@ void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) { continue; } - if (bufferHandle == mSlots[id].mGraphicBuffer->handle) { + if (bufferHandle == (buffer_handle_t)mSlots[id].mGraphicBuffer->getNativeBuffer()) { ALOGV("Slot %d returned, matches handle = %p", id, mSlots[id].mGraphicBuffer->handle); diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp index b7c1598ecf..2dd6df8032 100644 --- a/media/libstagefright/SurfaceUtils.cpp +++ b/media/libstagefright/SurfaceUtils.cpp @@ -108,8 +108,9 @@ status_t setNativeWindowSizeFormatAndUsage( } } - int finalUsage = usage | consumerUsage; - ALOGV("gralloc usage: %#x(producer) + %#x(consumer) = %#x", usage, consumerUsage, finalUsage); + uint64_t finalUsage = (usage | consumerUsage) & 0xffffffffLL; + ALOGV("gralloc usage: %#x(producer) + %#x(consumer) = %#" PRIx64, + usage, consumerUsage, finalUsage); err = native_window_set_usage(nativeWindow, finalUsage); if (err != NO_ERROR) { ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); @@ -123,7 +124,7 @@ status_t setNativeWindowSizeFormatAndUsage( return err; } - ALOGD("set up nativeWindow %p for %dx%d, color %#x, rotation %d, usage %#x", + ALOGD("set up nativeWindow %p for %dx%d, color %#x, rotation %d, usage %#" PRIx64, nativeWindow, width, height, format, rotation, finalUsage); return NO_ERROR; } diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp index 813a257e9f..cb3d1cb3f1 100644 --- a/media/libstagefright/matroska/MatroskaExtractor.cpp +++ b/media/libstagefright/matroska/MatroskaExtractor.cpp @@ -140,6 +140,7 @@ private: enum Type { AVC, AAC, + HEVC, OTHER }; @@ -148,7 +149,7 @@ private: Type mType; bool mIsAudio; BlockIterator mBlockIter; - ssize_t mNALSizeLen; // for type AVC + ssize_t mNALSizeLen; // for type AVC or HEVC List<MediaBuffer *> mPendingFrames; @@ -244,6 +245,19 @@ MatroskaSource::MatroskaSource( } else { ALOGE("No mNALSizeLen"); } + } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) { + mType = HEVC; + + uint32_t dummy; + const uint8_t *hvcc; + size_t hvccSize; + if (meta->findData(kKeyHVCC, &dummy, (const void **)&hvcc, &hvccSize) + && hvccSize >= 22u) { + mNALSizeLen = 1 + (hvcc[14+7] & 3); + ALOGV("mNALSizeLen = %zu", mNALSizeLen); + } else { + ALOGE("No mNALSizeLen"); + } } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { mType = AAC; } @@ -343,7 +357,15 @@ void BlockIterator::advance_l() { res = mCluster->Parse(pos, len); ALOGV("Parse (2) returned %ld", res); - CHECK_GE(res, 0); + + if (res < 0) { + // I/O error + + ALOGE("Cluster::Parse returned result %ld", res); + + mCluster = NULL; + break; + } mBlockEntryIndex = 0; continue; @@ -692,7 +714,7 @@ status_t MatroskaSource::read( MediaBuffer *frame = *mPendingFrames.begin(); mPendingFrames.erase(mPendingFrames.begin()); - if (mType != AVC || mNALSizeLen == 0) { + if ((mType != AVC && mType != HEVC) || mNALSizeLen == 0) { if (targetSampleTimeUs >= 0ll) { frame->meta_data()->setInt64( kKeyTargetTime, targetSampleTimeUs); @@ -1293,6 +1315,14 @@ void MatroskaExtractor::addTracks() { if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); + } else if (!strcmp("V_MPEGH/ISO/HEVC", codecID)) { + meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC); + if (codecPrivateSize > 0) { + meta->setData(kKeyHVCC, kTypeHVCC, codecPrivate, codecPrivateSize); + } else { + ALOGW("HEVC is detected, but does not have configuration."); + continue; + } } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { if (codecPrivateSize > 0) { meta->setCString( @@ -1398,6 +1428,8 @@ void MatroskaExtractor::addTracks() { } else if (!strcmp("A_FLAC", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC); err = addFlacMetadata(meta, codecPrivate, codecPrivateSize); + } else if (!strcmp("A_AC3", codecID)) { + meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3); } else { ALOGW("%s is not supported.", codecID); continue; diff --git a/media/libstagefright/omx/1.0/WOmxNode.cpp b/media/libstagefright/omx/1.0/WOmxNode.cpp index 9f822839a6..1dc7c7b6f0 100644 --- a/media/libstagefright/omx/1.0/WOmxNode.cpp +++ b/media/libstagefright/omx/1.0/WOmxNode.cpp @@ -154,7 +154,8 @@ status_t LWOmxNode::allocateSecureBuffer( hidl_handle const& outNativeHandle) { fnStatus = toStatusT(status); *buffer = outBuffer; - *native_handle = NativeHandle::create( + *native_handle = outNativeHandle.getNativeHandle() == nullptr ? + nullptr : NativeHandle::create( native_handle_clone(outNativeHandle), true); })); return transStatus == NO_ERROR ? fnStatus : transStatus; diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp index d4cdf693af..1a00fb9506 100644 --- a/media/libstagefright/omx/Android.bp +++ b/media/libstagefright/omx/Android.bp @@ -79,6 +79,17 @@ cc_library_shared { "-Wno-documentation", ], + product_variables: { + lineage: { + needs_legacy_camera_hal1_dyn_native_handle: { + cppflags: ["-DNEEDS_LEGACY_CAMERA_HAL1_DYN_NATIVE_HANDLE"], + }, + uses_qcom_bsp_legacy: { + cppflags: ["-DQCOM_BSP_LEGACY"], + }, + }, + }, + sanitize: { misc_undefined: [ "signed-integer-overflow", diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp index 1917d2add8..f74de85c2c 100644 --- a/media/libstagefright/omx/GraphicBufferSource.cpp +++ b/media/libstagefright/omx/GraphicBufferSource.cpp @@ -776,11 +776,13 @@ status_t GraphicBufferSource::submitBuffer_l(const VideoBuffer &item) { return UNKNOWN_ERROR; } +#ifndef QCOM_BSP_LEGACY if ((android_dataspace)item.mDataspace != mLastDataspace) { onDataspaceChanged_l( item.mDataspace, (android_pixel_format)item.mBuffer->getGraphicBuffer()->format); } +#endif std::shared_ptr<AcquiredBuffer> buffer = item.mBuffer; // use a GraphicBuffer for now as OMXNodeInstance is using GraphicBuffers to hold references diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index 0c2203ab79..04866d5baf 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -500,6 +500,9 @@ status_t OMXNodeInstance::freeNode() { Mutex::Autolock _l(mLock); + if (mActiveBuffers.size() > 0) { + freeActiveBuffers(); + } status_t err = mOwner->freeNode(this); mDispatcher.clear(); @@ -1078,6 +1081,9 @@ status_t OMXNodeInstance::useBuffer( case OMXBuffer::kBufferTypeSharedMem: { if (mPortMode[portIndex] != IOMX::kPortModePresetByteBuffer +#ifdef NEEDS_LEGACY_CAMERA_HAL1_DYN_NATIVE_HANDLE + && mPortMode[portIndex] != IOMX::kPortModeDynamicNativeHandle +#endif && mPortMode[portIndex] != IOMX::kPortModeDynamicANWBuffer) { break; } diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk index f7597db816..72fd887490 100644 --- a/media/mediaserver/Android.mk +++ b/media/mediaserver/Android.mk @@ -38,4 +38,15 @@ LOCAL_INIT_RC := mediaserver.rc LOCAL_CFLAGS := -Werror -Wall +ifeq ($(TARGET_HAS_LEGACY_CAMERA_HAL1),true) + LOCAL_CFLAGS += -DNO_CAMERA_SERVER + + LOCAL_SHARED_LIBRARIES += \ + libcameraservice \ + libgui \ + libhidltransport \ + android.hardware.camera.common@1.0 \ + android.hardware.camera.provider@2.4 +endif + include $(BUILD_EXECUTABLE) diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp index ecddc48272..53b589350f 100644 --- a/media/mediaserver/main_mediaserver.cpp +++ b/media/mediaserver/main_mediaserver.cpp @@ -25,6 +25,10 @@ #include "RegisterExtensions.h" // from LOCAL_C_INCLUDES +#ifdef NO_CAMERA_SERVER +#include "CameraService.h" +#include <hidl/HidlTransportSupport.h> +#endif #include "IcuUtils.h" #include "MediaPlayerService.h" #include "ResourceManagerService.h" @@ -35,12 +39,20 @@ int main(int argc __unused, char **argv __unused) { signal(SIGPIPE, SIG_IGN); +#ifdef NO_CAMERA_SERVER + // Set 3 threads for HIDL calls + hardware::configureRpcThreadpool(3, /*willjoin*/ false); +#endif + sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm(defaultServiceManager()); ALOGI("ServiceManager: %p", sm.get()); InitializeIcuOrDie(); MediaPlayerService::instantiate(); ResourceManagerService::instantiate(); +#ifdef NO_CAMERA_SERVER + CameraService::instantiate(); +#endif registerExtensions(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp index 8d894c17d1..9139925a8e 100644 --- a/media/mtp/MtpFfsHandle.cpp +++ b/media/mtp/MtpFfsHandle.cpp @@ -614,7 +614,7 @@ int MtpFfsHandle::start() { int MtpFfsHandle::configure(bool usePtp) { // Wait till previous server invocation has closed - if (!mLock.try_lock_for(std::chrono::milliseconds(1000))) { + if (!mLock.try_lock_for(std::chrono::milliseconds(300))) { LOG(ERROR) << "MtpServer was unable to get configure lock"; return -1; } diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp index 2180462e87..89823c4ff8 100644 --- a/media/mtp/MtpServer.cpp +++ b/media/mtp/MtpServer.cpp @@ -132,7 +132,7 @@ int MtpServer::configure(bool usePtp) { int ret = sHandle->configure(usePtp); if (ret) ALOGE("Failed to configure MTP driver!"); - else android::base::SetProperty("sys.usb.ffs.mtp.ready", "1"); + android::base::SetProperty("sys.usb.ffs.mtp.ready", "1"); return ret; } @@ -158,7 +158,7 @@ void MtpServer::removeStorage(MtpStorage* storage) { MtpStorage* MtpServer::getStorage(MtpStorageID id) { if (id == 0) - return mStorages[0]; + return mStorages.empty() ? nullptr : mStorages[0]; for (size_t i = 0; i < mStorages.size(); i++) { MtpStorage* storage = mStorages[i]; if (storage->getStorageID() == id) diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp index f313e901cd..35b83d3a7f 100644 --- a/media/ndk/NdkMediaCodec.cpp +++ b/media/ndk/NdkMediaCodec.cpp @@ -367,6 +367,13 @@ AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec *mData) { } EXPORT +AMediaFormat* AMediaCodec_getBufferFormat(AMediaCodec *mData, size_t index) { + sp<AMessage> format; + mData->mCodec->getOutputFormat(index, &format); + return AMediaFormat_fromMsg(&format); +} + +EXPORT media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec *mData, size_t idx, bool render) { if (render) { return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx)); diff --git a/media/ndk/include/media/NdkMediaCodec.h b/media/ndk/include/media/NdkMediaCodec.h index 7e7e81ed0b..56f8b395e0 100644 --- a/media/ndk/include/media/NdkMediaCodec.h +++ b/media/ndk/include/media/NdkMediaCodec.h @@ -179,6 +179,12 @@ ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec*, AMediaCodecBufferInfo *inf AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec*); /** + * Get format of the buffer. The specified buffer index must have been previously obtained from + * dequeueOutputBuffer. + */ +AMediaFormat* AMediaCodec_getBufferFormat(AMediaCodec*, size_t index); + +/** * If you are done with a buffer, use this call to return the buffer to * the codec. If you previously specified a surface when configuring this * video decoder you can optionally render the buffer. diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index ff5f745f9b..e93605655e 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1611,7 +1611,8 @@ sp<IAudioRecord> AudioFlinger::openRecord( } // check calling permissions - if (!recordingAllowed(opPackageName, tid, clientUid)) { + if (!isTrustedCallingUid(callingUid) && + !recordingAllowed(opPackageName, tid, callingUid)) { ALOGE("openRecord() permission denied: recording not allowed"); lStatus = PERMISSION_DENIED; goto Exit; diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp index bd5f146a82..7b8d4dcd04 100644 --- a/services/audioflinger/Effects.cpp +++ b/services/audioflinger/Effects.cpp @@ -1590,6 +1590,10 @@ void AudioFlinger::EffectChain::clearInputBuffer() return; } clearInputBuffer_l(thread); + + for (size_t i = 0; i < mEffects.size(); i++) { + mEffects[i]->reset_l(); + } } // Must be called with EffectChain::mLock locked diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h index 7b19f58b84..05916522e6 100644 --- a/services/audiopolicy/AudioPolicyInterface.h +++ b/services/audiopolicy/AudioPolicyInterface.h @@ -354,6 +354,8 @@ public: const struct audio_config_base *clientConfig, const struct audio_config_base *deviceConfig, audio_patch_handle_t patchHandle) = 0; + virtual void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& streamInfo, bool added) = 0; + }; extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface); diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h index 804f73ffd8..1fbf3e710e 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h @@ -78,6 +78,7 @@ public: sp<AudioPort> mPort; audio_devices_t mDevice; // current device this output is routed to + audio_io_handle_t mIoHandle; // output handle uint32_t mRefCount[AUDIO_STREAM_CNT]; // number of streams of each type using this output nsecs_t mStopTime[AUDIO_STREAM_CNT]; float mCurVolume[AUDIO_STREAM_CNT]; // current stream volume in dB @@ -123,7 +124,6 @@ public: virtual void toAudioPort(struct audio_port *port) const; const sp<IOProfile> mProfile; // I/O profile this output derives from - audio_io_handle_t mIoHandle; // output handle uint32_t mLatency; // audio_output_flags_t mFlags; // wp<AudioPolicyMix> mPolicyMix; // non NULL when used by a dynamic policy diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp index 3ac3cfff8f..59aceaf007 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp @@ -34,7 +34,7 @@ namespace android { AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port, AudioPolicyClientInterface *clientInterface) - : mPort(port), mDevice(AUDIO_DEVICE_NONE), + : mPort(port), mDevice(AUDIO_DEVICE_NONE), mIoHandle(0), mClientInterface(clientInterface), mPatchHandle(AUDIO_PATCH_HANDLE_NONE), mId(0) { // clear usage count for all stream types @@ -222,7 +222,7 @@ void AudioOutputDescriptor::log(const char* indent) SwAudioOutputDescriptor::SwAudioOutputDescriptor(const sp<IOProfile>& profile, AudioPolicyClientInterface *clientInterface) : AudioOutputDescriptor(profile, clientInterface), - mProfile(profile), mIoHandle(0), mLatency(0), + mProfile(profile), mLatency(0), mFlags((audio_output_flags_t)0), mPolicyMix(NULL), mOutput1(0), mOutput2(0), mDirectOpenCount(0), mDirectClientSession(AUDIO_SESSION_NONE), mGlobalRefCount(0) diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index ed7a23b4d6..505c727684 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -3557,7 +3557,7 @@ uint32_t AudioPolicyManager::nextAudioPortGeneration() #ifdef USE_XML_AUDIO_POLICY_CONF // Treblized audio policy xml config will be located in /odm/etc or /vendor/etc. static const char *kConfigLocationList[] = - {"/odm/etc", "/vendor/etc", "/system/etc"}; + {"/odm/etc", "/vendor/etc/audio", "/vendor/etc", "/system/etc"}; static const int kConfigLocationListSize = (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0])); diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index ea8d5c884a..8356b3f7cd 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -484,12 +484,12 @@ protected: // if argument "device" is different from AUDIO_DEVICE_NONE, startSource() will force // the re-evaluation of the output device. - status_t startSource(const sp<AudioOutputDescriptor>& outputDesc, + virtual status_t startSource(const sp<AudioOutputDescriptor>& outputDesc, audio_stream_type_t stream, audio_devices_t device, const char *address, uint32_t *delayMs); - status_t stopSource(const sp<AudioOutputDescriptor>& outputDesc, + virtual status_t stopSource(const sp<AudioOutputDescriptor>& outputDesc, audio_stream_type_t stream, bool forceDeviceUpdate); @@ -594,7 +594,7 @@ protected: // Audio Policy Engine Interface. AudioPolicyManagerInterface *mEngine; -private: +protected: // Add or remove AC3 DTS encodings based on user preferences. void filterSurroundFormats(FormatVector *formatsPtr); void filterSurroundChannelMasks(ChannelsVector *channelMasksPtr); @@ -626,7 +626,7 @@ private: SortedVector<audio_io_handle_t>& outputs /*out*/); uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; } // internal method to return the output handle for the given device and format - audio_io_handle_t getOutputForDevice( + virtual audio_io_handle_t getOutputForDevice( audio_devices_t device, audio_session_t session, audio_stream_type_t stream, @@ -662,7 +662,7 @@ private: sp<AudioPolicyMix> *policyMix = NULL); // Called by setDeviceConnectionState(). - status_t setDeviceConnectionStateInt(audio_devices_t device, + virtual status_t setDeviceConnectionStateInt(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address, const char *device_name); diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp index 31c9575fcd..becf50a4ea 100644 --- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp @@ -228,6 +228,13 @@ void AudioPolicyService::AudioPolicyClient::onRecordingConfigurationUpdate( clientConfig, deviceConfig, patchHandle); } +void AudioPolicyService::AudioPolicyClient::onOutputSessionEffectsUpdate( + sp<AudioSessionInfo>& info, bool added) +{ + mAudioPolicyService->onOutputSessionEffectsUpdate(info, added); +} + + audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId(audio_unique_id_use_t use) { return AudioSystem::newAudioUniqueId(use); diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp index 84b10731dc..50d4018b3d 100644 --- a/services/audiopolicy/service/AudioPolicyEffects.cpp +++ b/services/audiopolicy/service/AudioPolicyEffects.cpp @@ -30,6 +30,7 @@ #include <utils/SortedVector.h> #include <cutils/config_utils.h> #include <binder/IPCThreadState.h> +#include "AudioPolicyService.h" #include "AudioPolicyEffects.h" #include "ServiceUtilities.h" @@ -39,7 +40,8 @@ namespace android { // AudioPolicyEffects Implementation // ---------------------------------------------------------------------------- -AudioPolicyEffects::AudioPolicyEffects() +AudioPolicyEffects::AudioPolicyEffects(AudioPolicyService *audioPolicyService) : + mAudioPolicyService(audioPolicyService) { status_t loadResult = loadAudioEffectXmlConfig(); if (loadResult < 0) { @@ -235,6 +237,8 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output, { status_t status = NO_ERROR; + ALOGV("addOutputSessionEffects %d", audioSession); + Mutex::Autolock _l(mLock); // create audio processors according to stream // FIXME: should we have specific post processing settings for internal streams? @@ -242,6 +246,22 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output, if (stream >= AUDIO_STREAM_PUBLIC_CNT) { stream = AUDIO_STREAM_MUSIC; } + + // send the streaminfo notification only once + ssize_t sidx = mOutputAudioSessionInfo.indexOfKey(audioSession); + if (sidx >= 0) { + // AudioSessionInfo is existing and we just need to increase ref count + sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(sidx); + info->mRefCount++; + + if (info->mRefCount == 1) { + mAudioPolicyService->onOutputSessionEffectsUpdate(info, true); + } + ALOGV("addOutputSessionEffects(): session info %d refCount=%d", audioSession, info->mRefCount); + } else { + ALOGV("addOutputSessionEffects(): no output stream info found for stream"); + } + ssize_t index = mOutputStreams.indexOfKey(stream); if (index < 0) { ALOGV("addOutputSessionEffects(): no output processing needed for this stream"); @@ -287,6 +307,86 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output, return status; } +status_t AudioPolicyEffects::releaseOutputAudioSessionInfo(audio_io_handle_t /* output */, + audio_stream_type_t stream, + audio_session_t session) +{ + if (uint32_t(stream) >= AUDIO_STREAM_CNT) { + return BAD_VALUE; + } + + Mutex::Autolock _l(mLock); + + ssize_t idx = mOutputAudioSessionInfo.indexOfKey(session); + if (idx >= 0) { + sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(idx); + if (info->mRefCount == 0) { + mOutputAudioSessionInfo.removeItemsAt(idx); + } + ALOGV("releaseOutputAudioSessionInfo() sessionId=%d refcount=%d", + session, info->mRefCount); + } else { + ALOGV("releaseOutputAudioSessionInfo() no session info found"); + } + return NO_ERROR; +} + +status_t AudioPolicyEffects::updateOutputAudioSessionInfo(audio_io_handle_t /* output */, + audio_stream_type_t stream, + audio_session_t session, + audio_output_flags_t flags, + const audio_config_t *config, uid_t uid) +{ + if (uint32_t(stream) >= AUDIO_STREAM_CNT) { + return BAD_VALUE; + } + + Mutex::Autolock _l(mLock); + + // TODO: Handle other stream types based on client registration + if (stream != AUDIO_STREAM_MUSIC) { + return NO_ERROR; + } + + // update AudioSessionInfo. This is used in the stream open/close path + // to notify userspace applications about session creation and + // teardown, allowing the app to make decisions about effects for + // a particular stream. This is independent of the current + // output_session_processing feature which forcibly attaches a + // static list of effects to a stream. + ssize_t idx = mOutputAudioSessionInfo.indexOfKey(session); + sp<AudioSessionInfo> info; + if (idx < 0) { + info = new AudioSessionInfo(session, stream, flags, config->channel_mask, uid); + mOutputAudioSessionInfo.add(session, info); + } else { + // the streaminfo may actually change + info = mOutputAudioSessionInfo.valueAt(idx); + info->mFlags = flags; + info->mChannelMask = config->channel_mask; + } + + ALOGV("updateOutputAudioSessionInfo() sessionId=%d, flags=0x%x, channel_mask=0x%x uid=%d refCount=%d", + info->mSessionId, info->mFlags, info->mChannelMask, info->mUid, info->mRefCount); + + return NO_ERROR; +} + +status_t AudioPolicyEffects::listAudioSessions(audio_stream_type_t streams, + Vector< sp<AudioSessionInfo>> &sessions) +{ + ALOGV("listAudioSessions() streams %d", streams); + + for (unsigned int i = 0; i < mOutputAudioSessionInfo.size(); i++) { + sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(i); + if (streams == -1 || info->mStream == streams) { + sessions.push_back(info); + } + } + + return NO_ERROR; +} + status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output, audio_stream_type_t stream, audio_session_t audioSession) @@ -296,7 +396,19 @@ status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t outpu (void) stream; // argument not used for now Mutex::Autolock _l(mLock); - ssize_t index = mOutputSessions.indexOfKey(audioSession); + ssize_t index = mOutputAudioSessionInfo.indexOfKey(audioSession); + if (index >= 0) { + sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(index); + info->mRefCount--; + if (info->mRefCount == 0) { + mAudioPolicyService->onOutputSessionEffectsUpdate(info, false); + } + ALOGV("releaseOutputSessionEffects(): session=%d refCount=%d", info->mSessionId, info->mRefCount); + } else { + ALOGV("releaseOutputSessionEffects: no stream info was attached to this stream"); + } + + index = mOutputSessions.indexOfKey(audioSession); if (index < 0) { ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream"); return NO_ERROR; diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h index 59d5d14559..04d1923218 100644 --- a/services/audiopolicy/service/AudioPolicyEffects.h +++ b/services/audiopolicy/service/AudioPolicyEffects.h @@ -28,6 +28,8 @@ namespace android { +class AudioPolicyService; + // ---------------------------------------------------------------------------- // AudioPolicyEffects class @@ -41,7 +43,7 @@ public: // The constructor will parse audio_effects.conf // First it will look whether vendor specific file exists, // otherwise it will parse the system default file. - AudioPolicyEffects(); + AudioPolicyEffects(AudioPolicyService *audioPolicyService); virtual ~AudioPolicyEffects(); // NOTE: methods on AudioPolicyEffects should never be called with the AudioPolicyService @@ -82,6 +84,19 @@ public: audio_stream_type_t stream, audio_session_t audioSession); + status_t updateOutputAudioSessionInfo(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t audioSession, + audio_output_flags_t flags, + const audio_config_t *config, uid_t uid); + + status_t releaseOutputAudioSessionInfo(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t audioSession); + + status_t listAudioSessions(audio_stream_type_t streams, + Vector< sp<AudioSessionInfo>> &sessions); + private: // class to store the description of an effects and its parameters @@ -190,6 +205,10 @@ private: KeyedVector< audio_stream_type_t, EffectDescVector* > mOutputStreams; // Automatic output effects are unique for audiosession ID KeyedVector< audio_session_t, EffectVector* > mOutputSessions; + // Stream info for session events + KeyedVector< audio_session_t, sp<AudioSessionInfo> > mOutputAudioSessionInfo; + + AudioPolicyService *mAudioPolicyService; }; }; // namespace android diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index b7bce55c4c..56367cd525 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -173,18 +173,30 @@ status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr, if (mAudioPolicyManager == NULL) { return NO_INIT; } - ALOGV("getOutput()"); - Mutex::Autolock _l(mLock); + ALOGV("getOutputForAttr()"); + status_t status = NO_ERROR; + sp<AudioPolicyEffects> audioPolicyEffects; + { + Mutex::Autolock _l(mLock); - const uid_t callingUid = IPCThreadState::self()->getCallingUid(); - if (!isTrustedCallingUid(callingUid) || uid == (uid_t)-1) { - ALOGW_IF(uid != (uid_t)-1 && uid != callingUid, - "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, uid); - uid = callingUid; + const uid_t callingUid = IPCThreadState::self()->getCallingUid(); + if (!isTrustedCallingUid(callingUid) || uid == (uid_t)-1) { + ALOGW_IF(uid != (uid_t)-1 && uid != callingUid, + "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, uid); + uid = callingUid; + } + status = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid, + config, flags, selectedDeviceId, portId); + + audioPolicyEffects = mAudioPolicyEffects; } - return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid, - config, - flags, selectedDeviceId, portId); + + if (status == NO_ERROR && audioPolicyEffects != 0) { + audioPolicyEffects->updateOutputAudioSessionInfo(*output, + *stream, session, flags, config, uid); + } + + return status; } status_t AudioPolicyService::startOutput(audio_io_handle_t output, @@ -266,8 +278,16 @@ void AudioPolicyService::doReleaseOutput(audio_io_handle_t output, audio_session_t session) { ALOGV("doReleaseOutput from tid %d", gettid()); - Mutex::Autolock _l(mLock); - mAudioPolicyManager->releaseOutput(output, stream, session); + sp<AudioPolicyEffects>audioPolicyEffects; + { + Mutex::Autolock _l(mLock); + audioPolicyEffects = mAudioPolicyEffects; + mAudioPolicyManager->releaseOutput(output, stream, session); + } + if (audioPolicyEffects != 0) { + audioPolicyEffects->releaseOutputAudioSessionInfo(output, + stream, session); + } } status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr, @@ -331,7 +351,7 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr, 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(pid, uid)) { + if (!isTrustedCallingUid(callingUid) && !captureAudioOutputAllowed(pid, uid)) { ALOGE("getInputForAttr() permission denied: capture not allowed"); status = PERMISSION_DENIED; } @@ -772,7 +792,6 @@ status_t AudioPolicyService::getMasterMono(bool *mono) return mAudioPolicyManager->getMasterMono(mono); } - float AudioPolicyService::getStreamVolumeDB( audio_stream_type_t stream, int index, audio_devices_t device) { @@ -783,5 +802,24 @@ float AudioPolicyService::getStreamVolumeDB( return mAudioPolicyManager->getStreamVolumeDB(stream, index, device); } +status_t AudioPolicyService::listAudioSessions(audio_stream_type_t streams, + Vector< sp<AudioSessionInfo>> &sessions) +{ + sp<AudioPolicyEffects> audioPolicyEffects; + { + Mutex::Autolock _l(mLock); + if (mAudioPolicyManager == NULL) { + return NO_INIT; + } + audioPolicyEffects = mAudioPolicyEffects; + } + + if (audioPolicyEffects != 0) { + return audioPolicyEffects->listAudioSessions(streams, sessions); + } + + // no errors here if effects are not available + return NO_ERROR; +} }; // namespace android diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index b417631085..b421f6d2ad 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -74,7 +74,7 @@ void AudioPolicyService::onFirstRef() mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient); } // load audio processing modules - sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects(); + sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects(this); { Mutex::Autolock _l(mLock); mAudioPolicyEffects = audioPolicyEffects; @@ -223,6 +223,21 @@ status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_co return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs); } +void AudioPolicyService::onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added) +{ + ALOGV("AudioPolicyService::onOutputSessionEffectsUpdate(%d, %d, %d)", + info->mStream, info->mSessionId, added); + mOutputCommandThread->effectSessionUpdateCommand(info, added); +} + +void AudioPolicyService::doOnOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added) +{ + Mutex::Autolock _l(mNotificationClientsLock); + for (size_t i = 0; i < mNotificationClients.size(); i++) { + mNotificationClients.valueAt(i)->onOutputSessionEffectsUpdate(info, added); + } +} + AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service, const sp<IAudioPolicyServiceClient>& client, uid_t uid) @@ -258,6 +273,14 @@ void AudioPolicyService::NotificationClient::onAudioPatchListUpdate() } } +void AudioPolicyService::NotificationClient::onOutputSessionEffectsUpdate( + sp<AudioSessionInfo>& info, bool added) +{ + if (mAudioPolicyServiceClient != 0) { + mAudioPolicyServiceClient->onOutputSessionEffectsUpdate(info, added); + } +} + void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate( const String8& regId, int32_t state) { @@ -549,6 +572,21 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() data->mPatchHandle); mLock.lock(); } break; + case EFFECT_SESSION_UPDATE: { + EffectSessionUpdateData *data = + (EffectSessionUpdateData *)command->mParam.get(); + ALOGV("AudioCommandThread() processing effect session update %d %d %d", + data->mAudioSessionInfo->mStream, data->mAudioSessionInfo->mSessionId, + data->mAdded); + svc = mService.promote(); + if (svc == 0) { + break; + } + mLock.unlock(); + svc->doOnOutputSessionEffectsUpdate(data->mAudioSessionInfo, data->mAdded); + mLock.lock(); + } break; + default: ALOGW("AudioCommandThread() unknown command %d", command->mCommand); } @@ -828,6 +866,20 @@ void AudioPolicyService::AudioCommandThread::recordingConfigurationUpdateCommand sendCommand(command); } +void AudioPolicyService::AudioCommandThread::effectSessionUpdateCommand( + sp<AudioSessionInfo>& streamInfo, bool added) +{ + sp<AudioCommand> command = new AudioCommand(); + command->mCommand = EFFECT_SESSION_UPDATE; + EffectSessionUpdateData *data = new EffectSessionUpdateData(); + data->mAudioSessionInfo = streamInfo; + data->mAdded = added; + command->mParam = data; + ALOGV("AudioCommandThread() sending effect session update (id=%d) for stream %d (added=%d)", + streamInfo->mStream, streamInfo->mSessionId, added); + sendCommand(command); +} + status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs) { { diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h index 38d4b179fa..0525ba13fe 100644 --- a/services/audiopolicy/service/AudioPolicyService.h +++ b/services/audiopolicy/service/AudioPolicyService.h @@ -205,6 +205,9 @@ public: virtual float getStreamVolumeDB( audio_stream_type_t stream, int index, audio_devices_t device); + virtual status_t listAudioSessions(audio_stream_type_t stream, + Vector< sp<AudioSessionInfo>>& sessions); + status_t doStopOutput(audio_io_handle_t output, audio_stream_type_t stream, audio_session_t session); @@ -235,6 +238,9 @@ public: const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle); + void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added); + void doOnOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added); + private: AudioPolicyService() ANDROID_API; virtual ~AudioPolicyService(); @@ -266,7 +272,8 @@ private: UPDATE_AUDIOPATCH_LIST, SET_AUDIOPORT_CONFIG, DYN_POLICY_MIX_STATE_UPDATE, - RECORDING_CONFIGURATION_UPDATE + RECORDING_CONFIGURATION_UPDATE, + EFFECT_SESSION_UPDATE, }; AudioCommandThread (String8 name, const wp<AudioPolicyService>& service); @@ -312,6 +319,7 @@ private: const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle); void insertCommand_l(AudioCommand *command, int delayMs = 0); + void effectSessionUpdateCommand(sp<AudioSessionInfo>& info, bool added); private: class AudioCommandData; @@ -410,6 +418,12 @@ private: audio_patch_handle_t mPatchHandle; }; + class EffectSessionUpdateData : public AudioCommandData { + public: + sp<AudioSessionInfo> mAudioSessionInfo; + bool mAdded; + }; + Mutex mLock; Condition mWaitWorkCV; Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands @@ -523,6 +537,9 @@ private: virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use); + virtual void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added); + + private: AudioPolicyService *mAudioPolicyService; }; @@ -544,7 +561,8 @@ private: const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle); void setAudioPortCallbacksEnabled(bool enabled); - + void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, + bool added); // IBinder::DeathRecipient virtual void binderDied(const wp<IBinder>& who); diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk index 7ec3ccbb51..762959430e 100644 --- a/services/camera/libcameraservice/Android.mk +++ b/services/camera/libcameraservice/Android.mk @@ -80,6 +80,12 @@ LOCAL_SHARED_LIBRARIES:= \ android.hardware.camera.device@3.2 \ android.hardware.camera.device@3.3 +ifeq ($(TARGET_USES_QTI_CAMERA_DEVICE), true) +LOCAL_CFLAGS += -DQTI_CAMERA_DEVICE +LOCAL_SHARED_LIBRARIES += \ + vendor.qti.hardware.camera.device@1.0 +endif + LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder libcamera_client libfmq LOCAL_C_INCLUDES += \ @@ -94,6 +100,10 @@ LOCAL_CFLAGS += -Wall -Wextra -Werror # Workaround for invalid unused-lambda-capture warning http://b/38349491 LOCAL_CLANG_CFLAGS += -Wno-error=unused-lambda-capture +ifeq ($(TARGET_HAS_LEGACY_CAMERA_HAL1),true) + LOCAL_CFLAGS += -DNO_CAMERA_SERVER +endif + LOCAL_MODULE:= libcameraservice include $(BUILD_SHARED_LIBRARY) diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 20bd5e4479..3755d55cdb 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -744,7 +744,11 @@ int32_t CameraService::mapToInterface(StatusInternal status) { Status CameraService::initializeShimMetadata(int cameraId) { int uid = getCallingUid(); +#ifdef NO_CAMERA_SERVER + String16 internalPackageName("media"); +#else String16 internalPackageName("cameraserver"); +#endif String8 id = String8::format("%d", cameraId); Status ret = Status::ok(); sp<Client> tmp = nullptr; @@ -825,7 +829,9 @@ Status CameraService::getLegacyParametersLazy(int cameraId, static bool isTrustedCallingUid(uid_t uid) { switch (uid) { case AID_MEDIA: // mediaserver +#ifndef NO_CAMERA_SERVER case AID_CAMERASERVER: // cameraserver +#endif case AID_RADIO: // telephony return true; default: diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp index 2cf648f111..585d2ebd5f 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.cpp +++ b/services/camera/libcameraservice/api1/Camera2Client.cpp @@ -859,6 +859,12 @@ status_t Camera2Client::startPreviewL(Parameters ¶ms, bool restart) { outputStreams.push(getPreviewStreamId()); + if (params.isDeviceZslSupported) { + // If device ZSL is supported, resume preview buffers that may be paused + // during last takePicture(). + mDevice->dropStreamBuffers(false, getPreviewStreamId()); + } + if (!params.recordingHint) { if (!restart) { res = mStreamingProcessor->updatePreviewRequest(params); diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp index a407d0bb59..48757acdfc 100644 --- a/services/camera/libcameraservice/api1/CameraClient.cpp +++ b/services/camera/libcameraservice/api1/CameraClient.cpp @@ -59,6 +59,9 @@ CameraClient::CameraClient(const sp<CameraService>& cameraService, mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT); mLegacyMode = legacyMode; mPlayShutterSound = true; + + mLongshotEnabled = false; + mBurstCnt = 0; LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId); } @@ -365,12 +368,14 @@ status_t CameraClient::setPreviewCallbackTarget( // start preview mode status_t CameraClient::startPreview() { + Mutex::Autolock lock(mLock); LOG1("startPreview (pid %d)", getCallingPid()); return startCameraMode(CAMERA_PREVIEW_MODE); } // start recording mode status_t CameraClient::startRecording() { + Mutex::Autolock lock(mLock); LOG1("startRecording (pid %d)", getCallingPid()); return startCameraMode(CAMERA_RECORDING_MODE); } @@ -378,7 +383,6 @@ status_t CameraClient::startRecording() { // start preview or recording status_t CameraClient::startCameraMode(camera_mode mode) { LOG1("startCameraMode(%d)", mode); - Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; @@ -659,6 +663,10 @@ status_t CameraClient::takePicture(int msgType) { CAMERA_MSG_COMPRESSED_IMAGE); enableMsgType(picMsgType); + mBurstCnt = mHardware->getParameters().getInt("num-snaps-per-shutter"); + if(mBurstCnt <= 0) + mBurstCnt = 1; + LOG1("mBurstCnt = %d", mBurstCnt); return mHardware->takePicture(); } @@ -760,6 +768,20 @@ status_t CameraClient::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) { } else if (cmd == CAMERA_CMD_PING) { // If mHardware is 0, checkPidAndHardware will return error. return OK; + } else if (cmd == CAMERA_CMD_HISTOGRAM_ON) { + enableMsgType(CAMERA_MSG_STATS_DATA); + } else if (cmd == CAMERA_CMD_HISTOGRAM_OFF) { + disableMsgType(CAMERA_MSG_STATS_DATA); + } else if (cmd == CAMERA_CMD_METADATA_ON) { + enableMsgType(CAMERA_MSG_META_DATA); + } else if (cmd == CAMERA_CMD_METADATA_OFF) { + disableMsgType(CAMERA_MSG_META_DATA); + } else if ( cmd == CAMERA_CMD_LONGSHOT_ON ) { + mLongshotEnabled = true; + } else if ( cmd == CAMERA_CMD_LONGSHOT_OFF ) { + mLongshotEnabled = false; + disableMsgType(CAMERA_MSG_SHUTTER); + disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); } return mHardware->sendCommand(cmd, arg1, arg2); @@ -955,7 +977,9 @@ void CameraClient::handleShutter(void) { c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0); if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return; } - disableMsgType(CAMERA_MSG_SHUTTER); + if ( !mLongshotEnabled ) { + disableMsgType(CAMERA_MSG_SHUTTER); + } // Shutters only happen in response to takePicture, so mark device as // idle now, until preview is restarted @@ -1040,7 +1064,13 @@ void CameraClient::handleRawPicture(const sp<IMemory>& mem) { // picture callback - compressed picture ready void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) { - disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); + if (mBurstCnt) + mBurstCnt--; + + if (!mBurstCnt && !mLongshotEnabled) { + LOG1("handleCompressedPicture mBurstCnt = %d", mBurstCnt); + disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); + } sp<hardware::ICameraClient> c = mRemoteCallback; mLock.unlock(); diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h index 7f93fef93c..a0d9d0add4 100644 --- a/services/camera/libcameraservice/api1/CameraClient.h +++ b/services/camera/libcameraservice/api1/CameraClient.h @@ -178,6 +178,9 @@ private: // This function keeps trying to grab mLock, or give up if the message // is found to be disabled. It returns true if mLock is grabbed. bool lockIfMessageWanted(int32_t msgType); + + bool mLongshotEnabled; + int mBurstCnt; }; } diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp index b65f1c76ca..1ee216fd9a 100644 --- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp +++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp @@ -553,6 +553,12 @@ CaptureSequencer::CaptureState CaptureSequencer::manageStandardCapture( return DONE; } + if (l.mParameters.isDeviceZslSupported) { + // If device ZSL is supported, drop all pending preview buffers to reduce the chance of + // rendering preview frames newer than the still frame. + client->getCameraDevice()->dropStreamBuffers(true, client->getPreviewStreamId()); + } + /** * Clear the streaming request for still-capture pictures * (as opposed to i.e. video snapshots) diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h index 3919bfa7c8..a90050e1bf 100644 --- a/services/camera/libcameraservice/common/CameraDeviceBase.h +++ b/services/camera/libcameraservice/common/CameraDeviceBase.h @@ -349,6 +349,11 @@ class CameraDeviceBase : public virtual RefBase { virtual status_t setConsumerSurfaces(int streamId, const std::vector<sp<Surface>>& consumers) = 0; + /** + * Drop buffers for stream of streamId if dropping is true. If dropping is false, do not + * drop buffers for stream of streamId. + */ + virtual status_t dropStreamBuffers(bool /*dropping*/, int /*streamId*/) = 0; }; }; // namespace android diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp index 522d521b5b..498485430e 100644 --- a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp +++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp @@ -136,6 +136,27 @@ hardware::Return<void> CameraHardwareInterface::dataCallback( return hardware::Void(); } +#ifdef QTI_CAMERA_DEVICE +hardware::Return<void> CameraHardwareInterface::QDataCallback( + DataCallbackMsg msgType, uint32_t data, uint32_t bufferIndex, + const vendor::qti::hardware::camera::device::V1_0::QCameraFrameMetadata& metadata) { + camera_memory_t* mem = nullptr; + { + std::lock_guard<std::mutex> lock(mHidlMemPoolMapLock); + if (mHidlMemPoolMap.count(data) == 0) { + ALOGE("%s: memory pool ID %d not found", __FUNCTION__, data); + return hardware::Void(); + } + mem = mHidlMemPoolMap.at(data); + } + camera_frame_metadata_t md; + md.number_of_faces = metadata.faces.size(); + md.faces = (camera_face_t*) metadata.faces.data(); + sDataCb((int32_t) msgType, mem, bufferIndex, &md, this); + return hardware::Void(); +} +#endif + hardware::Return<void> CameraHardwareInterface::dataCallbackTimestamp( DataCallbackMsg msgType, uint32_t data, uint32_t bufferIndex, int64_t timestamp) { @@ -579,12 +600,16 @@ void CameraHardwareInterface::releaseRecordingFrame(const sp<IMemory>& mem) if (CC_LIKELY(mHidlDevice != nullptr)) { if (size == sizeof(VideoNativeHandleMetadata)) { VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*) mem->pointer(); - // Caching the handle here because md->pHandle will be subject to HAL's edit - native_handle_t* nh = md->pHandle; - hidl_handle frame = nh; - mHidlDevice->releaseRecordingFrameHandle(heapId, bufferIndex, frame); - native_handle_close(nh); - native_handle_delete(nh); + if (md->eType == kMetadataBufferTypeNativeHandleSource) { + // Caching the handle here because md->pHandle will be subject to HAL's edit + native_handle_t* nh = md->pHandle; + hidl_handle frame = nh; + mHidlDevice->releaseRecordingFrameHandle(heapId, bufferIndex, frame); + native_handle_close(nh); + native_handle_delete(nh); + } else { + mHidlDevice->releaseRecordingFrame(heapId, bufferIndex); + } } else { mHidlDevice->releaseRecordingFrame(heapId, bufferIndex); } diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h index e519b04cdd..4a20b6a597 100644 --- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h +++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h @@ -29,6 +29,9 @@ #include <hardware/camera.h> #include <common/CameraProviderManager.h> +#ifdef QTI_CAMERA_DEVICE +#include <vendor/qti/hardware/camera/device/1.0/IQCameraDeviceCallback.h> +#endif namespace android { @@ -85,7 +88,11 @@ typedef void (*data_callback_timestamp_batch)( class CameraHardwareInterface : public virtual RefBase, +#ifdef QTI_CAMERA_DEVICE + public virtual vendor::qti::hardware::camera::device::V1_0::IQCameraDeviceCallback, +#else public virtual hardware::camera::device::V1_0::ICameraDeviceCallback, +#endif public virtual hardware::camera::device::V1_0::ICameraDevicePreviewCallback { public: @@ -395,6 +402,12 @@ private: hardware::camera::device::V1_0::DataCallbackMsg msgType, const hardware::hidl_vec< hardware::camera::device::V1_0::HandleTimestampMessage>&) override; +#ifdef QTI_CAMERA_DEVICE + hardware::Return<void> QDataCallback( + hardware::camera::device::V1_0::DataCallbackMsg msgType, + uint32_t data, uint32_t bufferIndex, + const vendor::qti::hardware::camera::device::V1_0::QCameraFrameMetadata& metadata) override; +#endif /** * Implementation of android::hardware::camera::device::V1_0::ICameraDevicePreviewCallback diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index ced1d3af42..a980cde235 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -1977,6 +1977,20 @@ status_t Camera3Device::setConsumerSurfaces(int streamId, return OK; } +status_t Camera3Device::dropStreamBuffers(bool dropping, int streamId) { + Mutex::Autolock il(mInterfaceLock); + Mutex::Autolock l(mLock); + + int idx = mOutputStreams.indexOfKey(streamId); + if (idx == NAME_NOT_FOUND) { + ALOGE("%s: Stream %d is not found.", __FUNCTION__, streamId); + return BAD_VALUE; + } + + sp<Camera3OutputStreamInterface> stream = mOutputStreams.editValueAt(idx); + return stream->dropBuffers(dropping); +} + /** * Camera3Device private methods */ diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index fbbbd08ce9..081af1978b 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -178,6 +178,12 @@ class Camera3Device : */ status_t setConsumerSurfaces(int streamId, const std::vector<sp<Surface>>& consumers) override; + /** + * Drop buffers for stream of streamId if dropping is true. If dropping is false, do not + * drop buffers for stream of streamId. + */ + status_t dropStreamBuffers(bool dropping, int streamId) override; + private: // internal typedefs diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp index 6e2978f164..84fb8909d8 100644 --- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp +++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp @@ -108,6 +108,10 @@ bool Camera3DummyStream::isConsumerConfigurationDeferred(size_t /*surface_id*/) return false; } +status_t Camera3DummyStream::dropBuffers(bool /*dropping*/) { + return OK; +} + status_t Camera3DummyStream::setConsumers(const std::vector<sp<Surface>>& /*consumers*/) { ALOGE("%s: Stream %d: Dummy stream doesn't support set consumer surface!", __FUNCTION__, mId); diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.h b/services/camera/libcameraservice/device3/Camera3DummyStream.h index 492fb49eb1..9710765c2a 100644 --- a/services/camera/libcameraservice/device3/Camera3DummyStream.h +++ b/services/camera/libcameraservice/device3/Camera3DummyStream.h @@ -57,6 +57,12 @@ class Camera3DummyStream : virtual status_t detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd); /** + * Drop buffers for stream of streamId if dropping is true. If dropping is false, do not + * drop buffers for stream of streamId. + */ + virtual status_t dropBuffers(bool /*dropping*/) override; + + /** * Return if this output stream is for video encoding. */ bool isVideoStream() const; diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp index dcaefe374e..8460c34d00 100644 --- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp +++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp @@ -44,6 +44,7 @@ Camera3OutputStream::Camera3OutputStream(int id, mUseBufferManager(false), mTimestampOffset(timestampOffset), mConsumerUsage(0), + mDropBuffers(false), mDequeueBufferLatency(kDequeueLatencyBinSize) { if (mConsumer == NULL) { @@ -70,6 +71,7 @@ Camera3OutputStream::Camera3OutputStream(int id, mUseBufferManager(false), mTimestampOffset(timestampOffset), mConsumerUsage(0), + mDropBuffers(false), mDequeueBufferLatency(kDequeueLatencyBinSize) { if (format != HAL_PIXEL_FORMAT_BLOB && format != HAL_PIXEL_FORMAT_RAW_OPAQUE) { @@ -100,6 +102,7 @@ Camera3OutputStream::Camera3OutputStream(int id, mUseBufferManager(false), mTimestampOffset(timestampOffset), mConsumerUsage(consumerUsage), + mDropBuffers(false), mDequeueBufferLatency(kDequeueLatencyBinSize) { // Deferred consumer only support preview surface format now. if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) { @@ -139,6 +142,7 @@ Camera3OutputStream::Camera3OutputStream(int id, camera3_stream_type_t type, mUseBufferManager(false), mTimestampOffset(timestampOffset), mConsumerUsage(consumerUsage), + mDropBuffers(false), mDequeueBufferLatency(kDequeueLatencyBinSize) { if (setId > CAMERA3_STREAM_SET_ID_INVALID) { @@ -227,9 +231,14 @@ status_t Camera3OutputStream::returnBufferCheckedLocked( /** * Return buffer back to ANativeWindow */ - if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { + if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR || mDropBuffers) { // Cancel buffer - ALOGW("A frame is dropped for stream %d", mId); + if (mDropBuffers) { + ALOGV("%s: Dropping a frame for stream %d.", __FUNCTION__, mId); + } else { + ALOGW("%s: A frame is dropped for stream %d due to buffer error.", __FUNCTION__, mId); + } + res = currentConsumer->cancelBuffer(currentConsumer.get(), anwBuffer, anwReleaseFence); @@ -777,6 +786,12 @@ status_t Camera3OutputStream::detachBufferLocked(sp<GraphicBuffer>* buffer, int* return res; } +status_t Camera3OutputStream::dropBuffers(bool dropping) { + Mutex::Autolock l(mLock); + mDropBuffers = dropping; + return OK; +} + status_t Camera3OutputStream::notifyBufferReleased(ANativeWindowBuffer* /*anwBuffer*/) { return OK; } diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h index 7023d5d623..4865be7d31 100644 --- a/services/camera/libcameraservice/device3/Camera3OutputStream.h +++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h @@ -166,6 +166,11 @@ class Camera3OutputStream : virtual status_t notifyBufferReleased(ANativeWindowBuffer *anwBuffer); /** + * Drop buffers if dropping is true. If dropping is false, do not drop buffers. + */ + virtual status_t dropBuffers(bool dropping) override; + + /** * Set the graphic buffer manager to get/return the stream buffers. * * It is only legal to call this method when stream is in STATE_CONSTRUCTED state. @@ -247,6 +252,9 @@ class Camera3OutputStream : */ uint64_t mConsumerUsage; + // Whether to drop valid buffers. + bool mDropBuffers; + /** * Internal Camera3Stream interface */ diff --git a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h index 8107dd02b0..1719d74a1c 100644 --- a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h +++ b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h @@ -59,6 +59,11 @@ class Camera3OutputStreamInterface : public virtual Camera3StreamInterface { * */ virtual status_t detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd) = 0; + + /** + * Drop buffers if dropping is true. If dropping is false, do not drop buffers. + */ + virtual status_t dropBuffers(bool /*dropping*/) = 0; }; } // namespace camera3 diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp index 22519a32fd..f2caaa65f5 100644 --- a/services/soundtrigger/SoundTriggerHwService.cpp +++ b/services/soundtrigger/SoundTriggerHwService.cpp @@ -256,6 +256,37 @@ void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognitio if (module == NULL) { return; } + struct sound_trigger_phrase_recognition_event newEvent; + if (event-> type == SOUND_MODEL_TYPE_KEYPHRASE && event->data_size != 0 + && event->data_offset != sizeof(struct sound_trigger_phrase_recognition_event)) { + // set some defaults for the phrase if the recognition event won't be parsed properly + // TODO: read defaults from the config + + memset(&newEvent, 0, sizeof(struct sound_trigger_phrase_recognition_event)); + + sp<Model> model = module->getModel(event->model); + + newEvent.num_phrases = 1; + newEvent.phrase_extras[0].id = 100; + newEvent.phrase_extras[0].recognition_modes = RECOGNITION_MODE_VOICE_TRIGGER; + newEvent.phrase_extras[0].confidence_level = 100; + newEvent.phrase_extras[0].num_levels = 1; + newEvent.phrase_extras[0].levels[0].level = 100; + newEvent.phrase_extras[0].levels[0].user_id = 100; + newEvent.common.status = event->status; + newEvent.common.type = event->type; + newEvent.common.model = event->model; + newEvent.common.capture_available = event->capture_available; + newEvent.common.capture_session = event->capture_session; + newEvent.common.capture_delay_ms = event->capture_delay_ms; + newEvent.common.capture_preamble_ms = event->capture_preamble_ms; + newEvent.common.trigger_in_data = event->trigger_in_data; + newEvent.common.audio_config = event->audio_config; + newEvent.common.data_size = event->data_size; + newEvent.common.data_offset = sizeof(struct sound_trigger_phrase_recognition_event); + + event = &newEvent.common; + } sp<IMemory> eventMemory = prepareRecognitionEvent_l(event); if (eventMemory == 0) { return; |