Merge "audio policy: fix merging error for commit 112b0af8."
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 20a23e0..3505154 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -25,6 +25,7 @@
const int OutputConfiguration::INVALID_ROTATION = -1;
+const int OutputConfiguration::INVALID_SET_ID = -1;
// Read empty strings without printing a false error message.
String16 OutputConfiguration::readMaybeEmptyString16(const Parcel& parcel) {
@@ -45,6 +46,10 @@
return mRotation;
}
+int OutputConfiguration::getSurfaceSetID() const {
+ return mSurfaceSetID;
+}
+
OutputConfiguration::OutputConfiguration(const Parcel& parcel) {
status_t err;
int rotation = 0;
@@ -55,24 +60,36 @@
return;
}
+ int setID = INVALID_SET_ID;
+ if ((err = parcel.readInt32(&setID)) != OK) {
+ ALOGE("%s: Failed to read surface set ID from parcel", __FUNCTION__);
+ mGbp = NULL;
+ mSurfaceSetID = INVALID_SET_ID;
+ return;
+ }
+
String16 name = readMaybeEmptyString16(parcel);
const sp<IGraphicBufferProducer>& gbp =
interface_cast<IGraphicBufferProducer>(parcel.readStrongBinder());
mGbp = gbp;
mRotation = rotation;
+ mSurfaceSetID = setID;
ALOGV("%s: OutputConfiguration: bp = %p, name = %s", __FUNCTION__,
gbp.get(), String8(name).string());
}
-OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation) {
+OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
+ int surfaceSetID) {
mGbp = gbp;
mRotation = rotation;
+ mSurfaceSetID = surfaceSetID;
}
status_t OutputConfiguration::writeToParcel(Parcel& parcel) const {
parcel.writeInt32(mRotation);
+ parcel.writeInt32(mSurfaceSetID);
parcel.writeString16(String16("unknown_name")); // name of surface
sp<IBinder> b(IInterface::asBinder(mGbp));
parcel.writeStrongBinder(b);
diff --git a/camera/ndk/Android.mk b/camera/ndk/Android.mk
new file mode 100644
index 0000000..a7c96aa
--- /dev/null
+++ b/camera/ndk/Android.mk
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2015 The Android Open Source 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+ifneq ($(TARGET_BUILD_PDK), true)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ NdkCameraManager.cpp \
+ NdkCameraMetadata.cpp \
+ NdkCameraDevice.cpp \
+ NdkCaptureRequest.cpp \
+ NdkCameraCaptureSession.cpp \
+ impl/ACameraManager.cpp \
+ impl/ACameraMetadata.cpp \
+ impl/ACameraDevice.cpp \
+ impl/ACameraCaptureSession.cpp
+
+LOCAL_MODULE:= libcamera2ndk
+
+LOCAL_C_INCLUDES := \
+ system/media/camera/include \
+ frameworks/av/include/camera/ndk
+
+LOCAL_CFLAGS += -fvisibility=hidden -D EXPORT='__attribute__ ((visibility ("default")))'
+
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ liblog \
+ libgui \
+ libutils \
+ libandroid_runtime \
+ libcamera_client \
+ libstagefright_foundation \
+ libcutils \
+
+LOCAL_CLANG := true
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
new file mode 100644
index 0000000..ab93bd6
--- /dev/null
+++ b/camera/ndk/NdkCameraCaptureSession.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NdkCameraCaptureSession"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+
+#include <utils/Log.h>
+#include <utils/Mutex.h>
+#include <utils/StrongPointer.h>
+#include <utils/Trace.h>
+
+#include "NdkCameraDevice.h"
+#include <NdkCaptureRequest.h>
+#include <NdkCameraCaptureSession.h>
+#include "impl/ACameraCaptureSession.h"
+
+using namespace android;
+
+EXPORT
+void ACameraCaptureSession_close(ACameraCaptureSession* session) {
+ ATRACE_CALL();
+ if (session != nullptr) {
+ session->closeByApp();
+ }
+ return;
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_getDevice(
+ ACameraCaptureSession* session, ACameraDevice **device) {
+ ATRACE_CALL();
+ if (session == nullptr || device == nullptr) {
+ ALOGE("%s: Error: invalid input: session %p, device %p",
+ __FUNCTION__, session, device);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (session->isClosed()) {
+ ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+ *device = nullptr;
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ *device = session->getDevice();
+ if (*device == nullptr) {
+ // Should not reach here
+ ALOGE("%s: unknown failure: device is null", __FUNCTION__);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_capture(
+ ACameraCaptureSession* session, /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ if (session == nullptr || requests == nullptr || numRequests < 1) {
+ ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+ __FUNCTION__, session, numRequests, requests);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (session->isClosed()) {
+ ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+ *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ return session->capture(cbs, numRequests, requests, captureSequenceId);
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_setRepeatingRequest(
+ ACameraCaptureSession* session, /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ if (session == nullptr || requests == nullptr || numRequests < 1) {
+ ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+ __FUNCTION__, session, numRequests, requests);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (session->isClosed()) {
+ ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+ *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ return session->setRepeatingRequest(cbs, numRequests, requests, captureSequenceId);
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_stopRepeating(ACameraCaptureSession* session) {
+ ATRACE_CALL();
+ if (session == nullptr) {
+ ALOGE("%s: Error: session is null", __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (session->isClosed()) {
+ ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+ return session->stopRepeating();
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_abortCaptures(ACameraCaptureSession*) {
+ ATRACE_CALL();
+ return ACAMERA_OK;
+}
diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp
new file mode 100644
index 0000000..281d3e7
--- /dev/null
+++ b/camera/ndk/NdkCameraDevice.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NdkCameraDevice"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include <NdkCameraDevice.h>
+#include "impl/ACameraCaptureSession.h"
+
+using namespace android;
+
+EXPORT
+camera_status_t ACameraDevice_close(ACameraDevice* device) {
+ ATRACE_CALL();
+ if (device == nullptr) {
+ ALOGE("%s: invalid argument! device is null", __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ delete device;
+ return ACAMERA_OK;
+}
+
+EXPORT
+const char* ACameraDevice_getId(const ACameraDevice* device) {
+ ATRACE_CALL();
+ if (device == nullptr) {
+ ALOGE("%s: invalid argument! device is null", __FUNCTION__);
+ return nullptr;
+ }
+ return device->getId();
+}
+
+EXPORT
+camera_status_t ACameraDevice_createCaptureRequest(
+ const ACameraDevice* device,
+ ACameraDevice_request_template templateId,
+ ACaptureRequest** request) {
+ ATRACE_CALL();
+ if (device == nullptr || request == nullptr) {
+ ALOGE("%s: invalid argument! device %p request %p",
+ __FUNCTION__, device, request);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ switch (templateId) {
+ case TEMPLATE_PREVIEW:
+ case TEMPLATE_STILL_CAPTURE:
+ case TEMPLATE_RECORD:
+ case TEMPLATE_VIDEO_SNAPSHOT:
+ case TEMPLATE_ZERO_SHUTTER_LAG:
+ case TEMPLATE_MANUAL:
+ break;
+ default:
+ ALOGE("%s: unknown template ID %d", __FUNCTION__, templateId);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return device->createCaptureRequest(templateId, request);
+}
+
+EXPORT
+camera_status_t ACaptureSessionOutputContainer_create(
+ /*out*/ACaptureSessionOutputContainer** out) {
+ ATRACE_CALL();
+ if (out == nullptr) {
+ ALOGE("%s: Error: out null", __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ *out = new ACaptureSessionOutputContainer();
+ return ACAMERA_OK;
+}
+
+EXPORT
+void ACaptureSessionOutputContainer_free(ACaptureSessionOutputContainer* container) {
+ ATRACE_CALL();
+ if (container != nullptr) {
+ delete container;
+ }
+ return;
+}
+
+EXPORT
+camera_status_t ACaptureSessionOutput_create(
+ ANativeWindow* window, /*out*/ACaptureSessionOutput** out) {
+ ATRACE_CALL();
+ if (window == nullptr || out == nullptr) {
+ ALOGE("%s: Error: bad argument. window %p, out %p",
+ __FUNCTION__, window, out);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ *out = new ACaptureSessionOutput(window);
+ return ACAMERA_OK;
+}
+
+EXPORT
+void ACaptureSessionOutput_free(ACaptureSessionOutput* output) {
+ ATRACE_CALL();
+ if (output != nullptr) {
+ delete output;
+ }
+ return;
+}
+
+EXPORT
+camera_status_t ACaptureSessionOutputContainer_add(
+ ACaptureSessionOutputContainer* container, const ACaptureSessionOutput* output) {
+ ATRACE_CALL();
+ if (container == nullptr || output == nullptr) {
+ ALOGE("%s: Error: invalid input: container %p, output %p",
+ __FUNCTION__, container, output);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ auto pair = container->mOutputs.insert(*output);
+ if (!pair.second) {
+ ALOGW("%s: output %p already exists!", __FUNCTION__, output);
+ }
+ return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACaptureSessionOutputContainer_remove(
+ ACaptureSessionOutputContainer* container, const ACaptureSessionOutput* output) {
+ ATRACE_CALL();
+ if (container == nullptr || output == nullptr) {
+ ALOGE("%s: Error: invalid input: container %p, output %p",
+ __FUNCTION__, container, output);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ container->mOutputs.erase(*output);
+ return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACameraDevice_createCaptureSession(
+ ACameraDevice* device,
+ const ACaptureSessionOutputContainer* outputs,
+ const ACameraCaptureSession_stateCallbacks* callbacks,
+ /*out*/ACameraCaptureSession** session) {
+ ATRACE_CALL();
+ if (device == nullptr || outputs == nullptr || callbacks == nullptr || session == nullptr) {
+ ALOGE("%s: Error: invalid input: device %p, outputs %p, callbacks %p, session %p",
+ __FUNCTION__, device, outputs, callbacks, session);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return device->createCaptureSession(outputs, callbacks, session);
+}
diff --git a/camera/ndk/NdkCameraManager.cpp b/camera/ndk/NdkCameraManager.cpp
new file mode 100644
index 0000000..7d9f84b
--- /dev/null
+++ b/camera/ndk/NdkCameraManager.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NdkCameraManager"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include <NdkCameraManager.h>
+#include "impl/ACameraManager.h"
+
+EXPORT
+ACameraManager* ACameraManager_create() {
+ ATRACE_CALL();
+ return new ACameraManager();
+}
+
+EXPORT
+void ACameraManager_delete(ACameraManager* manager) {
+ ATRACE_CALL();
+ if (manager != nullptr) {
+ delete manager;
+ }
+}
+
+EXPORT
+camera_status_t ACameraManager_getCameraIdList(
+ ACameraManager* manager, ACameraIdList** cameraIdList) {
+ ATRACE_CALL();
+ if (manager == nullptr || cameraIdList == nullptr) {
+ ALOGE("%s: invalid argument! manager %p, cameraIdList %p",
+ __FUNCTION__, manager, cameraIdList);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return manager->getCameraIdList(cameraIdList);
+}
+
+EXPORT
+void ACameraManager_deleteCameraIdList(ACameraIdList* cameraIdList) {
+ ATRACE_CALL();
+ if (cameraIdList != nullptr) {
+ ACameraManager::deleteCameraIdList(cameraIdList);
+ }
+}
+
+EXPORT
+camera_status_t ACameraManager_registerAvailabilityCallback(
+ ACameraManager*, const ACameraManager_AvailabilityCallbacks *callback) {
+ ATRACE_CALL();
+ if (callback == nullptr) {
+ ALOGE("%s: invalid argument! callback is null!", __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ if (callback->onCameraAvailable == nullptr || callback->onCameraUnavailable == nullptr) {
+ ALOGE("%s: invalid argument! callback %p, "
+ "onCameraAvailable %p, onCameraUnavailable %p",
+ __FUNCTION__, callback,
+ callback->onCameraAvailable, callback->onCameraUnavailable);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ CameraManagerGlobal::getInstance().registerAvailabilityCallback(callback);
+ return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACameraManager_unregisterAvailabilityCallback(
+ ACameraManager*, const ACameraManager_AvailabilityCallbacks *callback) {
+ ATRACE_CALL();
+ if (callback == nullptr) {
+ ALOGE("%s: invalid argument! callback is null!", __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ if (callback->onCameraAvailable == nullptr || callback->onCameraUnavailable == nullptr) {
+ ALOGE("%s: invalid argument! callback %p, "
+ "onCameraAvailable %p, onCameraUnavailable %p",
+ __FUNCTION__, callback,
+ callback->onCameraAvailable, callback->onCameraUnavailable);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ CameraManagerGlobal::getInstance().unregisterAvailabilityCallback(callback);
+ return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACameraManager_getCameraCharacteristics(
+ ACameraManager* mgr, const char* cameraId, ACameraMetadata** chars){
+ ATRACE_CALL();
+ if (mgr == nullptr || cameraId == nullptr || chars == nullptr) {
+ ALOGE("%s: invalid argument! mgr %p cameraId %p chars %p",
+ __FUNCTION__, mgr, cameraId, chars);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return mgr->getCameraCharacteristics(cameraId, chars);
+}
+
+EXPORT
+camera_status_t ACameraManager_openCamera(
+ ACameraManager* mgr, const char* cameraId,
+ ACameraDevice_StateCallbacks* callback,
+ /*out*/ACameraDevice** device) {
+ ATRACE_CALL();
+ if (mgr == nullptr || cameraId == nullptr || callback == nullptr || device == nullptr) {
+ ALOGE("%s: invalid argument! mgr %p cameraId %p callback %p device %p",
+ __FUNCTION__, mgr, cameraId, callback, device);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return mgr->openCamera(cameraId, callback, device);
+}
diff --git a/camera/ndk/NdkCameraMetadata.cpp b/camera/ndk/NdkCameraMetadata.cpp
new file mode 100644
index 0000000..18718d3
--- /dev/null
+++ b/camera/ndk/NdkCameraMetadata.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NdkCameraMetadata"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include "NdkCameraMetadata.h"
+#include "impl/ACameraMetadata.h"
+
+using namespace android;
+
+EXPORT
+camera_status_t ACameraMetadata_getConstEntry(
+ const ACameraMetadata* acm, uint32_t tag, ACameraMetadata_const_entry* entry) {
+ ATRACE_CALL();
+ if (acm == nullptr || entry == nullptr) {
+ ALOGE("%s: invalid argument! metadata %p, tag 0x%x, entry %p",
+ __FUNCTION__, acm, tag, entry);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return acm->getConstEntry(tag, entry);
+}
+
+EXPORT
+ACameraMetadata* ACameraMetadata_copy(const ACameraMetadata* src) {
+ ATRACE_CALL();
+ if (src == nullptr) {
+ ALOGE("%s: src is null!", __FUNCTION__);
+ return nullptr;
+ }
+ return new ACameraMetadata(*src);
+}
+
+EXPORT
+void ACameraMetadata_free(ACameraMetadata* metadata) {
+ ATRACE_CALL();
+ if (metadata != nullptr) {
+ delete metadata;
+ }
+}
diff --git a/camera/ndk/NdkCaptureRequest.cpp b/camera/ndk/NdkCaptureRequest.cpp
new file mode 100644
index 0000000..4fee09c
--- /dev/null
+++ b/camera/ndk/NdkCaptureRequest.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NdkCaptureRequest"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include "NdkCaptureRequest.h"
+#include "impl/ACameraMetadata.h"
+#include "impl/ACaptureRequest.h"
+
+EXPORT
+camera_status_t ACameraOutputTarget_create(
+ ANativeWindow* window, ACameraOutputTarget** out) {
+ ATRACE_CALL();
+ if (window == nullptr) {
+ ALOGE("%s: Error: input window is null", __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ *out = new ACameraOutputTarget(window);
+ return ACAMERA_OK;
+}
+
+EXPORT
+void ACameraOutputTarget_free(ACameraOutputTarget* target) {
+ ATRACE_CALL();
+ if (target != nullptr) {
+ delete target;
+ }
+ return;
+}
+
+EXPORT
+camera_status_t ACaptureRequest_addTarget(
+ ACaptureRequest* req, const ACameraOutputTarget* target) {
+ ATRACE_CALL();
+ if (req == nullptr || req->targets == nullptr || target == nullptr) {
+ ALOGE("%s: Error: invalid input: req %p, req-targets %p, target %p",
+ __FUNCTION__, req, req->targets, target);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ auto pair = req->targets->mOutputs.insert(*target);
+ if (!pair.second) {
+ ALOGW("%s: target %p already exists!", __FUNCTION__, target);
+ }
+ return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACaptureRequest_removeTarget(
+ ACaptureRequest* req, const ACameraOutputTarget* target) {
+ ATRACE_CALL();
+ if (req == nullptr || req->targets == nullptr || target == nullptr) {
+ ALOGE("%s: Error: invalid input: req %p, req-targets %p, target %p",
+ __FUNCTION__, req, req->targets, target);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ req->targets->mOutputs.erase(*target);
+ return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACaptureRequest_getConstEntry(
+ const ACaptureRequest* req, uint32_t tag, ACameraMetadata_const_entry* entry) {
+ ATRACE_CALL();
+ if (req == nullptr || entry == nullptr) {
+ ALOGE("%s: invalid argument! req 0x%p, tag 0x%x, entry 0x%p",
+ __FUNCTION__, req, tag, entry);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return req->settings->getConstEntry(tag, entry);
+}
+
+#define SET_ENTRY(NAME,NDK_TYPE) \
+EXPORT \
+camera_status_t ACaptureRequest_setEntry_##NAME( \
+ ACaptureRequest* req, uint32_t tag, uint32_t count, const NDK_TYPE* data) { \
+ ATRACE_CALL(); \
+ if (req == nullptr || (count > 0 && data == nullptr)) { \
+ ALOGE("%s: invalid argument! req %p, tag 0x%x, count %d, data 0x%p", \
+ __FUNCTION__, req, tag, count, data); \
+ return ACAMERA_ERROR_INVALID_PARAMETER; \
+ } \
+ return req->settings->update(tag, count, data); \
+}
+
+SET_ENTRY(u8,uint8_t)
+SET_ENTRY(i32,int32_t)
+SET_ENTRY(float,float)
+SET_ENTRY(double,double)
+SET_ENTRY(i64,int64_t)
+SET_ENTRY(rational,ACameraMetadata_rational)
+
+#undef SET_ENTRY
+
+EXPORT
+void ACaptureRequest_free(ACaptureRequest* request) {
+ ATRACE_CALL();
+ if (request == nullptr) {
+ return;
+ }
+ delete request->settings;
+ delete request->targets;
+ delete request;
+ return;
+}
diff --git a/camera/ndk/impl/ACameraCaptureSession.cpp b/camera/ndk/impl/ACameraCaptureSession.cpp
new file mode 100644
index 0000000..7f1b75d
--- /dev/null
+++ b/camera/ndk/impl/ACameraCaptureSession.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2016 The Android Open Source 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ACameraCaptureSession"
+
+#include "ACameraCaptureSession.h"
+
+using namespace android;
+
+ACameraCaptureSession::~ACameraCaptureSession() {
+ ALOGV("~ACameraCaptureSession: %p notify device end of life", this);
+ sp<CameraDevice> dev = getDeviceSp();
+ if (dev != nullptr && !dev->isClosed()) {
+ dev->lockDeviceForSessionOps();
+ {
+ Mutex::Autolock _l(mSessionLock);
+ dev->notifySessionEndOfLifeLocked(this);
+ }
+ dev->unlockDevice();
+ }
+ // Fire onClosed callback
+ (*mUserSessionCallback.onClosed)(mUserSessionCallback.context, this);
+ ALOGV("~ACameraCaptureSession: %p is deleted", this);
+}
+
+void
+ACameraCaptureSession::closeByApp() {
+ sp<CameraDevice> dev = getDeviceSp();
+ if (dev != nullptr) {
+ dev->lockDeviceForSessionOps();
+ }
+
+ {
+ Mutex::Autolock _l(mSessionLock);
+
+ if (!mIsClosed && dev != nullptr) {
+ camera_status_t ret = dev->stopRepeatingLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Stop repeating request failed while closing session %p", this);
+ }
+ }
+ mIsClosed = true;
+ }
+
+ if (dev != nullptr) {
+ dev->unlockDevice();
+ }
+ this->decStrong((void*) ACameraDevice_createCaptureSession);
+}
+
+camera_status_t
+ACameraCaptureSession::stopRepeating() {
+ sp<CameraDevice> dev = getDeviceSp();
+ if (dev == nullptr) {
+ ALOGE("Error: Device associated with session %p has been closed!", this);
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ camera_status_t ret;
+ dev->lockDeviceForSessionOps();
+ {
+ Mutex::Autolock _l(mSessionLock);
+ ret = dev->stopRepeatingLocked();
+ }
+ dev->unlockDevice();
+ return ret;
+}
+
+camera_status_t
+ACameraCaptureSession::setRepeatingRequest(
+ /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ sp<CameraDevice> dev = getDeviceSp();
+ if (dev == nullptr) {
+ ALOGE("Error: Device associated with session %p has been closed!", this);
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ camera_status_t ret;
+ dev->lockDeviceForSessionOps();
+ {
+ Mutex::Autolock _l(mSessionLock);
+ ret = dev->setRepeatingRequestsLocked(
+ this, cbs, numRequests, requests, captureSequenceId);
+ }
+ dev->unlockDevice();
+ return ret;
+}
+
+camera_status_t ACameraCaptureSession::capture(
+ /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ sp<CameraDevice> dev = getDeviceSp();
+ if (dev == nullptr) {
+ ALOGE("Error: Device associated with session %p has been closed!", this);
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+ camera_status_t ret;
+ dev->lockDeviceForSessionOps();
+ {
+ Mutex::Autolock _l(mSessionLock);
+ ret = dev->captureLocked(this, cbs, numRequests, requests, captureSequenceId);
+ }
+ dev->unlockDevice();
+ return ret;
+}
+
+ACameraDevice*
+ACameraCaptureSession::getDevice() {
+ Mutex::Autolock _l(mSessionLock);
+ sp<CameraDevice> dev = getDeviceSp();
+ if (dev == nullptr) {
+ ALOGE("Error: Device associated with session %p has been closed!", this);
+ return nullptr;
+ }
+ return dev->getWrapper();
+}
+
+void
+ACameraCaptureSession::closeByDevice() {
+ Mutex::Autolock _l(mSessionLock);
+ mIsClosed = true;
+}
+
+sp<CameraDevice>
+ACameraCaptureSession::getDeviceSp() {
+ sp<CameraDevice> device = mDevice.promote();
+ if (device == nullptr || device->isClosed()) {
+ ALOGW("Device is closed but session %d is not notified", mId);
+ return nullptr;
+ }
+ return device;
+}
+
+
diff --git a/camera/ndk/impl/ACameraCaptureSession.h b/camera/ndk/impl/ACameraCaptureSession.h
new file mode 100644
index 0000000..1db1b21
--- /dev/null
+++ b/camera/ndk/impl/ACameraCaptureSession.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 The Android Open Source 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 _ACAMERA_CAPTURE_SESSION_H
+#define _ACAMERA_CAPTURE_SESSION_H
+
+#include <set>
+#include <hardware/camera3.h>
+#include <NdkCameraDevice.h>
+#include "ACameraDevice.h"
+
+using namespace android;
+
+struct ACaptureSessionOutput {
+ ACaptureSessionOutput(ANativeWindow* window) : mWindow(window) {};
+
+ bool operator == (const ACaptureSessionOutput& other) const {
+ return mWindow == other.mWindow;
+ }
+ bool operator != (const ACaptureSessionOutput& other) const {
+ return mWindow != other.mWindow;
+ }
+ bool operator < (const ACaptureSessionOutput& other) const {
+ return mWindow < other.mWindow;
+ }
+ bool operator > (const ACaptureSessionOutput& other) const {
+ return mWindow > other.mWindow;
+ }
+
+ ANativeWindow* mWindow;
+ int mRotation = CAMERA3_STREAM_ROTATION_0;
+};
+
+struct ACaptureSessionOutputContainer {
+ std::set<ACaptureSessionOutput> mOutputs;
+};
+
+/**
+ * ACameraCaptureSession opaque struct definition
+ * Leave outside of android namespace because it's NDK struct
+ */
+struct ACameraCaptureSession : public RefBase {
+ public:
+ ACameraCaptureSession(
+ int id,
+ const ACaptureSessionOutputContainer* outputs,
+ const ACameraCaptureSession_stateCallbacks* cb,
+ CameraDevice* device) :
+ mId(id), mOutput(*outputs), mUserSessionCallback(*cb),
+ mDevice(device) {}
+
+ // This can be called in app calling close() or after some app callback is finished
+ // Make sure the caller does not hold device or session lock!
+ ~ACameraCaptureSession();
+
+ // No API except Session_Close will work if device is closed
+ // A session will enter closed state when one of the following happens:
+ // 1. Explicitly closed by app
+ // 2. Replaced by a newer session
+ // 3. Device is closed
+ bool isClosed() { Mutex::Autolock _l(mSessionLock); return mIsClosed; }
+
+ // Close the session and mark app no longer need this session.
+ void closeByApp();
+
+ camera_status_t stopRepeating();
+
+ camera_status_t setRepeatingRequest(
+ /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId);
+
+ camera_status_t capture(
+ /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId);
+
+ ACameraDevice* getDevice();
+
+ private:
+ friend class CameraDevice;
+
+ // Close session because app close camera device, camera device got ERROR_DISCONNECTED,
+ // or a new session is replacing this session.
+ void closeByDevice();
+
+ sp<CameraDevice> getDeviceSp();
+
+ const int mId;
+ const ACaptureSessionOutputContainer mOutput;
+ const ACameraCaptureSession_stateCallbacks mUserSessionCallback;
+ const wp<CameraDevice> mDevice;
+ bool mIsClosed = false;
+ bool mIdle = true;
+ Mutex mSessionLock;
+};
+
+#endif // _ACAMERA_CAPTURE_SESSION_H
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
new file mode 100644
index 0000000..5f89fa3
--- /dev/null
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -0,0 +1,1212 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ACameraDevice"
+
+#include <vector>
+#include <utility>
+#include <inttypes.h>
+#include <gui/Surface.h>
+#include "ACameraDevice.h"
+#include "ACameraMetadata.h"
+#include "ACaptureRequest.h"
+#include "ACameraCaptureSession.h"
+
+using namespace android;
+
+namespace android {
+// Static member definitions
+const char* CameraDevice::kContextKey = "Context";
+const char* CameraDevice::kDeviceKey = "Device";
+const char* CameraDevice::kErrorCodeKey = "ErrorCode";
+const char* CameraDevice::kCallbackFpKey = "Callback";
+const char* CameraDevice::kSessionSpKey = "SessionSp";
+const char* CameraDevice::kCaptureRequestKey = "CaptureRequest";
+const char* CameraDevice::kTimeStampKey = "TimeStamp";
+const char* CameraDevice::kCaptureResultKey = "CaptureResult";
+const char* CameraDevice::kCaptureFailureKey = "CaptureFailure";
+const char* CameraDevice::kSequenceIdKey = "SequenceId";
+const char* CameraDevice::kFrameNumberKey = "FrameNumber";
+
+/**
+ * CameraDevice Implementation
+ */
+CameraDevice::CameraDevice(
+ const char* id,
+ ACameraDevice_StateCallbacks* cb,
+ std::unique_ptr<ACameraMetadata> chars,
+ ACameraDevice* wrapper) :
+ mCameraId(id),
+ mAppCallbacks(*cb),
+ mChars(std::move(chars)),
+ mServiceCallback(new ServiceCallback(this)),
+ mWrapper(wrapper),
+ mInError(false),
+ mError(ACAMERA_OK),
+ mIdle(true) {
+ mClosing = false;
+ // Setup looper thread to perfrom device callbacks to app
+ mCbLooper = new ALooper;
+ mCbLooper->setName("C2N-dev-looper");
+ status_t ret = mCbLooper->start(
+ /*runOnCallingThread*/false,
+ /*canCallJava*/ true,
+ PRIORITY_DEFAULT);
+ mHandler = new CallbackHandler();
+ mCbLooper->registerHandler(mHandler);
+
+ CameraMetadata metadata = mChars->mData;
+ camera_metadata_entry entry = metadata.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
+ if (entry.count != 1) {
+ ALOGW("%s: bad count %zu for partial result count", __FUNCTION__, entry.count);
+ mPartialResultCount = 1;
+ } else {
+ mPartialResultCount = entry.data.i32[0];
+ }
+
+ entry = metadata.find(ANDROID_LENS_INFO_SHADING_MAP_SIZE);
+ if (entry.count != 2) {
+ ALOGW("%s: bad count %zu for shading map size", __FUNCTION__, entry.count);
+ mShadingMapSize[0] = 0;
+ mShadingMapSize[1] = 0;
+ } else {
+ mShadingMapSize[0] = entry.data.i32[0];
+ mShadingMapSize[1] = entry.data.i32[1];
+ }
+}
+
+// Device close implementaiton
+CameraDevice::~CameraDevice() {
+ Mutex::Autolock _l(mDeviceLock);
+ if (!isClosed()) {
+ disconnectLocked();
+ }
+ if (mCbLooper != nullptr) {
+ mCbLooper->unregisterHandler(mHandler->id());
+ mCbLooper->stop();
+ }
+ mCbLooper.clear();
+ mHandler.clear();
+}
+
+// TODO: cached created request?
+camera_status_t
+CameraDevice::createCaptureRequest(
+ ACameraDevice_request_template templateId,
+ ACaptureRequest** request) const {
+ Mutex::Autolock _l(mDeviceLock);
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+ if (mRemote == nullptr) {
+ return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+ }
+ CameraMetadata rawRequest;
+ status_t remoteRet = mRemote->createDefaultRequest(templateId, &rawRequest);
+ if (remoteRet == BAD_VALUE) {
+ ALOGW("Create capture request failed! template %d is not supported on this device",
+ templateId);
+ return ACAMERA_ERROR_UNSUPPORTED;
+ } else if (remoteRet != OK) {
+ ALOGE("Create capture request failed! error %d", remoteRet);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ ACaptureRequest* outReq = new ACaptureRequest();
+ outReq->settings = new ACameraMetadata(rawRequest.release(), ACameraMetadata::ACM_REQUEST);
+ outReq->targets = new ACameraOutputTargets();
+ *request = outReq;
+ return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::createCaptureSession(
+ const ACaptureSessionOutputContainer* outputs,
+ const ACameraCaptureSession_stateCallbacks* callbacks,
+ /*out*/ACameraCaptureSession** session) {
+ Mutex::Autolock _l(mDeviceLock);
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+
+ if (mCurrentSession != nullptr) {
+ mCurrentSession->closeByDevice();
+ stopRepeatingLocked();
+ }
+
+ // Create new session
+ ret = configureStreamsLocked(outputs);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Fail to create new session. cannot configure streams");
+ return ret;
+ }
+
+ ACameraCaptureSession* newSession = new ACameraCaptureSession(
+ mNextSessionId++, outputs, callbacks, this);
+
+ bool configureSucceeded = (ret == ACAMERA_OK);
+
+ // set new session as current session
+ newSession->incStrong((void *) ACameraDevice_createCaptureSession);
+ mCurrentSession = newSession;
+ *session = newSession;
+ return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::captureLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ return submitRequestsLocked(
+ session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
+}
+
+camera_status_t
+CameraDevice::setRepeatingRequestsLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ return submitRequestsLocked(
+ session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
+}
+
+camera_status_t
+CameraDevice::submitRequestsLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId,
+ bool isRepeating) {
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
+ return ret;
+ }
+
+ // Form List/Vector of capture request
+ List<sp<CaptureRequest> > requestList;
+ Vector<sp<CaptureRequest> > requestsV;
+ requestsV.setCapacity(numRequests);
+ for (int i = 0; i < numRequests; i++) {
+ sp<CaptureRequest> req;
+ ret = allocateCaptureRequest(requests[i], req);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Convert capture request to internal format failure! ret %d", ret);
+ return ret;
+ }
+ if (req->mSurfaceList.empty()) {
+ ALOGE("Capture request without output target cannot be submitted!");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ requestList.push_back(req);
+ requestsV.push_back(req);
+ }
+
+ if (isRepeating) {
+ ret = stopRepeatingLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+ return ret;
+ }
+ }
+
+ int sequenceId;
+ int64_t lastFrameNumber;
+
+ sequenceId = mRemote->submitRequestList(requestList, isRepeating, &lastFrameNumber);
+ if (sequenceId < 0) {
+ ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+
+ CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
+ mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
+
+ if (isRepeating) {
+ // stopRepeating above should have cleanup repeating sequence id
+ if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ return ACAMERA_ERROR_CAMERA_DEVICE;
+ }
+ mRepeatingSequenceId = sequenceId;
+ } else {
+ mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
+ }
+
+ if (mIdle) {
+ sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+ msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+ msg->post();
+ }
+ mIdle = false;
+ mBusySession = session;
+
+ if (captureSequenceId) {
+ *captureSequenceId = sequenceId;
+ }
+ return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::allocateCaptureRequest(
+ const ACaptureRequest* request, /*out*/sp<CaptureRequest>& outReq) {
+ camera_status_t ret;
+ sp<CaptureRequest> req(new CaptureRequest());
+ req->mMetadata = request->settings->mData;
+ req->mIsReprocess = false; // NDK does not support reprocessing yet
+
+ for (auto outputTarget : request->targets->mOutputs) {
+ ANativeWindow* anw = outputTarget.mWindow;
+ sp<Surface> surface;
+ ret = getSurfaceFromANativeWindow(anw, surface);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Bad output target in capture request! ret %d", ret);
+ return ret;
+ }
+ req->mSurfaceList.push_back(surface);
+ }
+ outReq = req;
+ return ACAMERA_OK;
+}
+
+ACaptureRequest*
+CameraDevice::allocateACaptureRequest(sp<CaptureRequest>& req) {
+ ACaptureRequest* pRequest = new ACaptureRequest();
+ CameraMetadata clone = req->mMetadata;
+ pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST);
+ pRequest->targets = new ACameraOutputTargets();
+ for (size_t i = 0; i < req->mSurfaceList.size(); i++) {
+ ANativeWindow* anw = static_cast<ANativeWindow*>(req->mSurfaceList[i].get());
+ ACameraOutputTarget outputTarget(anw);
+ pRequest->targets->mOutputs.insert(outputTarget);
+ }
+ return pRequest;
+}
+
+void
+CameraDevice::freeACaptureRequest(ACaptureRequest* req) {
+ if (req == nullptr) {
+ return;
+ }
+ delete req->settings;
+ delete req->targets;
+ delete req;
+}
+
+void
+CameraDevice::notifySessionEndOfLifeLocked(ACameraCaptureSession* session) {
+ if (isClosed()) {
+ // Device is closing already. do nothing
+ return;
+ }
+
+ if (session != mCurrentSession) {
+ // Session has been replaced by other seesion or device is closed
+ return;
+ }
+ mCurrentSession = nullptr;
+
+ // Should not happen
+ if (!session->mIsClosed) {
+ ALOGE("Error: unclosed session %p reaches end of life!", session);
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ return;
+ }
+
+ // No new session, unconfigure now
+ camera_status_t ret = configureStreamsLocked(nullptr);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Unconfigure stream failed. Device might still be configured! ret %d", ret);
+ }
+}
+
+void
+CameraDevice::disconnectLocked() {
+ if (mClosing.exchange(true)) {
+ // Already closing, just return
+ ALOGW("Camera device %s is already closing.", getId());
+ return;
+ }
+
+ if (mRemote != nullptr) {
+ mRemote->disconnect();
+ }
+ mRemote = nullptr;
+
+ if (mCurrentSession != nullptr) {
+ mCurrentSession->closeByDevice();
+ mCurrentSession = nullptr;
+ }
+}
+
+camera_status_t
+CameraDevice::stopRepeatingLocked() {
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+ return ret;
+ }
+ if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+ int repeatingSequenceId = mRepeatingSequenceId;
+ mRepeatingSequenceId = REQUEST_ID_NONE;
+
+ int64_t lastFrameNumber;
+ status_t remoteRet = mRemote->cancelRequest(repeatingSequenceId, &lastFrameNumber);
+ if (remoteRet != OK) {
+ ALOGE("Stop repeating request fails in remote! ret %d", remoteRet);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
+ }
+ return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::waitUntilIdleLocked() {
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Wait until camera %s idle failed! ret %d", getId(), ret);
+ return ret;
+ }
+
+ if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+ ALOGE("Camera device %s won't go to idle when there is repeating request!", getId());
+ return ACAMERA_ERROR_INVALID_OPERATION;
+ }
+
+ status_t remoteRet = mRemote->waitUntilIdle();
+ if (remoteRet != OK) {
+ ALOGE("Camera device %s waitUntilIdle failed! ret %d", getId(), remoteRet);
+ // TODO: define a function to convert status_t -> camera_status_t
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+
+ return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::getIGBPfromSessionOutput(
+ const ACaptureSessionOutput& config,
+ sp<IGraphicBufferProducer>& out) {
+ ANativeWindow* anw = config.mWindow;
+ if (anw == nullptr) {
+ ALOGE("Error: output ANativeWindow is null");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ int value;
+ int err = (*anw->query)(anw, NATIVE_WINDOW_CONCRETE_TYPE, &value);
+ if (value != NATIVE_WINDOW_SURFACE) {
+ ALOGE("Error: ANativeWindow is not backed by Surface!");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ const sp<Surface> surface(static_cast<Surface*>(anw));
+ out = surface->getIGraphicBufferProducer();
+ return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::getSurfaceFromANativeWindow(
+ ANativeWindow* anw, sp<Surface>& out) {
+ if (anw == nullptr) {
+ ALOGE("Error: output ANativeWindow is null");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ int value;
+ int err = (*anw->query)(anw, NATIVE_WINDOW_CONCRETE_TYPE, &value);
+ if (value != NATIVE_WINDOW_SURFACE) {
+ ALOGE("Error: ANativeWindow is not backed by Surface!");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ sp<Surface> surface(static_cast<Surface*>(anw));
+ out = surface;
+ return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::configureStreamsLocked(const ACaptureSessionOutputContainer* outputs) {
+ ACaptureSessionOutputContainer emptyOutput;
+ if (outputs == nullptr) {
+ outputs = &emptyOutput;
+ }
+
+ bool success = false;
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+
+ std::set<OutputConfiguration> outputSet;
+ for (auto outConfig : outputs->mOutputs) {
+ sp<IGraphicBufferProducer> iGBP(nullptr);
+ ret = getIGBPfromSessionOutput(outConfig, iGBP);
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+ outputSet.insert(OutputConfiguration(iGBP, outConfig.mRotation));
+ }
+ std::set<OutputConfiguration> addSet = outputSet;
+ std::vector<int> deleteList;
+
+ // Determine which streams need to be created, which to be deleted
+ for (auto& kvPair : mConfiguredOutputs) {
+ int streamId = kvPair.first;
+ OutputConfiguration& outConfig = kvPair.second;
+ if (outputSet.count(outConfig) == 0) {
+ deleteList.push_back(streamId); // Need to delete a no longer needed stream
+ } else {
+ addSet.erase(outConfig); // No need to add already existing stream
+ }
+ }
+
+ ret = stopRepeatingLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera device %s stop repeating failed, ret %d", getId(), ret);
+ return ret;
+ }
+
+ ret = waitUntilIdleLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera device %s wait until idle failed, ret %d", getId(), ret);
+ return ret;
+ }
+
+ // Send onReady to previous session
+ // CurrentSession will be updated after configureStreamLocked, so here
+ // mCurrentSession is the session to be replaced by a new session
+ if (!mIdle && mCurrentSession != nullptr) {
+ if (mBusySession != mCurrentSession) {
+ ALOGE("Current session != busy session");
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ return ACAMERA_ERROR_CAMERA_DEVICE;
+ }
+ sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+ msg->setPointer(kContextKey, mBusySession->mUserSessionCallback.context);
+ msg->setObject(kSessionSpKey, mBusySession);
+ msg->setPointer(kCallbackFpKey, (void*) mBusySession->mUserSessionCallback.onReady);
+ mBusySession.clear();
+ msg->post();
+ }
+ mIdle = true;
+
+ status_t remoteRet = mRemote->beginConfigure();
+ if (remoteRet != ACAMERA_OK) {
+ ALOGE("Camera device %s begin configure failed, ret %d", getId(), remoteRet);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+
+ // delete to-be-deleted streams
+ for (auto streamId : deleteList) {
+ remoteRet = mRemote->deleteStream(streamId);
+ if (remoteRet != ACAMERA_OK) {
+ ALOGE("Camera device %s fails to remove stream %d", getId(), streamId);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ mConfiguredOutputs.erase(streamId);
+ }
+
+ // add new streams
+ for (auto outConfig : addSet) {
+ remoteRet = mRemote->createStream(outConfig);
+ if (remoteRet < 0) {
+ ALOGE("Camera device %s fails to create stream", getId());
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ int streamId = remoteRet; // Weird, right?
+ mConfiguredOutputs.insert(std::make_pair(streamId, outConfig));
+ }
+
+ remoteRet = mRemote->endConfigure();
+ if (remoteRet == BAD_VALUE) {
+ ALOGE("Camera device %s cannnot support app output configuration", getId());
+ return ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
+ } else if (remoteRet != ACAMERA_OK) {
+ ALOGE("Camera device %s end configure failed, ret %d", getId(), remoteRet);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+
+ return ACAMERA_OK;
+}
+
+void
+CameraDevice::setRemoteDevice(sp<ICameraDeviceUser> remote) {
+ Mutex::Autolock _l(mDeviceLock);
+ mRemote = remote;
+}
+
+camera_status_t
+CameraDevice::checkCameraClosedOrErrorLocked() const {
+ if (mRemote == nullptr) {
+ ALOGE("%s: camera device already closed", __FUNCTION__);
+ return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+ }
+ if (mInError) {// triggered by onDeviceError
+ ALOGE("%s: camera device has encountered a serious error", __FUNCTION__);
+ return mError;
+ }
+ return ACAMERA_OK;
+}
+
+void
+CameraDevice::setCameraDeviceErrorLocked(camera_status_t error) {
+ mInError = true;
+ mError = error;
+ return;
+}
+
+void
+CameraDevice::FrameNumberTracker::updateTracker(int64_t frameNumber, bool isError) {
+ ALOGV("updateTracker frame %" PRId64 " isError %d", frameNumber, isError);
+ if (isError) {
+ mFutureErrorSet.insert(frameNumber);
+ } else if (frameNumber <= mCompletedFrameNumber) {
+ ALOGE("Frame number %" PRId64 " decreased! current fn %" PRId64,
+ frameNumber, mCompletedFrameNumber);
+ return;
+ } else {
+ if (frameNumber != mCompletedFrameNumber + 1) {
+ ALOGE("Frame number out of order. Expect %" PRId64 " but get %" PRId64,
+ mCompletedFrameNumber + 1, frameNumber);
+ // Do not assert as in java implementation
+ }
+ mCompletedFrameNumber = frameNumber;
+ }
+ update();
+}
+
+void
+CameraDevice::FrameNumberTracker::update() {
+ for (auto it = mFutureErrorSet.begin(); it != mFutureErrorSet.end();) {
+ int64_t errorFrameNumber = *it;
+ if (errorFrameNumber == mCompletedFrameNumber + 1) {
+ mCompletedFrameNumber++;
+ it = mFutureErrorSet.erase(it);
+ } else if (errorFrameNumber <= mCompletedFrameNumber) {
+ // This should not happen, but deal with it anyway
+ ALOGE("Completd frame number passed through current frame number!");
+ // erase the old error since it's no longer useful
+ it = mFutureErrorSet.erase(it);
+ } else {
+ // Normal requests hasn't catched up error frames, just break
+ break;
+ }
+ }
+ ALOGV("Update complete frame %" PRId64, mCompletedFrameNumber);
+}
+
+void
+CameraDevice::onCaptureErrorLocked(
+ ICameraDeviceCallbacks::CameraErrorCode errorCode,
+ const CaptureResultExtras& resultExtras) {
+ int sequenceId = resultExtras.requestId;
+ int64_t frameNumber = resultExtras.frameNumber;
+ int32_t burstId = resultExtras.burstId;
+
+ // No way to report buffer error now
+ if (errorCode == ICameraDeviceCallbacks::CameraErrorCode::ERROR_CAMERA_BUFFER) {
+ ALOGE("Camera %s Lost output buffer for frame %" PRId64,
+ getId(), frameNumber);
+ return;
+ }
+ // Fire capture failure callback if there is one registered
+ auto it = mSequenceCallbackMap.find(sequenceId);
+ if (it != mSequenceCallbackMap.end()) {
+ CallbackHolder cbh = (*it).second;
+ ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed;
+ sp<ACameraCaptureSession> session = cbh.mSession;
+ if ((size_t) burstId >= cbh.mRequests.size()) {
+ ALOGE("%s: Error: request index %d out of bound (size %zu)",
+ __FUNCTION__, burstId, cbh.mRequests.size());
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+ return;
+ }
+ sp<CaptureRequest> request = cbh.mRequests[burstId];
+ sp<CameraCaptureFailure> failure(new CameraCaptureFailure());
+ failure->frameNumber = frameNumber;
+ // TODO: refine this when implementing flush
+ failure->reason = CAPTURE_FAILURE_REASON_ERROR;
+ failure->sequenceId = sequenceId;
+ failure->wasImageCaptured = (errorCode ==
+ ICameraDeviceCallbacks::CameraErrorCode::ERROR_CAMERA_RESULT);
+
+ sp<AMessage> msg = new AMessage(kWhatCaptureFail, mHandler);
+ msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) onError);
+ msg->setObject(kCaptureRequestKey, request);
+ msg->setObject(kCaptureFailureKey, failure);
+ msg->post();
+ }
+
+ // Update tracker
+ mFrameNumberTracker.updateTracker(frameNumber, /*isError*/true);
+ checkAndFireSequenceCompleteLocked();
+}
+
+void CameraDevice::CallbackHandler::onMessageReceived(
+ const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatOnDisconnected:
+ case kWhatOnError:
+ case kWhatSessionStateCb:
+ case kWhatCaptureStart:
+ case kWhatCaptureResult:
+ case kWhatCaptureFail:
+ case kWhatCaptureSeqEnd:
+ case kWhatCaptureSeqAbort:
+ ALOGV("%s: Received msg %d", __FUNCTION__, msg->what());
+ break;
+ default:
+ ALOGE("%s:Error: unknown device callback %d", __FUNCTION__, msg->what());
+ return;
+ }
+ // Check the common part of all message
+ void* context;
+ bool found = msg->findPointer(kContextKey, &context);
+ if (!found) {
+ ALOGE("%s: Cannot find callback context!", __FUNCTION__);
+ return;
+ }
+ switch (msg->what()) {
+ case kWhatOnDisconnected:
+ {
+ ACameraDevice* dev;
+ found = msg->findPointer(kDeviceKey, (void**) &dev);
+ if (!found || dev == nullptr) {
+ ALOGE("%s: Cannot find device pointer!", __FUNCTION__);
+ return;
+ }
+ ACameraDevice_StateCallback onDisconnected;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onDisconnected);
+ if (!found) {
+ ALOGE("%s: Cannot find onDisconnected!", __FUNCTION__);
+ return;
+ }
+ if (onDisconnected == nullptr) {
+ return;
+ }
+ (*onDisconnected)(context, dev);
+ break;
+ }
+ case kWhatOnError:
+ {
+ ACameraDevice* dev;
+ found = msg->findPointer(kDeviceKey, (void**) &dev);
+ if (!found || dev == nullptr) {
+ ALOGE("%s: Cannot find device pointer!", __FUNCTION__);
+ return;
+ }
+ ACameraDevice_ErrorStateCallback onError;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onError);
+ if (!found) {
+ ALOGE("%s: Cannot find onError!", __FUNCTION__);
+ return;
+ }
+ int errorCode;
+ found = msg->findInt32(kErrorCodeKey, &errorCode);
+ if (!found) {
+ ALOGE("%s: Cannot find error code!", __FUNCTION__);
+ return;
+ }
+ if (onError == nullptr) {
+ return;
+ }
+ (*onError)(context, dev, errorCode);
+ break;
+ }
+ case kWhatSessionStateCb:
+ case kWhatCaptureStart:
+ case kWhatCaptureResult:
+ case kWhatCaptureFail:
+ case kWhatCaptureSeqEnd:
+ case kWhatCaptureSeqAbort:
+ {
+ sp<RefBase> obj;
+ found = msg->findObject(kSessionSpKey, &obj);
+ if (!found || obj == nullptr) {
+ ALOGE("%s: Cannot find session pointer!", __FUNCTION__);
+ return;
+ }
+ sp<ACameraCaptureSession> session(static_cast<ACameraCaptureSession*>(obj.get()));
+ sp<CaptureRequest> requestSp = nullptr;
+ switch (msg->what()) {
+ case kWhatCaptureStart:
+ case kWhatCaptureResult:
+ case kWhatCaptureFail:
+ found = msg->findObject(kCaptureRequestKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture request!", __FUNCTION__);
+ return;
+ }
+ requestSp = static_cast<CaptureRequest*>(obj.get());
+ break;
+ }
+
+ switch (msg->what()) {
+ case kWhatSessionStateCb:
+ {
+ ACameraCaptureSession_stateCallback onState;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onState);
+ if (!found) {
+ ALOGE("%s: Cannot find state callback!", __FUNCTION__);
+ return;
+ }
+ if (onState == nullptr) {
+ return;
+ }
+ (*onState)(context, session.get());
+ break;
+ }
+ case kWhatCaptureStart:
+ {
+ ACameraCaptureSession_captureCallback_start onStart;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onStart);
+ if (!found) {
+ ALOGE("%s: Cannot find capture start callback!", __FUNCTION__);
+ return;
+ }
+ if (onStart == nullptr) {
+ return;
+ }
+ int64_t timestamp;
+ found = msg->findInt64(kTimeStampKey, ×tamp);
+ if (!found) {
+ ALOGE("%s: Cannot find timestamp!", __FUNCTION__);
+ return;
+ }
+ ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ (*onStart)(context, session.get(), request, timestamp);
+ freeACaptureRequest(request);
+ break;
+ }
+ case kWhatCaptureResult:
+ {
+ ACameraCaptureSession_captureCallback_result onResult;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onResult);
+ if (!found) {
+ ALOGE("%s: Cannot find capture result callback!", __FUNCTION__);
+ return;
+ }
+ if (onResult == nullptr) {
+ return;
+ }
+
+ found = msg->findObject(kCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture result!", __FUNCTION__);
+ return;
+ }
+ sp<ACameraMetadata> result(static_cast<ACameraMetadata*>(obj.get()));
+ ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ (*onResult)(context, session.get(), request, result.get());
+ freeACaptureRequest(request);
+ break;
+ }
+ case kWhatCaptureFail:
+ {
+ ACameraCaptureSession_captureCallback_failed onFail;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onFail);
+ if (!found) {
+ ALOGE("%s: Cannot find capture fail callback!", __FUNCTION__);
+ return;
+ }
+ if (onFail == nullptr) {
+ return;
+ }
+
+ found = msg->findObject(kCaptureFailureKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture failure!", __FUNCTION__);
+ return;
+ }
+ sp<CameraCaptureFailure> failureSp(
+ static_cast<CameraCaptureFailure*>(obj.get()));
+ ACameraCaptureFailure* failure =
+ static_cast<ACameraCaptureFailure*>(failureSp.get());
+ ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ (*onFail)(context, session.get(), request, failure);
+ freeACaptureRequest(request);
+ delete failure;
+ break;
+ }
+ case kWhatCaptureSeqEnd:
+ {
+ ACameraCaptureSession_captureCallback_sequenceEnd onSeqEnd;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onSeqEnd);
+ if (!found) {
+ ALOGE("%s: Cannot find sequence end callback!", __FUNCTION__);
+ return;
+ }
+ if (onSeqEnd == nullptr) {
+ return;
+ }
+ int seqId;
+ found = msg->findInt32(kSequenceIdKey, &seqId);
+ if (!found) {
+ ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+ return;
+ }
+ int64_t frameNumber;
+ found = msg->findInt64(kFrameNumberKey, &frameNumber);
+ if (!found) {
+ ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+ return;
+ }
+ (*onSeqEnd)(context, session.get(), seqId, frameNumber);
+ break;
+ }
+ case kWhatCaptureSeqAbort:
+ {
+ ACameraCaptureSession_captureCallback_sequenceAbort onSeqAbort;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onSeqAbort);
+ if (!found) {
+ ALOGE("%s: Cannot find sequence end callback!", __FUNCTION__);
+ return;
+ }
+ if (onSeqAbort == nullptr) {
+ return;
+ }
+ int seqId;
+ found = msg->findInt32(kSequenceIdKey, &seqId);
+ if (!found) {
+ ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+ return;
+ }
+ (*onSeqAbort)(context, session.get(), seqId);
+ break;
+ }
+ }
+ break;
+ }
+ }
+}
+
+CameraDevice::CallbackHolder::CallbackHolder(
+ sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_captureCallbacks* cbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating), mCallbacks(fillCb(cbs)) {}
+
+void
+CameraDevice::checkRepeatingSequenceCompleteLocked(
+ const int sequenceId, const int64_t lastFrameNumber) {
+ ALOGV("Repeating seqId %d lastFrameNumer %" PRId64, sequenceId, lastFrameNumber);
+ if (lastFrameNumber == NO_FRAMES_CAPTURED) {
+ if (mSequenceCallbackMap.count(sequenceId) == 0) {
+ ALOGW("No callback found for sequenceId %d", sequenceId);
+ return;
+ }
+ // remove callback holder from callback map
+ auto cbIt = mSequenceCallbackMap.find(sequenceId);
+ CallbackHolder cbh = cbIt->second;
+ mSequenceCallbackMap.erase(cbIt);
+ // send seq aborted callback
+ sp<AMessage> msg = new AMessage(kWhatCaptureSeqAbort, mHandler);
+ msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setObject(kSessionSpKey, cbh.mSession);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceAborted);
+ msg->setInt32(kSequenceIdKey, sequenceId);
+ msg->post();
+ } else {
+ // Use mSequenceLastFrameNumberMap to track
+ mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
+
+ // Last frame might have arrived. Check now
+ checkAndFireSequenceCompleteLocked();
+ }
+}
+
+void
+CameraDevice::checkAndFireSequenceCompleteLocked() {
+ int64_t completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
+ //std::map<int, int64_t> mSequenceLastFrameNumberMap;
+ auto it = mSequenceLastFrameNumberMap.begin();
+ while (it != mSequenceLastFrameNumberMap.end()) {
+ int sequenceId = it->first;
+ int64_t lastFrameNumber = it->second;
+ bool seqCompleted = false;
+ bool hasCallback = true;
+
+ if (mRemote == nullptr) {
+ ALOGW("Camera %s closed while checking sequence complete", getId());
+ return;
+ }
+
+ // Check if there is callback for this sequence
+ // This should not happen because we always register callback (with nullptr inside)
+ if (mSequenceCallbackMap.count(sequenceId) == 0) {
+ ALOGW("No callback found for sequenceId %d", sequenceId);
+ hasCallback = false;
+ }
+
+ if (lastFrameNumber <= completedFrameNumber) {
+ ALOGV("seq %d reached last frame %" PRId64 ", completed %" PRId64,
+ sequenceId, lastFrameNumber, completedFrameNumber);
+ seqCompleted = true;
+ }
+
+ if (seqCompleted && hasCallback) {
+ // remove callback holder from callback map
+ auto cbIt = mSequenceCallbackMap.find(sequenceId);
+ CallbackHolder cbh = cbIt->second;
+ mSequenceCallbackMap.erase(cbIt);
+ // send seq complete callback
+ sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
+ msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setObject(kSessionSpKey, cbh.mSession);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceCompleted);
+ msg->setInt32(kSequenceIdKey, sequenceId);
+ msg->setInt64(kFrameNumberKey, lastFrameNumber);
+
+ // Clear the session sp before we send out the message
+ // This will guarantee the rare case where the message is processed
+ // before cbh goes out of scope and causing we call the session
+ // destructor while holding device lock
+ cbh.mSession.clear();
+ msg->post();
+ }
+
+ // No need to track sequence complete if there is no callback registered
+ if (seqCompleted || !hasCallback) {
+ it = mSequenceLastFrameNumberMap.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+/**
+ * Camera service callback implementation
+ */
+void
+CameraDevice::ServiceCallback::onDeviceError(
+ CameraErrorCode errorCode,
+ const CaptureResultExtras& resultExtras) {
+ ALOGD("Device error received, code %d, frame number %" PRId64 ", request ID %d, subseq ID %d",
+ errorCode, resultExtras.frameNumber, resultExtras.requestId, resultExtras.burstId);
+
+ sp<CameraDevice> dev = mDevice.promote();
+ if (dev == nullptr) {
+ return; // device has been closed
+ }
+
+ Mutex::Autolock _l(dev->mDeviceLock);
+ if (dev->mRemote == nullptr) {
+ return; // device has been closed
+ }
+ switch (errorCode) {
+ case ERROR_CAMERA_DISCONNECTED:
+ {
+ // Camera is disconnected, close the session and expect no more callbacks
+ if (dev->mCurrentSession != nullptr) {
+ dev->mCurrentSession->closeByDevice();
+ dev->mCurrentSession = nullptr;
+ }
+ sp<AMessage> msg = new AMessage(kWhatOnDisconnected, dev->mHandler);
+ msg->setPointer(kContextKey, dev->mAppCallbacks.context);
+ msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
+ msg->setPointer(kCallbackFpKey, (void*) dev->mAppCallbacks.onDisconnected);
+ msg->post();
+ break;
+ }
+ default:
+ ALOGE("Unknown error from camera device: %d", errorCode);
+ // no break
+ case ERROR_CAMERA_DEVICE:
+ case ERROR_CAMERA_SERVICE:
+ {
+ switch (errorCode) {
+ case ERROR_CAMERA_DEVICE:
+ dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ break;
+ case ERROR_CAMERA_SERVICE:
+ dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+ break;
+ default:
+ dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_UNKNOWN);
+ break;
+ }
+ sp<AMessage> msg = new AMessage(kWhatOnError, dev->mHandler);
+ msg->setPointer(kContextKey, dev->mAppCallbacks.context);
+ msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
+ msg->setPointer(kCallbackFpKey, (void*) dev->mAppCallbacks.onError);
+ msg->setInt32(kErrorCodeKey, errorCode);
+ msg->post();
+ break;
+ }
+ case ERROR_CAMERA_REQUEST:
+ case ERROR_CAMERA_RESULT:
+ case ERROR_CAMERA_BUFFER:
+ dev->onCaptureErrorLocked(errorCode, resultExtras);
+ break;
+ }
+}
+
+void
+CameraDevice::ServiceCallback::onDeviceIdle() {
+ ALOGV("Camera is now idle");
+ sp<CameraDevice> dev = mDevice.promote();
+ if (dev == nullptr) {
+ return; // device has been closed
+ }
+
+ Mutex::Autolock _l(dev->mDeviceLock);
+ if (dev->isClosed() || dev->mRemote == nullptr) {
+ return;
+ }
+
+ if (dev->mIdle) {
+ // Already in idle state. Possibly other thread did waitUntilIdle
+ return;
+ }
+
+ if (dev->mCurrentSession != nullptr) {
+ ALOGE("onDeviceIdle sending state cb");
+ if (dev->mBusySession != dev->mCurrentSession) {
+ ALOGE("Current session != busy session");
+ dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ return;
+ }
+ sp<AMessage> msg = new AMessage(kWhatSessionStateCb, dev->mHandler);
+ msg->setPointer(kContextKey, dev->mBusySession->mUserSessionCallback.context);
+ msg->setObject(kSessionSpKey, dev->mBusySession);
+ msg->setPointer(kCallbackFpKey, (void*) dev->mBusySession->mUserSessionCallback.onReady);
+ // Make sure we clear the sp first so the session destructor can
+ // only happen on handler thread (where we don't hold device/session lock)
+ dev->mBusySession.clear();
+ msg->post();
+ }
+ dev->mIdle = true;
+}
+
+void
+CameraDevice::ServiceCallback::onCaptureStarted(
+ const CaptureResultExtras& resultExtras,
+ int64_t timestamp) {
+ sp<CameraDevice> dev = mDevice.promote();
+ if (dev == nullptr) {
+ return; // device has been closed
+ }
+ Mutex::Autolock _l(dev->mDeviceLock);
+ if (dev->isClosed() || dev->mRemote == nullptr) {
+ return;
+ }
+
+ int sequenceId = resultExtras.requestId;
+ int64_t frameNumber = resultExtras.frameNumber;
+ int32_t burstId = resultExtras.burstId;
+
+ auto it = dev->mSequenceCallbackMap.find(sequenceId);
+ if (it != dev->mSequenceCallbackMap.end()) {
+ CallbackHolder cbh = (*it).second;
+ ACameraCaptureSession_captureCallback_start onStart = cbh.mCallbacks.onCaptureStarted;
+ sp<ACameraCaptureSession> session = cbh.mSession;
+ if ((size_t) burstId >= cbh.mRequests.size()) {
+ ALOGE("%s: Error: request index %d out of bound (size %zu)",
+ __FUNCTION__, burstId, cbh.mRequests.size());
+ dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+ }
+ sp<CaptureRequest> request = cbh.mRequests[burstId];
+ sp<AMessage> msg = new AMessage(kWhatCaptureStart, dev->mHandler);
+ msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) onStart);
+ msg->setObject(kCaptureRequestKey, request);
+ msg->setInt64(kTimeStampKey, timestamp);
+ msg->post();
+ }
+}
+
+void
+CameraDevice::ServiceCallback::onResultReceived(
+ const CameraMetadata& metadata,
+ const CaptureResultExtras& resultExtras) {
+ sp<CameraDevice> dev = mDevice.promote();
+ if (dev == nullptr) {
+ return; // device has been closed
+ }
+ int sequenceId = resultExtras.requestId;
+ int64_t frameNumber = resultExtras.frameNumber;
+ int32_t burstId = resultExtras.burstId;
+ bool isPartialResult = (resultExtras.partialResultCount < dev->mPartialResultCount);
+
+ if (!isPartialResult) {
+ ALOGV("SeqId %d frame %" PRId64 " result arrive.", sequenceId, frameNumber);
+ }
+
+ Mutex::Autolock _l(dev->mDeviceLock);
+ if (dev->mRemote == nullptr) {
+ return; // device has been disconnected
+ }
+
+ if (dev->isClosed()) {
+ if (!isPartialResult) {
+ dev->mFrameNumberTracker.updateTracker(frameNumber, /*isError*/false);
+ }
+ // early return to avoid callback sent to closed devices
+ return;
+ }
+
+ CameraMetadata metadataCopy = metadata;
+ // Copied from java implmentation. Why do we need this?
+ metadataCopy.update(ANDROID_LENS_INFO_SHADING_MAP_SIZE, dev->mShadingMapSize, /*data_count*/2);
+
+ auto it = dev->mSequenceCallbackMap.find(sequenceId);
+ if (it != dev->mSequenceCallbackMap.end()) {
+ CallbackHolder cbh = (*it).second;
+ ACameraCaptureSession_captureCallback_result onResult = isPartialResult ?
+ cbh.mCallbacks.onCaptureProgressed :
+ cbh.mCallbacks.onCaptureCompleted;
+ sp<ACameraCaptureSession> session = cbh.mSession;
+ if ((size_t) burstId >= cbh.mRequests.size()) {
+ ALOGE("%s: Error: request index %d out of bound (size %zu)",
+ __FUNCTION__, burstId, cbh.mRequests.size());
+ dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+ }
+ sp<CaptureRequest> request = cbh.mRequests[burstId];
+ sp<ACameraMetadata> result(new ACameraMetadata(
+ metadataCopy.release(), ACameraMetadata::ACM_RESULT));
+
+ sp<AMessage> msg = new AMessage(kWhatCaptureResult, dev->mHandler);
+ msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) onResult);
+ msg->setObject(kCaptureRequestKey, request);
+ msg->setObject(kCaptureResultKey, result);
+ msg->post();
+ }
+
+ if (!isPartialResult) {
+ dev->mFrameNumberTracker.updateTracker(frameNumber, /*isError*/false);
+ dev->checkAndFireSequenceCompleteLocked();
+ }
+}
+
+void
+CameraDevice::ServiceCallback::onPrepared(int) {
+ // Prepare not yet implemented in NDK
+ return;
+}
+
+} // namespace android
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
new file mode 100644
index 0000000..b73e621
--- /dev/null
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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 _ACAMERA_DEVICE_H
+#define _ACAMERA_DEVICE_H
+
+#include <memory>
+#include <map>
+#include <set>
+#include <atomic>
+#include <utils/StrongPointer.h>
+#include <utils/Mutex.h>
+#include <utils/String8.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <camera/CaptureResult.h>
+#include <camera/camera2/ICameraDeviceCallbacks.h>
+#include <camera/camera2/ICameraDeviceUser.h>
+#include <camera/camera2/OutputConfiguration.h>
+#include <camera/camera2/CaptureRequest.h>
+
+#include <NdkCameraDevice.h>
+#include "ACameraMetadata.h"
+
+using namespace android;
+
+namespace android {
+
+// Wrap ACameraCaptureFailure so it can be ref-counter
+struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure {};
+
+class CameraDevice final : public RefBase {
+ public:
+ CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
+ std::unique_ptr<ACameraMetadata> chars,
+ ACameraDevice* wrapper);
+ ~CameraDevice();
+
+ inline const char* getId() const { return mCameraId.string(); }
+
+ camera_status_t createCaptureRequest(
+ ACameraDevice_request_template templateId,
+ ACaptureRequest** request) const;
+
+ camera_status_t createCaptureSession(
+ const ACaptureSessionOutputContainer* outputs,
+ const ACameraCaptureSession_stateCallbacks* callbacks,
+ /*out*/ACameraCaptureSession** session);
+
+ // Callbacks from camera service
+ class ServiceCallback : public BnCameraDeviceCallbacks {
+ public:
+ ServiceCallback(CameraDevice* device) : mDevice(device) {}
+ void onDeviceError(CameraErrorCode errorCode,
+ const CaptureResultExtras& resultExtras) override;
+ void onDeviceIdle() override;
+ void onCaptureStarted(const CaptureResultExtras& resultExtras,
+ int64_t timestamp) override;
+ void onResultReceived(const CameraMetadata& metadata,
+ const CaptureResultExtras& resultExtras) override;
+ void onPrepared(int streamId) override;
+ private:
+ const wp<CameraDevice> mDevice;
+ };
+ inline sp<ICameraDeviceCallbacks> getServiceCallback() { return mServiceCallback; };
+
+ // Camera device is only functional after remote being set
+ void setRemoteDevice(sp<ICameraDeviceUser> remote);
+
+ inline ACameraDevice* getWrapper() const { return mWrapper; };
+
+ private:
+ friend ACameraCaptureSession;
+ camera_status_t checkCameraClosedOrErrorLocked() const;
+
+ // device goes into fatal error state after this
+ void setCameraDeviceErrorLocked(camera_status_t error);
+
+ void disconnectLocked(); // disconnect from camera service
+
+ camera_status_t stopRepeatingLocked();
+
+ camera_status_t waitUntilIdleLocked();
+
+
+ camera_status_t captureLocked(sp<ACameraCaptureSession> session,
+ /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId);
+
+ camera_status_t setRepeatingRequestsLocked(sp<ACameraCaptureSession> session,
+ /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId);
+
+ camera_status_t submitRequestsLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*out*/int* captureSequenceId,
+ bool isRepeating);
+
+ static camera_status_t allocateCaptureRequest(
+ const ACaptureRequest* request, sp<CaptureRequest>& outReq);
+
+ static ACaptureRequest* allocateACaptureRequest(sp<CaptureRequest>& req);
+ static void freeACaptureRequest(ACaptureRequest*);
+
+ // only For session to hold device lock
+ // Always grab device lock before grabbing session lock
+ void lockDeviceForSessionOps() const { mDeviceLock.lock(); };
+ void unlockDevice() const { mDeviceLock.unlock(); };
+
+ // For capture session to notify its end of life
+ void notifySessionEndOfLifeLocked(ACameraCaptureSession* session);
+
+ camera_status_t configureStreamsLocked(const ACaptureSessionOutputContainer* outputs);
+
+ static camera_status_t getIGBPfromSessionOutput(
+ const ACaptureSessionOutput& config, sp<IGraphicBufferProducer>& out);
+
+ static camera_status_t getSurfaceFromANativeWindow(
+ ANativeWindow* anw, sp<Surface>& out);
+
+ mutable Mutex mDeviceLock;
+ const String8 mCameraId; // Camera ID
+ const ACameraDevice_StateCallbacks mAppCallbacks; // Callback to app
+ const std::unique_ptr<ACameraMetadata> mChars; // Camera characteristics
+ const sp<ServiceCallback> mServiceCallback;
+ ACameraDevice* mWrapper;
+
+ // stream id -> OutputConfiguration map
+ std::map<int, OutputConfiguration> mConfiguredOutputs;
+
+ // TODO: maybe a bool will suffice for synchronous implementation?
+ std::atomic_bool mClosing;
+ inline bool isClosed() { return mClosing; }
+
+ bool mInError;
+ camera_status_t mError;
+ void onCaptureErrorLocked(
+ ICameraDeviceCallbacks::CameraErrorCode errorCode,
+ const CaptureResultExtras& resultExtras);
+
+ bool mIdle;
+ // This will avoid a busy session being deleted before it's back to idle state
+ sp<ACameraCaptureSession> mBusySession;
+
+ sp<ICameraDeviceUser> mRemote;
+
+ // Looper thread to handle callback to app
+ sp<ALooper> mCbLooper;
+ // definition of handler and message
+ enum {
+ // Device state callbacks
+ kWhatOnDisconnected, // onDisconnected
+ kWhatOnError, // onError
+ // Session state callbacks
+ kWhatSessionStateCb, // onReady, onActive
+ // Capture callbacks
+ kWhatCaptureStart, // onCaptureStarted
+ kWhatCaptureResult, // onCaptureProgressed, onCaptureCompleted
+ kWhatCaptureFail, // onCaptureFailed
+ kWhatCaptureSeqEnd, // onCaptureSequenceCompleted
+ kWhatCaptureSeqAbort // onCaptureSequenceAborted
+ };
+ static const char* kContextKey;
+ static const char* kDeviceKey;
+ static const char* kErrorCodeKey;
+ static const char* kCallbackFpKey;
+ static const char* kSessionSpKey;
+ static const char* kCaptureRequestKey;
+ static const char* kTimeStampKey;
+ static const char* kCaptureResultKey;
+ static const char* kCaptureFailureKey;
+ static const char* kSequenceIdKey;
+ static const char* kFrameNumberKey;
+ class CallbackHandler : public AHandler {
+ public:
+ CallbackHandler() {}
+ void onMessageReceived(const sp<AMessage> &msg) override;
+ };
+ sp<CallbackHandler> mHandler;
+
+ /***********************************
+ * Capture session related members *
+ ***********************************/
+ // The current active session
+ ACameraCaptureSession* mCurrentSession = nullptr;
+
+ int mNextSessionId = 0;
+ // TODO: might need another looper/handler to handle callbacks from service
+
+ static const int REQUEST_ID_NONE = -1;
+ int mRepeatingSequenceId = REQUEST_ID_NONE;
+
+ // sequence id -> last frame number map
+ std::map<int, int64_t> mSequenceLastFrameNumberMap;
+
+ struct CallbackHolder {
+ CallbackHolder(sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_captureCallbacks* cbs);
+
+ static ACameraCaptureSession_captureCallbacks fillCb(
+ ACameraCaptureSession_captureCallbacks* cbs) {
+ if (cbs != nullptr) {
+ return *cbs;
+ }
+ return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
+ }
+
+ sp<ACameraCaptureSession> mSession;
+ Vector<sp<CaptureRequest> > mRequests;
+ const bool mIsRepeating;
+ ACameraCaptureSession_captureCallbacks mCallbacks;
+ };
+ // sequence id -> callbacks map
+ std::map<int, CallbackHolder> mSequenceCallbackMap;
+
+ static const int64_t NO_FRAMES_CAPTURED = -1;
+ class FrameNumberTracker {
+ public:
+ // TODO: Called in onResultReceived and onCaptureErrorLocked
+ void updateTracker(int64_t frameNumber, bool isError);
+ inline int64_t getCompletedFrameNumber() { return mCompletedFrameNumber; }
+ private:
+ void update();
+ void updateCompletedFrameNumber(int64_t frameNumber);
+
+ int64_t mCompletedFrameNumber = NO_FRAMES_CAPTURED;
+ List<int64_t> mSkippedFrameNumbers;
+ std::set<int64_t> mFutureErrorSet;
+ };
+ FrameNumberTracker mFrameNumberTracker;
+
+ void checkRepeatingSequenceCompleteLocked(const int sequenceId, const int64_t lastFrameNumber);
+ void checkAndFireSequenceCompleteLocked();
+
+ // Misc variables
+ int32_t mShadingMapSize[2]; // const after constructor
+ int32_t mPartialResultCount; // const after constructor
+
+};
+
+} // namespace android;
+
+/**
+ * ACameraDevice opaque struct definition
+ * Leave outside of android namespace because it's NDK struct
+ */
+struct ACameraDevice {
+ ACameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
+ std::unique_ptr<ACameraMetadata> chars) :
+ mDevice(new CameraDevice(id, cb, std::move(chars), this)) {}
+
+ ~ACameraDevice() {};
+
+ /*******************
+ * NDK public APIs *
+ *******************/
+ inline const char* getId() const { return mDevice->getId(); }
+
+ camera_status_t createCaptureRequest(
+ ACameraDevice_request_template templateId,
+ ACaptureRequest** request) const {
+ return mDevice->createCaptureRequest(templateId, request);
+ }
+
+ camera_status_t createCaptureSession(
+ const ACaptureSessionOutputContainer* outputs,
+ const ACameraCaptureSession_stateCallbacks* callbacks,
+ /*out*/ACameraCaptureSession** session) {
+ return mDevice->createCaptureSession(outputs, callbacks, session);
+ }
+
+ /***********************
+ * Device interal APIs *
+ ***********************/
+ inline sp<ICameraDeviceCallbacks> getServiceCallback() {
+ return mDevice->getServiceCallback();
+ };
+
+ // Camera device is only functional after remote being set
+ inline void setRemoteDevice(sp<ICameraDeviceUser> remote) {
+ mDevice->setRemoteDevice(remote);
+ }
+
+ private:
+ sp<CameraDevice> mDevice;
+};
+
+#endif // _ACAMERA_DEVICE_H
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
new file mode 100644
index 0000000..ed5c3ba
--- /dev/null
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -0,0 +1,479 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ACameraManager"
+
+#include <memory>
+#include "ACameraManager.h"
+#include "ACameraMetadata.h"
+#include "ACameraDevice.h"
+#include <utils/Vector.h>
+#include <stdlib.h>
+#include <camera/VendorTagDescriptor.h>
+
+using namespace android;
+
+//constants shared between ACameraManager and CameraManagerGlobal
+namespace {
+ const int kMaxCameraIdLen = 32;
+}
+
+namespace android {
+// Static member definitions
+const char* CameraManagerGlobal::kCameraIdKey = "CameraId";
+const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp";
+const char* CameraManagerGlobal::kContextKey = "CallbackContext";
+Mutex CameraManagerGlobal::sLock;
+CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
+
+CameraManagerGlobal&
+CameraManagerGlobal::getInstance() {
+ Mutex::Autolock _l(sLock);
+ CameraManagerGlobal* instance = sInstance;
+ if (instance == nullptr) {
+ instance = new CameraManagerGlobal();
+ sInstance = instance;
+ }
+ return *instance;
+}
+
+CameraManagerGlobal::~CameraManagerGlobal() {
+ // clear sInstance so next getInstance call knows to create a new one
+ Mutex::Autolock _sl(sLock);
+ sInstance = nullptr;
+ Mutex::Autolock _l(mLock);
+ if (mCameraService != nullptr) {
+ IInterface::asBinder(mCameraService)->unlinkToDeath(mDeathNotifier);
+ mCameraService->removeListener(mCameraServiceListener);
+ }
+ mDeathNotifier.clear();
+ if (mCbLooper != nullptr) {
+ mCbLooper->unregisterHandler(mHandler->id());
+ mCbLooper->stop();
+ }
+ mCbLooper.clear();
+ mHandler.clear();
+ mCameraServiceListener.clear();
+ mCameraService.clear();
+}
+
+sp<ICameraService> CameraManagerGlobal::getCameraService() {
+ Mutex::Autolock _l(mLock);
+ if (mCameraService.get() == nullptr) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder;
+ do {
+ binder = sm->getService(String16(kCameraServiceName));
+ if (binder != nullptr) {
+ break;
+ }
+ ALOGW("CameraService not published, waiting...");
+ usleep(kCameraServicePollDelay);
+ } while(true);
+ if (mDeathNotifier == nullptr) {
+ mDeathNotifier = new DeathNotifier(this);
+ }
+ binder->linkToDeath(mDeathNotifier);
+ mCameraService = interface_cast<ICameraService>(binder);
+
+ // Setup looper thread to perfrom availiability callbacks
+ if (mCbLooper == nullptr) {
+ mCbLooper = new ALooper;
+ mCbLooper->setName("C2N-mgr-looper");
+ status_t ret = mCbLooper->start(
+ /*runOnCallingThread*/false,
+ /*canCallJava*/ true,
+ PRIORITY_DEFAULT);
+ if (mHandler == nullptr) {
+ mHandler = new CallbackHandler();
+ }
+ mCbLooper->registerHandler(mHandler);
+ }
+
+ // register ICameraServiceListener
+ if (mCameraServiceListener == nullptr) {
+ mCameraServiceListener = new CameraServiceListener(this);
+ }
+ mCameraService->addListener(mCameraServiceListener);
+
+ // setup vendor tags
+ sp<VendorTagDescriptor> desc;
+ status_t ret = mCameraService->getCameraVendorTagDescriptor(/*out*/desc);
+
+ if (ret == OK) {
+ ret = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
+ if (ret != OK) {
+ ALOGE("%s: Failed to set vendor tag descriptors, received error %s (%d)",
+ __FUNCTION__, strerror(-ret), ret);
+ }
+ } else if (ret == -EOPNOTSUPP) {
+ ALOGW("%s: Camera HAL too old; does not support vendor tags",
+ __FUNCTION__);
+ VendorTagDescriptor::clearGlobalVendorTagDescriptor();
+ } else {
+ ALOGE("%s: Failed to get vendor tag descriptors, received error %s (%d)",
+ __FUNCTION__, strerror(-ret), ret);
+ }
+ }
+ ALOGE_IF(mCameraService == nullptr, "no CameraService!?");
+ return mCameraService;
+}
+
+void CameraManagerGlobal::DeathNotifier::binderDied(const wp<IBinder>&)
+{
+ ALOGE("Camera service binderDied!");
+ sp<CameraManagerGlobal> cm = mCameraManager.promote();
+ if (cm != nullptr) {
+ AutoMutex lock(cm->mLock);
+ for (auto pair : cm->mDeviceStatusMap) {
+ int32_t cameraId = pair.first;
+ cm->onStatusChangedLocked(
+ ICameraServiceListener::STATUS_NOT_PRESENT, cameraId);
+ }
+ cm->mCameraService.clear();
+ // TODO: consider adding re-connect call here?
+ }
+}
+
+void CameraManagerGlobal::registerAvailabilityCallback(
+ const ACameraManager_AvailabilityCallbacks *callback) {
+ Mutex::Autolock _l(mLock);
+ Callback cb(callback);
+ auto pair = mCallbacks.insert(cb);
+ // Send initial callbacks if callback is newly registered
+ if (pair.second) {
+ for (auto pair : mDeviceStatusMap) {
+ int32_t cameraId = pair.first;
+ Status status = pair.second;
+
+ sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
+ ACameraManager_AvailabilityCallback cb = isStatusAvailable(status) ?
+ callback->onCameraAvailable : callback->onCameraUnavailable;
+ msg->setPointer(kCallbackFpKey, (void *) cb);
+ msg->setPointer(kContextKey, callback->context);
+ msg->setInt32(kCameraIdKey, cameraId);
+ msg->post();
+ }
+ }
+}
+
+void CameraManagerGlobal::unregisterAvailabilityCallback(
+ const ACameraManager_AvailabilityCallbacks *callback) {
+ Mutex::Autolock _l(mLock);
+ Callback cb(callback);
+ mCallbacks.erase(cb);
+}
+
+bool CameraManagerGlobal::validStatus(Status status) {
+ switch (status) {
+ case ICameraServiceListener::STATUS_NOT_PRESENT:
+ case ICameraServiceListener::STATUS_PRESENT:
+ case ICameraServiceListener::STATUS_ENUMERATING:
+ case ICameraServiceListener::STATUS_NOT_AVAILABLE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool CameraManagerGlobal::isStatusAvailable(Status status) {
+ switch (status) {
+ case ICameraServiceListener::STATUS_PRESENT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void CameraManagerGlobal::CallbackHandler::sendSingleCallback(
+ int32_t cameraId, void* context,
+ ACameraManager_AvailabilityCallback cb) const {
+ char cameraIdStr[kMaxCameraIdLen];
+ snprintf(cameraIdStr, sizeof(cameraIdStr), "%d", cameraId);
+ (*cb)(context, cameraIdStr);
+}
+
+void CameraManagerGlobal::CallbackHandler::onMessageReceived(
+ const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatSendSingleCallback:
+ {
+ ACameraManager_AvailabilityCallback cb;
+ void* context;
+ int32_t cameraId;
+ bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
+ if (!found) {
+ ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
+ return;
+ }
+ found = msg->findPointer(kContextKey, &context);
+ if (!found) {
+ ALOGE("%s: Cannot find callback context!", __FUNCTION__);
+ return;
+ }
+ found = msg->findInt32(kCameraIdKey, &cameraId);
+ if (!found) {
+ ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
+ return;
+ }
+ sendSingleCallback(cameraId, context, cb);
+ break;
+ }
+ default:
+ ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
+ break;
+ }
+}
+
+void CameraManagerGlobal::CameraServiceListener::onStatusChanged(
+ Status status, int32_t cameraId) {
+ sp<CameraManagerGlobal> cm = mCameraManager.promote();
+ if (cm == nullptr) {
+ ALOGE("Cannot deliver status change. Global camera manager died");
+ return;
+ }
+ cm->onStatusChanged(status, cameraId);
+}
+
+void CameraManagerGlobal::onStatusChanged(
+ Status status, int32_t cameraId) {
+ Mutex::Autolock _l(mLock);
+ onStatusChangedLocked(status, cameraId);
+}
+
+void CameraManagerGlobal::onStatusChangedLocked(
+ Status status, int32_t cameraId) {
+ if (!validStatus(status)) {
+ ALOGE("%s: Invalid status %d", __FUNCTION__, status);
+ return;
+ }
+
+ bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
+ Status oldStatus = firstStatus ?
+ status : // first status
+ mDeviceStatusMap[cameraId];
+
+ if (!firstStatus &&
+ isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
+ // No status update. No need to send callback
+ return;
+ }
+
+ // Iterate through all registered callbacks
+ mDeviceStatusMap[cameraId] = status;
+ for (auto cb : mCallbacks) {
+ sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
+ ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
+ cb.mAvailable : cb.mUnavailable;
+ msg->setPointer(kCallbackFpKey, (void *) cbFp);
+ msg->setPointer(kContextKey, cb.mContext);
+ msg->setInt32(kCameraIdKey, cameraId);
+ msg->post();
+ }
+}
+
+} // namespace android
+
+/**
+ * ACameraManger Implementation
+ */
+camera_status_t
+ACameraManager::getOrCreateCameraIdListLocked(ACameraIdList** cameraIdList) {
+ if (mCachedCameraIdList.numCameras == kCameraIdListNotInit) {
+ int numCameras = 0;
+ Vector<char *> cameraIds;
+ sp<ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+ if (cs == nullptr) {
+ ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
+ return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+ }
+ // Get number of cameras
+ int numAllCameras = cs->getNumberOfCameras(ICameraService::CAMERA_TYPE_ALL);
+ // Filter API2 compatible cameras and push to cameraIds
+ for (int i = 0; i < numAllCameras; i++) {
+ // TODO: Only suppot HALs that supports API2 directly now
+ status_t camera2Support = cs->supportsCameraApi(i, ICameraService::API_VERSION_2);
+ char buf[kMaxCameraIdLen];
+ if (camera2Support == OK) {
+ numCameras++;
+ mCameraIds.insert(i);
+ snprintf(buf, sizeof(buf), "%d", i);
+ size_t cameraIdSize = strlen(buf) + 1;
+ char *cameraId = new char[cameraIdSize];
+ if (!cameraId) {
+ ALOGE("Allocate memory for ACameraIdList failed!");
+ return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
+ }
+ strlcpy(cameraId, buf, cameraIdSize);
+ cameraIds.push(cameraId);
+ }
+ }
+ mCachedCameraIdList.numCameras = numCameras;
+ mCachedCameraIdList.cameraIds = new const char*[numCameras];
+ if (!mCachedCameraIdList.cameraIds) {
+ ALOGE("Allocate memory for ACameraIdList failed!");
+ return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
+ }
+ for (int i = 0; i < numCameras; i++) {
+ mCachedCameraIdList.cameraIds[i] = cameraIds[i];
+ }
+ }
+ *cameraIdList = &mCachedCameraIdList;
+ return ACAMERA_OK;
+}
+
+camera_status_t
+ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
+ Mutex::Autolock _l(mLock);
+ ACameraIdList* cachedList;
+ camera_status_t ret = getOrCreateCameraIdListLocked(&cachedList);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Get camera ID list failed! err: %d", ret);
+ return ret;
+ }
+
+ int numCameras = cachedList->numCameras;
+ ACameraIdList *out = new ACameraIdList;
+ if (!out) {
+ ALOGE("Allocate memory for ACameraIdList failed!");
+ return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
+ }
+ out->numCameras = numCameras;
+ out->cameraIds = new const char*[numCameras];
+ if (!out->cameraIds) {
+ ALOGE("Allocate memory for ACameraIdList failed!");
+ return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
+ }
+ for (int i = 0; i < numCameras; i++) {
+ const char* src = cachedList->cameraIds[i];
+ size_t dstSize = strlen(src) + 1;
+ char* dst = new char[dstSize];
+ if (!dst) {
+ ALOGE("Allocate memory for ACameraIdList failed!");
+ return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
+ }
+ strlcpy(dst, src, dstSize);
+ out->cameraIds[i] = dst;
+ }
+ *cameraIdList = out;
+ return ACAMERA_OK;
+}
+
+void
+ACameraManager::deleteCameraIdList(ACameraIdList* cameraIdList) {
+ if (cameraIdList != nullptr) {
+ if (cameraIdList->cameraIds != nullptr) {
+ for (int i = 0; i < cameraIdList->numCameras; i ++) {
+ delete[] cameraIdList->cameraIds[i];
+ }
+ delete[] cameraIdList->cameraIds;
+ }
+ delete cameraIdList;
+ }
+}
+
+camera_status_t ACameraManager::getCameraCharacteristics(
+ const char *cameraIdStr, ACameraMetadata **characteristics) {
+ Mutex::Autolock _l(mLock);
+ ACameraIdList* cachedList;
+ // Make sure mCameraIds is initialized
+ camera_status_t ret = getOrCreateCameraIdListLocked(&cachedList);
+ if (ret != ACAMERA_OK) {
+ ALOGE("%s: Get camera ID list failed! err: %d", __FUNCTION__, ret);
+ return ret;
+ }
+ int cameraId = atoi(cameraIdStr);
+ if (mCameraIds.count(cameraId) == 0) {
+ ALOGE("%s: Camera ID %s does not exist!", __FUNCTION__, cameraIdStr);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ sp<ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+ if (cs == nullptr) {
+ ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
+ return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+ }
+ CameraMetadata rawMetadata;
+ status_t serviceRet = cs->getCameraCharacteristics(cameraId, &rawMetadata);
+ if (serviceRet != OK) {
+ ALOGE("Get camera characteristics from camera service failed! Err %d", ret);
+ return ACAMERA_ERROR_UNKNOWN; // should not reach here
+ }
+
+ *characteristics = new ACameraMetadata(
+ rawMetadata.release(), ACameraMetadata::ACM_CHARACTERISTICS);
+ return ACAMERA_OK;
+}
+
+camera_status_t
+ACameraManager::openCamera(
+ const char* cameraId,
+ ACameraDevice_StateCallbacks* callback,
+ /*out*/ACameraDevice** outDevice) {
+ ACameraMetadata* rawChars;
+ camera_status_t ret = getCameraCharacteristics(cameraId, &rawChars);
+ Mutex::Autolock _l(mLock);
+ if (ret != ACAMERA_OK) {
+ ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
+ __FUNCTION__, cameraId, ret);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ std::unique_ptr<ACameraMetadata> chars(rawChars);
+ rawChars = nullptr;
+
+ ACameraDevice* device = new ACameraDevice(cameraId, callback, std::move(chars));
+
+ sp<ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+ if (cs == nullptr) {
+ ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
+ return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+ }
+
+ int id = atoi(cameraId);
+ sp<ICameraDeviceCallbacks> callbacks = device->getServiceCallback();
+ sp<ICameraDeviceUser> deviceRemote;
+ // No way to get package name from native.
+ // Send a zero length package name and let camera service figure it out from UID
+ status_t serviceRet = cs->connectDevice(
+ callbacks, id, String16(""),
+ ICameraService::USE_CALLING_UID, /*out*/deviceRemote);
+
+ if (serviceRet != OK) {
+ ALOGE("%s: connect camera device failed! err %d", __FUNCTION__, serviceRet);
+ // TODO: generate better error message here
+ delete device;
+ return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+ }
+ if (deviceRemote == nullptr) {
+ ALOGE("%s: connect camera device failed! remote device is null", __FUNCTION__);
+ delete device;
+ return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+ }
+ device->setRemoteDevice(deviceRemote);
+ *outDevice = device;
+ return ACAMERA_OK;
+}
+
+ACameraManager::~ACameraManager() {
+ Mutex::Autolock _l(mLock);
+ if (mCachedCameraIdList.numCameras != kCameraIdListNotInit) {
+ for (int i = 0; i < mCachedCameraIdList.numCameras; i++) {
+ delete[] mCachedCameraIdList.cameraIds[i];
+ }
+ delete[] mCachedCameraIdList.cameraIds;
+ }
+}
+
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
new file mode 100644
index 0000000..b68685d
--- /dev/null
+++ b/camera/ndk/impl/ACameraManager.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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 _ACAMERA_MANAGER_H
+#define _ACAMERA_MANAGER_H
+
+#include "NdkCameraManager.h"
+
+#include <camera/CameraMetadata.h>
+#include <camera/ICameraService.h>
+#include <camera/ICameraServiceListener.h>
+#include <binder/IServiceManager.h>
+#include <utils/StrongPointer.h>
+#include <utils/Mutex.h>
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <set>
+#include <map>
+
+using namespace android;
+
+namespace android {
+
+/**
+ * Per-process singleton instance of CameraManger. Shared by all ACameraManager
+ * instances. Created when first ACameraManager is created and destroyed when
+ * all ACameraManager instances are deleted.
+ *
+ * TODO: maybe CameraManagerGlobal is better sutied in libcameraclient?
+ */
+class CameraManagerGlobal final : public RefBase {
+ public:
+ static CameraManagerGlobal& getInstance();
+ sp<ICameraService> getCameraService();
+
+ void registerAvailabilityCallback(
+ const ACameraManager_AvailabilityCallbacks *callback);
+ void unregisterAvailabilityCallback(
+ const ACameraManager_AvailabilityCallbacks *callback);
+
+ private:
+ sp<ICameraService> mCameraService;
+ const int kCameraServicePollDelay = 500000; // 0.5s
+ const char* kCameraServiceName = "media.camera";
+ Mutex mLock;
+
+ class DeathNotifier : public IBinder::DeathRecipient {
+ public:
+ DeathNotifier(CameraManagerGlobal* cm) : mCameraManager(cm) {}
+ protected:
+ // IBinder::DeathRecipient implementation
+ virtual void binderDied(const wp<IBinder>& who);
+ private:
+ const wp<CameraManagerGlobal> mCameraManager;
+ };
+ sp<DeathNotifier> mDeathNotifier;
+
+ class CameraServiceListener final : public BnCameraServiceListener {
+ public:
+ CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {}
+ virtual void onStatusChanged(Status status, int32_t cameraId);
+
+ // Torch API not implemented yet
+ virtual void onTorchStatusChanged(TorchStatus, const String16&) {};
+ private:
+ const wp<CameraManagerGlobal> mCameraManager;
+ };
+ sp<CameraServiceListener> mCameraServiceListener;
+
+ // Wrapper of ACameraManager_AvailabilityCallbacks so we can store it in std::set
+ struct Callback {
+ Callback(const ACameraManager_AvailabilityCallbacks *callback) :
+ mAvailable(callback->onCameraAvailable),
+ mUnavailable(callback->onCameraUnavailable),
+ mContext(callback->context) {}
+
+ bool operator == (const Callback& other) const {
+ return (mAvailable == other.mAvailable &&
+ mUnavailable == other.mUnavailable &&
+ mContext == other.mContext);
+ }
+ bool operator != (const Callback& other) const {
+ return !(*this == other);
+ }
+ bool operator < (const Callback& other) const {
+ if (*this == other) return false;
+ if (mContext != other.mContext) return mContext < other.mContext;
+ if (mAvailable != other.mAvailable) return mAvailable < other.mAvailable;
+ return mUnavailable < other.mUnavailable;
+ }
+ bool operator > (const Callback& other) const {
+ return (*this != other && !(*this < other));
+ }
+ ACameraManager_AvailabilityCallback mAvailable;
+ ACameraManager_AvailabilityCallback mUnavailable;
+ void* mContext;
+ };
+ std::set<Callback> mCallbacks;
+
+ // definition of handler and message
+ enum {
+ kWhatSendSingleCallback
+ };
+ static const char* kCameraIdKey;
+ static const char* kCallbackFpKey;
+ static const char* kContextKey;
+ class CallbackHandler : public AHandler {
+ public:
+ CallbackHandler() {}
+ void onMessageReceived(const sp<AMessage> &msg) override;
+ private:
+ inline void sendSingleCallback(
+ int32_t cameraId, void* context,
+ ACameraManager_AvailabilityCallback cb) const;
+ };
+ sp<CallbackHandler> mHandler;
+ sp<ALooper> mCbLooper; // Looper thread where callbacks actually happen on
+
+ typedef ICameraServiceListener::Status Status;
+ void onStatusChanged(Status status, int32_t cameraId);
+ void onStatusChangedLocked(Status status, int32_t cameraId);
+ // Utils for status
+ static bool validStatus(Status status);
+ static bool isStatusAvailable(Status status);
+
+ // Map camera_id -> status
+ std::map<int32_t, Status> mDeviceStatusMap;
+
+ // For the singleton instance
+ static Mutex sLock;
+ static CameraManagerGlobal* sInstance;
+ CameraManagerGlobal() {};
+ ~CameraManagerGlobal();
+};
+
+} // namespace android;
+
+/**
+ * ACameraManager opaque struct definition
+ * Leave outside of android namespace because it's NDK struct
+ */
+struct ACameraManager {
+ ACameraManager() :
+ mCachedCameraIdList({kCameraIdListNotInit, nullptr}),
+ mGlobalManager(&(CameraManagerGlobal::getInstance())) {}
+ ~ACameraManager();
+ camera_status_t getCameraIdList(ACameraIdList** cameraIdList);
+ static void deleteCameraIdList(ACameraIdList* cameraIdList);
+
+ camera_status_t getCameraCharacteristics(
+ const char *cameraId, ACameraMetadata **characteristics);
+ camera_status_t openCamera(const char* cameraId,
+ ACameraDevice_StateCallbacks* callback,
+ /*out*/ACameraDevice** device);
+
+ private:
+ camera_status_t getOrCreateCameraIdListLocked(ACameraIdList** cameraIdList);
+
+ enum {
+ kCameraIdListNotInit = -1
+ };
+ Mutex mLock;
+ std::set<int> mCameraIds; // Init by getOrCreateCameraIdListLocked
+ ACameraIdList mCachedCameraIdList; // Init by getOrCreateCameraIdListLocked
+ sp<CameraManagerGlobal> mGlobalManager;
+};
+
+#endif //_ACAMERA_MANAGER_H
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
new file mode 100644
index 0000000..f121391
--- /dev/null
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ACameraMetadata"
+
+#include "ACameraMetadata.h"
+#include <utils/Vector.h>
+
+using namespace android;
+
+/**
+ * ACameraMetadata Implementation
+ */
+ACameraMetadata::ACameraMetadata(camera_metadata_t* buffer, ACAMERA_METADATA_TYPE type) :
+ mData(buffer), mType(type) {
+ if (mType == ACM_CHARACTERISTICS) {
+ filterUnsupportedFeatures();
+ }
+ // TODO: filter request/result keys
+}
+
+bool
+ACameraMetadata::isNdkSupportedCapability(int32_t capability) {
+ switch (capability) {
+ case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE:
+ case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR:
+ case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING:
+ case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW:
+ case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS:
+ case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE:
+ case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT:
+ return true;
+ case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING:
+ case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING:
+ case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO:
+ return false;
+ default:
+ // Newly defined capabilities will be unsupported by default (blacklist)
+ // TODO: Should we do whitelist or blacklist here?
+ ALOGE("%s: Unknonwn capability %d", __FUNCTION__, capability);
+ return false;
+ }
+}
+
+void
+ACameraMetadata::filterUnsupportedFeatures() {
+ // Hide unsupported capabilities (reprocessing)
+ camera_metadata_entry entry = mData.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+ if (entry.count == 0 || entry.type != ACAMERA_TYPE_BYTE) {
+ ALOGE("%s: malformed available capability key! count %zu, type %d",
+ __FUNCTION__, entry.count, entry.type);
+ return;
+ }
+
+ Vector<uint8_t> capabilities;
+ capabilities.setCapacity(entry.count);
+ for (size_t i = 0; i < entry.count; i++) {
+ uint8_t capability = entry.data.u8[i];
+ if (isNdkSupportedCapability(capability)) {
+ capabilities.push(capability);
+ }
+ }
+ mData.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities);
+ // TODO: Hide unsupported streams (input/bidirectional streams)
+}
+
+bool
+ACameraMetadata::isVendorTag(const uint32_t tag) {
+ uint32_t tag_section = tag >> 16;
+ if (tag_section >= VENDOR_SECTION) {
+ return true;
+ }
+ return false;
+}
+
+camera_status_t
+ACameraMetadata::getConstEntry(uint32_t tag, ACameraMetadata_const_entry* entry) const {
+ if (entry == nullptr) {
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ camera_metadata_ro_entry rawEntry = mData.find(tag);
+ if (rawEntry.count == 0) {
+ ALOGE("%s: cannot find metadata tag %d", __FUNCTION__, tag);
+ return ACAMERA_ERROR_METADATA_NOT_FOUND;
+ }
+ entry->tag = tag;
+ entry->type = rawEntry.type;
+ entry->count = rawEntry.count;
+ entry->data.u8 = rawEntry.data.u8;
+ return ACAMERA_OK;
+}
+
+camera_status_t
+ACameraMetadata::update(uint32_t tag, uint32_t count, const uint8_t* data) {
+ return updateImpl<uint8_t>(tag, count, data);
+}
+
+camera_status_t
+ACameraMetadata::update(uint32_t tag, uint32_t count, const int32_t* data) {
+ return updateImpl<int32_t>(tag, count, data);
+}
+
+camera_status_t
+ACameraMetadata::update(uint32_t tag, uint32_t count, const float* data) {
+ return updateImpl<float>(tag, count, data);
+}
+
+camera_status_t
+ACameraMetadata::update(uint32_t tag, uint32_t count, const double* data) {
+ return updateImpl<double>(tag, count, data);
+}
+
+camera_status_t
+ACameraMetadata::update(uint32_t tag, uint32_t count, const int64_t* data) {
+ return updateImpl<int64_t>(tag, count, data);
+}
+
+camera_status_t
+ACameraMetadata::update(uint32_t tag, uint32_t count, const ACameraMetadata_rational* data) {
+ return updateImpl<camera_metadata_rational_t>(tag, count, data);
+}
+
+
+// TODO: some of key below should be hidden from user
+// ex: ACAMERA_REQUEST_ID and ACAMERA_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
+/*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+ * The key entries below this point are generated from metadata
+ * definitions in /system/media/camera/docs. Do not modify by hand or
+ * modify the comment blocks at the start or end.
+ *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
+
+bool
+ACameraMetadata::isCaptureRequestTag(const uint32_t tag) {
+ // Skip check for vendor keys
+ if (isVendorTag(tag)) {
+ return true;
+ }
+
+ switch (tag) {
+ case ACAMERA_COLOR_CORRECTION_MODE:
+ case ACAMERA_COLOR_CORRECTION_TRANSFORM:
+ case ACAMERA_COLOR_CORRECTION_GAINS:
+ case ACAMERA_COLOR_CORRECTION_ABERRATION_MODE:
+ case ACAMERA_CONTROL_AE_ANTIBANDING_MODE:
+ case ACAMERA_CONTROL_AE_EXPOSURE_COMPENSATION:
+ case ACAMERA_CONTROL_AE_LOCK:
+ case ACAMERA_CONTROL_AE_MODE:
+ case ACAMERA_CONTROL_AE_REGIONS:
+ case ACAMERA_CONTROL_AE_TARGET_FPS_RANGE:
+ case ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER:
+ case ACAMERA_CONTROL_AF_MODE:
+ case ACAMERA_CONTROL_AF_REGIONS:
+ case ACAMERA_CONTROL_AF_TRIGGER:
+ case ACAMERA_CONTROL_AWB_LOCK:
+ case ACAMERA_CONTROL_AWB_MODE:
+ case ACAMERA_CONTROL_AWB_REGIONS:
+ case ACAMERA_CONTROL_CAPTURE_INTENT:
+ case ACAMERA_CONTROL_EFFECT_MODE:
+ case ACAMERA_CONTROL_MODE:
+ case ACAMERA_CONTROL_SCENE_MODE:
+ case ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE:
+ case ACAMERA_CONTROL_POST_RAW_SENSITIVITY_BOOST:
+ case ACAMERA_EDGE_MODE:
+ case ACAMERA_FLASH_MODE:
+ case ACAMERA_HOT_PIXEL_MODE:
+ case ACAMERA_JPEG_GPS_COORDINATES:
+ case ACAMERA_JPEG_GPS_PROCESSING_METHOD:
+ case ACAMERA_JPEG_GPS_TIMESTAMP:
+ case ACAMERA_JPEG_ORIENTATION:
+ case ACAMERA_JPEG_QUALITY:
+ case ACAMERA_JPEG_THUMBNAIL_QUALITY:
+ case ACAMERA_JPEG_THUMBNAIL_SIZE:
+ case ACAMERA_LENS_APERTURE:
+ case ACAMERA_LENS_FILTER_DENSITY:
+ case ACAMERA_LENS_FOCAL_LENGTH:
+ case ACAMERA_LENS_FOCUS_DISTANCE:
+ case ACAMERA_LENS_OPTICAL_STABILIZATION_MODE:
+ case ACAMERA_NOISE_REDUCTION_MODE:
+ case ACAMERA_REQUEST_ID:
+ case ACAMERA_SCALER_CROP_REGION:
+ case ACAMERA_SENSOR_EXPOSURE_TIME:
+ case ACAMERA_SENSOR_FRAME_DURATION:
+ case ACAMERA_SENSOR_SENSITIVITY:
+ case ACAMERA_SENSOR_TEST_PATTERN_DATA:
+ case ACAMERA_SENSOR_TEST_PATTERN_MODE:
+ case ACAMERA_SHADING_MODE:
+ case ACAMERA_STATISTICS_FACE_DETECT_MODE:
+ case ACAMERA_STATISTICS_HOT_PIXEL_MAP_MODE:
+ case ACAMERA_STATISTICS_LENS_SHADING_MAP_MODE:
+ case ACAMERA_TONEMAP_CURVE_BLUE:
+ case ACAMERA_TONEMAP_CURVE_GREEN:
+ case ACAMERA_TONEMAP_CURVE_RED:
+ case ACAMERA_TONEMAP_MODE:
+ case ACAMERA_TONEMAP_GAMMA:
+ case ACAMERA_TONEMAP_PRESET_CURVE:
+ case ACAMERA_LED_TRANSMIT:
+ case ACAMERA_BLACK_LEVEL_LOCK:
+ case ACAMERA_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+ * End generated code
+ *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/camera/ndk/impl/ACameraMetadata.h b/camera/ndk/impl/ACameraMetadata.h
new file mode 100644
index 0000000..fa0149a
--- /dev/null
+++ b/camera/ndk/impl/ACameraMetadata.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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 _ACAMERA_METADATA_H
+#define _ACAMERA_METADATA_H
+
+#include <sys/types.h>
+#include <utils/RefBase.h>
+#include <camera/CameraMetadata.h>
+
+#include "NdkCameraMetadata.h"
+
+using namespace android;
+
+/**
+ * ACameraMetadata opaque struct definition
+ * Leave outside of android namespace because it's NDK struct
+ */
+struct ACameraMetadata : public RefBase {
+ public:
+ typedef enum {
+ ACM_CHARACTERISTICS, // Read only
+ ACM_REQUEST, // Read/Write
+ ACM_RESULT, // Read only
+ } ACAMERA_METADATA_TYPE;
+
+ // Takes ownership of pass-in buffer
+ ACameraMetadata(camera_metadata_t *buffer, ACAMERA_METADATA_TYPE type);
+ // Clone
+ ACameraMetadata(const ACameraMetadata& other) :
+ mData(other.mData), mType(other.mType) {};
+
+ camera_status_t getConstEntry(uint32_t tag, ACameraMetadata_const_entry* entry) const;
+
+ camera_status_t update(uint32_t tag, uint32_t count, const uint8_t* data);
+ camera_status_t update(uint32_t tag, uint32_t count, const int32_t* data);
+ camera_status_t update(uint32_t tag, uint32_t count, const float* data);
+ camera_status_t update(uint32_t tag, uint32_t count, const double* data);
+ camera_status_t update(uint32_t tag, uint32_t count, const int64_t* data);
+ camera_status_t update(uint32_t tag, uint32_t count, const ACameraMetadata_rational* data);
+
+ bool isNdkSupportedCapability(const int32_t capability);
+ inline bool isVendorTag(const uint32_t tag);
+ bool isCaptureRequestTag(const uint32_t tag);
+ void filterUnsupportedFeatures(); // Hide features not yet supported by NDK
+
+ template<typename INTERNAL_T, typename NDK_T>
+ camera_status_t updateImpl(uint32_t tag, uint32_t count, const NDK_T* data) {
+ if (mType != ACM_REQUEST) {
+ ALOGE("Error: Write to metadata is only allowed for capture request!");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ if (!isCaptureRequestTag(tag)) {
+ ALOGE("Error: tag %d is not writable!", tag);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ // Here we have to use reinterpret_cast because the NDK data type is
+ // exact copy of internal data type but they do not inherit from each other
+ status_t ret = mData.update(tag, reinterpret_cast<const INTERNAL_T*>(data), count);
+ if (ret == OK) {
+ return ACAMERA_OK;
+ } else {
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ CameraMetadata mData;
+ const ACAMERA_METADATA_TYPE mType;
+};
+
+#endif // _ACAMERA_METADATA_H
diff --git a/camera/ndk/impl/ACaptureRequest.h b/camera/ndk/impl/ACaptureRequest.h
new file mode 100644
index 0000000..6bd8406
--- /dev/null
+++ b/camera/ndk/impl/ACaptureRequest.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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 _ACAPTURE_REQUEST_H
+#define _ACAPTURE_REQUEST_H
+
+#include "NdkCaptureRequest.h"
+#include <set>
+
+using namespace android;
+
+struct ACameraOutputTarget {
+ ACameraOutputTarget(ANativeWindow* window) : mWindow(window) {};
+
+ bool operator == (const ACameraOutputTarget& other) const {
+ return mWindow == other.mWindow;
+ }
+ bool operator != (const ACameraOutputTarget& other) const {
+ return mWindow != other.mWindow;
+ }
+ bool operator < (const ACameraOutputTarget& other) const {
+ return mWindow < other.mWindow;
+ }
+ bool operator > (const ACameraOutputTarget& other) const {
+ return mWindow > other.mWindow;
+ }
+
+ ANativeWindow* mWindow;
+};
+
+struct ACameraOutputTargets {
+ std::set<ACameraOutputTarget> mOutputs;
+};
+
+struct ACaptureRequest {
+ ACameraMetadata* settings;
+ ACameraOutputTargets* targets;
+};
+
+#endif // _ACAPTURE_REQUEST_H
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 78a1b58..a36d2f9 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -243,16 +243,36 @@
};
+namespace {
+ Mutex gLock;
+ class DeathNotifier : public IBinder::DeathRecipient
+ {
+ public:
+ DeathNotifier() {}
+
+ virtual void binderDied(const wp<IBinder>& /*who*/) {
+ ALOGV("binderDied");
+ Mutex::Autolock _l(gLock);
+ ALOGW("Camera service died!");
+ }
+ };
+ sp<DeathNotifier> gDeathNotifier;
+}; // anonymous namespace
+
// Exercise basic binder calls for the camera service
TEST(CameraServiceBinderTest, CheckBinderCameraService) {
ProcessState::self()->startThreadPool();
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("media.camera"));
ASSERT_NOT_NULL(binder);
+ if (gDeathNotifier == NULL) {
+ gDeathNotifier = new DeathNotifier();
+ }
+ binder->linkToDeath(gDeathNotifier);
sp<ICameraService> service = interface_cast<ICameraService>(binder);
- int32_t numCameras = service->getNumberOfCameras();
+ int32_t numCameras = service->getNumberOfCameras(ICameraService::CAMERA_TYPE_ALL);
EXPECT_LE(0, numCameras);
// Check listener binder calls
diff --git a/include/camera/camera2/CaptureRequest.h b/include/camera/camera2/CaptureRequest.h
index eeab217..1dd15c4 100644
--- a/include/camera/camera2/CaptureRequest.h
+++ b/include/camera/camera2/CaptureRequest.h
@@ -25,7 +25,7 @@
class Surface;
-struct CaptureRequest : public virtual RefBase {
+struct CaptureRequest : public RefBase {
public:
CameraMetadata mMetadata;
diff --git a/include/camera/camera2/OutputConfiguration.h b/include/camera/camera2/OutputConfiguration.h
index 5bcbe15..137d98c 100644
--- a/include/camera/camera2/OutputConfiguration.h
+++ b/include/camera/camera2/OutputConfiguration.h
@@ -17,19 +17,20 @@
#ifndef ANDROID_HARDWARE_CAMERA2_OUTPUTCONFIGURATION_H
#define ANDROID_HARDWARE_CAMERA2_OUTPUTCONFIGURATION_H
-#include <utils/RefBase.h>
#include <gui/IGraphicBufferProducer.h>
namespace android {
class Surface;
-class OutputConfiguration : public virtual RefBase {
+class OutputConfiguration {
public:
static const int INVALID_ROTATION;
+ static const int INVALID_SET_ID;
sp<IGraphicBufferProducer> getGraphicBufferProducer() const;
int getRotation() const;
+ int getSurfaceSetID() const;
/**
* Keep impl up-to-date with OutputConfiguration.java in frameworks/base
@@ -39,12 +40,29 @@
// getRotation will be INVALID_ROTATION if error occurred
OutputConfiguration(const Parcel& parcel);
- OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation);
+ OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
+ int surfaceSetID = INVALID_SET_ID);
+
+ bool operator == (const OutputConfiguration& other) const {
+ return (mGbp == other.mGbp &&
+ mRotation == other.mRotation);
+ }
+ bool operator != (const OutputConfiguration& other) const {
+ return !(*this == other);
+ }
+ bool operator < (const OutputConfiguration& other) const {
+ if (*this == other) return false;
+ if (mGbp != other.mGbp) return mGbp < other.mGbp;
+ return mRotation < other.mRotation;
+ }
+ bool operator > (const OutputConfiguration& other) const {
+ return (*this != other && !(*this < other));
+ }
private:
sp<IGraphicBufferProducer> mGbp;
int mRotation;
-
+ int mSurfaceSetID;
// helper function
static String16 readMaybeEmptyString16(const Parcel& parcel);
};
diff --git a/include/camera/ndk/NdkCameraCaptureSession.h b/include/camera/ndk/NdkCameraCaptureSession.h
new file mode 100644
index 0000000..5d5cae2
--- /dev/null
+++ b/include/camera/ndk/NdkCameraCaptureSession.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+#include "NdkCameraError.h"
+#include "NdkCameraMetadata.h"
+
+#ifndef _NDK_CAMERA_CAPTURE_SESSION_H
+#define _NDK_CAMERA_CAPTURE_SESSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ACameraCaptureSession ACameraCaptureSession;
+
+typedef void (*ACameraCaptureSession_stateCallback)(void* context, ACameraCaptureSession *session);
+
+typedef struct ACameraCaptureSession_stateCallbacks {
+ void* context;
+ ACameraCaptureSession_stateCallback onClosed; // session is unusable after this callback
+ ACameraCaptureSession_stateCallback onReady;
+ ACameraCaptureSession_stateCallback onActive;
+} ACameraCaptureSession_stateCallbacks;
+
+enum {
+ CAPTURE_FAILURE_REASON_FLUSHED = 0,
+ CAPTURE_FAILURE_REASON_ERROR
+};
+
+typedef struct ACameraCaptureFailure {
+ int64_t frameNumber;
+ int reason;
+ int sequenceId;
+ bool wasImageCaptured;
+} ACameraCaptureFailure;
+
+/* Note that the ACaptureRequest* in the callback will be different to what app has submitted,
+ but the contents will still be the same as what app submitted */
+typedef void (*ACameraCaptureSession_captureCallback_start)(
+ void* context, ACameraCaptureSession* session,
+ const ACaptureRequest* request, int64_t timestamp);
+
+typedef void (*ACameraCaptureSession_captureCallback_result)(
+ void* context, ACameraCaptureSession* session,
+ ACaptureRequest* request, const ACameraMetadata* result);
+
+typedef void (*ACameraCaptureSession_captureCallback_failed)(
+ void* context, ACameraCaptureSession* session,
+ ACaptureRequest* request, ACameraCaptureFailure* failure);
+
+typedef void (*ACameraCaptureSession_captureCallback_sequenceEnd)(
+ void* context, ACameraCaptureSession* session,
+ int sequenceId, int64_t frameNumber);
+
+typedef void (*ACameraCaptureSession_captureCallback_sequenceAbort)(
+ void* context, ACameraCaptureSession* session,
+ int sequenceId);
+
+typedef struct ACameraCaptureSession_captureCallbacks {
+ void* context;
+ ACameraCaptureSession_captureCallback_start onCaptureStarted;
+ ACameraCaptureSession_captureCallback_result onCaptureProgressed;
+ ACameraCaptureSession_captureCallback_result onCaptureCompleted;
+ ACameraCaptureSession_captureCallback_failed onCaptureFailed;
+ ACameraCaptureSession_captureCallback_sequenceEnd onCaptureSequenceCompleted;
+ ACameraCaptureSession_captureCallback_sequenceAbort onCaptureSequenceAborted;
+} ACameraCaptureSession_captureCallbacks;
+
+enum {
+ CAPTURE_SEQUENCE_ID_NONE = -1
+};
+
+/*
+ * Close capture session
+ */
+void ACameraCaptureSession_close(ACameraCaptureSession*);
+
+struct ACameraDevice;
+typedef struct ACameraDevice ACameraDevice;
+
+/**
+ * Get the camera device associated with this capture session
+ */
+camera_status_t ACameraCaptureSession_getDevice(
+ ACameraCaptureSession*, ACameraDevice** device);
+
+/**
+ * Send capture request(s)
+ */
+camera_status_t ACameraCaptureSession_capture(
+ ACameraCaptureSession*, /*optional*/ACameraCaptureSession_captureCallbacks*,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId);
+
+/**
+ * Send repeating capture request(s)
+ */
+camera_status_t ACameraCaptureSession_setRepeatingRequest(
+ ACameraCaptureSession*, /*optional*/ACameraCaptureSession_captureCallbacks*,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId);
+
+/**
+ * Stop repeating capture request(s)
+ */
+camera_status_t ACameraCaptureSession_stopRepeating(ACameraCaptureSession*);
+
+/**
+ * Stop all capture requests as soon as possible
+ */
+camera_status_t ACameraCaptureSession_abortCaptures(ACameraCaptureSession*);
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _NDK_CAMERA_CAPTURE_SESSION_H
diff --git a/include/camera/ndk/NdkCameraDevice.h b/include/camera/ndk/NdkCameraDevice.h
new file mode 100644
index 0000000..2008a68
--- /dev/null
+++ b/include/camera/ndk/NdkCameraDevice.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+
+#include <android/native_window.h>
+#include "NdkCameraError.h"
+#include "NdkCaptureRequest.h"
+#include "NdkCameraCaptureSession.h"
+
+#ifndef _NDK_CAMERA_DEVICE_H
+#define _NDK_CAMERA_DEVICE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ACameraDevice ACameraDevice;
+
+// Struct to hold camera state callbacks
+typedef void (*ACameraDevice_StateCallback)(void* context, ACameraDevice* device);
+typedef void (*ACameraDevice_ErrorStateCallback)(void* context, ACameraDevice* device, int error);
+
+typedef struct ACameraDevice_StateCallbacks {
+ void* context;
+ ACameraDevice_StateCallback onDisconnected; // Device is unusable after this callback
+ ACameraDevice_ErrorStateCallback onError; // Device is unusable after this callback
+} ACameraDevice_stateCallbacks;
+
+/**
+ * Close the camera device synchronously. Open is done in ACameraManager_openCamera
+ */
+camera_status_t ACameraDevice_close(ACameraDevice*);
+
+/**
+ * Return the camera id associated with this camera device
+ * The returned pointer is still owned by framework and should not be delete/free by app
+ * The returned pointer should not be used after the device has been closed
+ */
+const char* ACameraDevice_getId(const ACameraDevice*);
+
+typedef enum {
+ TEMPLATE_PREVIEW = 1,
+ TEMPLATE_STILL_CAPTURE,
+ TEMPLATE_RECORD,
+ TEMPLATE_VIDEO_SNAPSHOT,
+ TEMPLATE_ZERO_SHUTTER_LAG,
+ TEMPLATE_MANUAL,
+} ACameraDevice_request_template;
+
+/**
+ * Create/free a default capture request for input template
+ */
+camera_status_t ACameraDevice_createCaptureRequest(
+ const ACameraDevice*, ACameraDevice_request_template, /*out*/ACaptureRequest** request);
+
+/**
+ * APIs for createing capture session
+ */
+typedef struct ACaptureSessionOutputContainer ACaptureSessionOutputContainer;
+
+typedef struct ACaptureSessionOutput ACaptureSessionOutput;
+
+camera_status_t ACaptureSessionOutputContainer_create(/*out*/ACaptureSessionOutputContainer**);
+void ACaptureSessionOutputContainer_free(ACaptureSessionOutputContainer*);
+
+camera_status_t ACaptureSessionOutput_create(ANativeWindow*, /*out*/ACaptureSessionOutput**);
+void ACaptureSessionOutput_free(ACaptureSessionOutput*);
+
+camera_status_t ACaptureSessionOutputContainer_add(
+ ACaptureSessionOutputContainer*, const ACaptureSessionOutput*);
+camera_status_t ACaptureSessionOutputContainer_remove(
+ ACaptureSessionOutputContainer*, const ACaptureSessionOutput*);
+
+/*
+ * Create a new capture session.
+ * If there is a preexisting session, the previous session will be closed automatically.
+ * However, app still needs to call ACameraCaptureSession_close on previous session.
+ * Otherwise the resources hold by previous session won't be freed
+ */
+camera_status_t ACameraDevice_createCaptureSession(
+ ACameraDevice*,
+ const ACaptureSessionOutputContainer* outputs,
+ const ACameraCaptureSession_stateCallbacks* callbacks,
+ /*out*/ACameraCaptureSession** session);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _NDK_CAMERA_DEVICE_H
diff --git a/include/camera/ndk/NdkCameraError.h b/include/camera/ndk/NdkCameraError.h
new file mode 100644
index 0000000..6d671de
--- /dev/null
+++ b/include/camera/ndk/NdkCameraError.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+
+#ifndef _NDK_CAMERA_ERROR_H
+#define _NDK_CAMERA_ERROR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ ACAMERA_OK = 0,
+
+ ACAMERA_ERROR_BASE = -10000,
+ ACAMERA_ERROR_UNKNOWN = ACAMERA_ERROR_BASE,
+ ACAMERA_ERROR_UNSUPPORTED = ACAMERA_ERROR_BASE - 1,
+ ACAMERA_ERROR_INVALID_PARAMETER = ACAMERA_ERROR_BASE - 2,
+ ACAMERA_ERROR_CAMERA_DISCONNECTED = ACAMERA_ERROR_BASE - 3,
+ ACAMERA_ERROR_NOT_ENOUGH_MEMORY = ACAMERA_ERROR_BASE - 4,
+ ACAMERA_ERROR_METADATA_NOT_FOUND = ACAMERA_ERROR_BASE - 5,
+ ACAMERA_ERROR_CAMERA_DEVICE = ACAMERA_ERROR_BASE - 6,
+ ACAMERA_ERROR_CAMERA_SERVICE = ACAMERA_ERROR_BASE - 7,
+ ACAMERA_ERROR_CAMERA_REQUEST = ACAMERA_ERROR_BASE - 8,
+ ACAMERA_ERROR_CAMERA_RESULT = ACAMERA_ERROR_BASE - 9,
+ ACAMERA_ERROR_CAMERA_BUFFER = ACAMERA_ERROR_BASE - 10,
+ ACAMERA_ERROR_SESSION_CLOSED = ACAMERA_ERROR_BASE - 11,
+ ACAMERA_ERROR_SESSION_NOT_DRAINED = ACAMERA_ERROR_BASE - 12,
+ ACAMERA_ERROR_INVALID_OPERATION = ACAMERA_ERROR_BASE - 13,
+ ACAMERA_ERROR_TIMEOUT = ACAMERA_ERROR_BASE - 14,
+ ACAMERA_ERROR_STREAM_CONFIGURE_FAIL = ACAMERA_ERROR_BASE - 15,
+} camera_status_t;
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _NDK_CAMERA_ERROR_H
diff --git a/include/camera/ndk/NdkCameraManager.h b/include/camera/ndk/NdkCameraManager.h
new file mode 100644
index 0000000..adef6ed
--- /dev/null
+++ b/include/camera/ndk/NdkCameraManager.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+
+#ifndef _NDK_CAMERA_MANAGER_H
+#define _NDK_CAMERA_MANAGER_H
+
+#include "NdkCameraError.h"
+#include "NdkCameraMetadata.h"
+#include "NdkCameraDevice.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ACameraManager ACameraManager;
+
+/**
+ * Create CameraManager instance.
+ * The caller must call ACameraManager_delete to free the resources
+ */
+ACameraManager* ACameraManager_create();
+
+/**
+ * delete the ACameraManager and free its resources
+ */
+void ACameraManager_delete(ACameraManager*);
+
+// Struct to hold list of camera devices
+typedef struct ACameraIdList {
+ int numCameras;
+ const char** cameraIds;
+} ACameraIdList;
+
+/**
+ * Create/delete a list of camera devices.
+ * ACameraManager_getCameraIdList will allocate and return an ACameraIdList.
+ * The caller must call ACameraManager_deleteCameraIdList to free the memory
+ */
+camera_status_t ACameraManager_getCameraIdList(ACameraManager*,
+ /*out*/ACameraIdList** cameraIdList);
+void ACameraManager_deleteCameraIdList(ACameraIdList* cameraIdList);
+
+
+// Struct to hold camera availability callbacks
+typedef void (*ACameraManager_AvailabilityCallback)(void* context, const char* cameraId);
+
+typedef struct ACameraManager_AvailabilityListener {
+ void* context; // optional application context.
+ ACameraManager_AvailabilityCallback onCameraAvailable;
+ ACameraManager_AvailabilityCallback onCameraUnavailable;
+} ACameraManager_AvailabilityCallbacks;
+
+/**
+ * register/unregister camera availability callbacks
+ */
+camera_status_t ACameraManager_registerAvailabilityCallback(
+ ACameraManager*, const ACameraManager_AvailabilityCallbacks *callback);
+camera_status_t ACameraManager_unregisterAvailabilityCallback(
+ ACameraManager*, const ACameraManager_AvailabilityCallbacks *callback);
+
+/**
+ * Query the characteristics of a camera.
+ * The caller must call ACameraMetadata_free to free the memory of the output characteristics.
+ */
+camera_status_t ACameraManager_getCameraCharacteristics(
+ ACameraManager*, const char *cameraId,
+ /*out*/ACameraMetadata **characteristics);
+
+/**
+ * Open a camera device synchronously.
+ * The opened camera device will be returned in
+ */
+camera_status_t ACameraManager_openCamera(
+ ACameraManager*, const char* cameraId,
+ ACameraDevice_StateCallbacks* callback,
+ /*out*/ACameraDevice** device);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif //_NDK_CAMERA_MANAGER_H
diff --git a/include/camera/ndk/NdkCameraMetadata.h b/include/camera/ndk/NdkCameraMetadata.h
new file mode 100644
index 0000000..56412ad
--- /dev/null
+++ b/include/camera/ndk/NdkCameraMetadata.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+
+#ifndef _NDK_CAMERA_METADATA_H
+#define _NDK_CAMERA_METADATA_H
+
+#include "NdkCameraError.h"
+#include "NdkCameraMetadataTags.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ACameraMetadata ACameraMetadata;
+
+// Keep in sync with system/media/include/system/camera_metadata.h
+enum {
+ // Unsigned 8-bit integer (uint8_t)
+ ACAMERA_TYPE_BYTE = 0,
+ // Signed 32-bit integer (int32_t)
+ ACAMERA_TYPE_INT32 = 1,
+ // 32-bit float (float)
+ ACAMERA_TYPE_FLOAT = 2,
+ // Signed 64-bit integer (int64_t)
+ ACAMERA_TYPE_INT64 = 3,
+ // 64-bit float (double)
+ ACAMERA_TYPE_DOUBLE = 4,
+ // A 64-bit fraction (ACameraMetadata_rational)
+ ACAMERA_TYPE_RATIONAL = 5,
+ // Number of type fields
+ ACAMERA_NUM_TYPES
+};
+
+typedef struct ACameraMetadata_rational {
+ int32_t numerator;
+ int32_t denominator;
+} ACameraMetadata_rational;
+
+typedef struct ACameraMetadata_entry {
+ uint32_t tag;
+ uint8_t type;
+ uint32_t count;
+ union {
+ uint8_t *u8;
+ int32_t *i32;
+ float *f;
+ int64_t *i64;
+ double *d;
+ ACameraMetadata_rational* r;
+ } data;
+} ACameraMetadata_entry;
+
+typedef struct ACameraMetadata_const_entry {
+ uint32_t tag;
+ uint8_t type;
+ uint32_t count;
+ union {
+ const uint8_t *u8;
+ const int32_t *i32;
+ const float *f;
+ const int64_t *i64;
+ const double *d;
+ const ACameraMetadata_rational* r;
+ } data;
+} ACameraMetadata_const_entry;
+
+/*
+ * Get a metadata entry
+ */
+camera_status_t ACameraMetadata_getConstEntry(
+ const ACameraMetadata*, uint32_t tag, ACameraMetadata_const_entry* entry);
+
+// TODO: need an API to list all tags in the metadata. Same for ACaptureRequest
+
+/**
+ * Copy a metadata. Duplicates a metadata structure.
+ * The destination ACameraMetadata must be freed by the application with ACameraMetadata_free
+ * after application is done using it.
+ * Returns NULL when src cannot be copied
+ */
+ACameraMetadata* ACameraMetadata_copy(const ACameraMetadata* src);
+
+/**
+ * Frees a metadata structure.
+ */
+void ACameraMetadata_free(ACameraMetadata*);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif //_NDK_CAMERA_METADATA_H
diff --git a/include/camera/ndk/NdkCameraMetadataTags.h b/include/camera/ndk/NdkCameraMetadataTags.h
new file mode 100644
index 0000000..0c398be
--- /dev/null
+++ b/include/camera/ndk/NdkCameraMetadataTags.h
@@ -0,0 +1,877 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+
+#ifndef _NDK_CAMERA_METADATA_TAGS_H
+#define _NDK_CAMERA_METADATA_TAGS_H
+
+typedef enum acamera_metadata_section {
+ ACAMERA_COLOR_CORRECTION,
+ ACAMERA_CONTROL,
+ ACAMERA_DEMOSAIC,
+ ACAMERA_EDGE,
+ ACAMERA_FLASH,
+ ACAMERA_FLASH_INFO,
+ ACAMERA_HOT_PIXEL,
+ ACAMERA_JPEG,
+ ACAMERA_LENS,
+ ACAMERA_LENS_INFO,
+ ACAMERA_NOISE_REDUCTION,
+ ACAMERA_QUIRKS,
+ ACAMERA_REQUEST,
+ ACAMERA_SCALER,
+ ACAMERA_SENSOR,
+ ACAMERA_SENSOR_INFO,
+ ACAMERA_SHADING,
+ ACAMERA_STATISTICS,
+ ACAMERA_STATISTICS_INFO,
+ ACAMERA_TONEMAP,
+ ACAMERA_LED,
+ ACAMERA_INFO,
+ ACAMERA_BLACK_LEVEL,
+ ACAMERA_SYNC,
+ ACAMERA_REPROCESS,
+ ACAMERA_DEPTH,
+ ACAMERA_SECTION_COUNT,
+
+ ACAMERA_VENDOR = 0x8000
+} acamera_metadata_section_t;
+
+/**
+ * Hierarchy positions in enum space.
+ */
+typedef enum acamera_metadata_section_start {
+ ACAMERA_COLOR_CORRECTION_START = ACAMERA_COLOR_CORRECTION << 16,
+ ACAMERA_CONTROL_START = ACAMERA_CONTROL << 16,
+ ACAMERA_DEMOSAIC_START = ACAMERA_DEMOSAIC << 16,
+ ACAMERA_EDGE_START = ACAMERA_EDGE << 16,
+ ACAMERA_FLASH_START = ACAMERA_FLASH << 16,
+ ACAMERA_FLASH_INFO_START = ACAMERA_FLASH_INFO << 16,
+ ACAMERA_HOT_PIXEL_START = ACAMERA_HOT_PIXEL << 16,
+ ACAMERA_JPEG_START = ACAMERA_JPEG << 16,
+ ACAMERA_LENS_START = ACAMERA_LENS << 16,
+ ACAMERA_LENS_INFO_START = ACAMERA_LENS_INFO << 16,
+ ACAMERA_NOISE_REDUCTION_START = ACAMERA_NOISE_REDUCTION << 16,
+ ACAMERA_QUIRKS_START = ACAMERA_QUIRKS << 16,
+ ACAMERA_REQUEST_START = ACAMERA_REQUEST << 16,
+ ACAMERA_SCALER_START = ACAMERA_SCALER << 16,
+ ACAMERA_SENSOR_START = ACAMERA_SENSOR << 16,
+ ACAMERA_SENSOR_INFO_START = ACAMERA_SENSOR_INFO << 16,
+ ACAMERA_SHADING_START = ACAMERA_SHADING << 16,
+ ACAMERA_STATISTICS_START = ACAMERA_STATISTICS << 16,
+ ACAMERA_STATISTICS_INFO_START = ACAMERA_STATISTICS_INFO << 16,
+ ACAMERA_TONEMAP_START = ACAMERA_TONEMAP << 16,
+ ACAMERA_LED_START = ACAMERA_LED << 16,
+ ACAMERA_INFO_START = ACAMERA_INFO << 16,
+ ACAMERA_BLACK_LEVEL_START = ACAMERA_BLACK_LEVEL << 16,
+ ACAMERA_SYNC_START = ACAMERA_SYNC << 16,
+ ACAMERA_REPROCESS_START = ACAMERA_REPROCESS << 16,
+ ACAMERA_DEPTH_START = ACAMERA_DEPTH << 16,
+ ACAMERA_VENDOR_START = ACAMERA_VENDOR << 16
+} acamera_metadata_section_start_t;
+
+/**
+ * Main enum for camera metadata tags.
+ */
+typedef enum acamera_metadata_tag {
+ ACAMERA_COLOR_CORRECTION_MODE = // byte (enum)
+ ACAMERA_COLOR_CORRECTION_START,
+ ACAMERA_COLOR_CORRECTION_TRANSFORM, // rational[3*3]
+ ACAMERA_COLOR_CORRECTION_GAINS, // float[4]
+ ACAMERA_COLOR_CORRECTION_ABERRATION_MODE, // byte (enum)
+ ACAMERA_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, // byte[n]
+ ACAMERA_COLOR_CORRECTION_END,
+
+ ACAMERA_CONTROL_AE_ANTIBANDING_MODE = // byte (enum)
+ ACAMERA_CONTROL_START,
+ ACAMERA_CONTROL_AE_EXPOSURE_COMPENSATION, // int32
+ ACAMERA_CONTROL_AE_LOCK, // byte (enum)
+ ACAMERA_CONTROL_AE_MODE, // byte (enum)
+ ACAMERA_CONTROL_AE_REGIONS, // int32[5*area_count]
+ ACAMERA_CONTROL_AE_TARGET_FPS_RANGE, // int32[2]
+ ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER, // byte (enum)
+ ACAMERA_CONTROL_AF_MODE, // byte (enum)
+ ACAMERA_CONTROL_AF_REGIONS, // int32[5*area_count]
+ ACAMERA_CONTROL_AF_TRIGGER, // byte (enum)
+ ACAMERA_CONTROL_AWB_LOCK, // byte (enum)
+ ACAMERA_CONTROL_AWB_MODE, // byte (enum)
+ ACAMERA_CONTROL_AWB_REGIONS, // int32[5*area_count]
+ ACAMERA_CONTROL_CAPTURE_INTENT, // byte (enum)
+ ACAMERA_CONTROL_EFFECT_MODE, // byte (enum)
+ ACAMERA_CONTROL_MODE, // byte (enum)
+ ACAMERA_CONTROL_SCENE_MODE, // byte (enum)
+ ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE, // byte (enum)
+ ACAMERA_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, // byte[n]
+ ACAMERA_CONTROL_AE_AVAILABLE_MODES, // byte[n]
+ ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, // int32[2*n]
+ ACAMERA_CONTROL_AE_COMPENSATION_RANGE, // int32[2]
+ ACAMERA_CONTROL_AE_COMPENSATION_STEP, // rational
+ ACAMERA_CONTROL_AF_AVAILABLE_MODES, // byte[n]
+ ACAMERA_CONTROL_AVAILABLE_EFFECTS, // byte[n]
+ ACAMERA_CONTROL_AVAILABLE_SCENE_MODES, // byte[n]
+ ACAMERA_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, // byte[n]
+ ACAMERA_CONTROL_AWB_AVAILABLE_MODES, // byte[n]
+ ACAMERA_CONTROL_MAX_REGIONS, // int32[3]
+ ACAMERA_CONTROL_RESERVED_29,
+ ACAMERA_CONTROL_RESERVED_30,
+ ACAMERA_CONTROL_AE_STATE, // byte (enum)
+ ACAMERA_CONTROL_AF_STATE, // byte (enum)
+ ACAMERA_CONTROL_RESERVED_33,
+ ACAMERA_CONTROL_AWB_STATE, // byte (enum)
+ ACAMERA_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS, // int32[5*n]
+ ACAMERA_CONTROL_AE_LOCK_AVAILABLE, // byte (enum)
+ ACAMERA_CONTROL_AWB_LOCK_AVAILABLE, // byte (enum)
+ ACAMERA_CONTROL_AVAILABLE_MODES, // byte[n]
+ ACAMERA_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE, // int32[2]
+ ACAMERA_CONTROL_POST_RAW_SENSITIVITY_BOOST, // int32
+ ACAMERA_CONTROL_END,
+
+ ACAMERA_DEMOSAIC_RESERVED_0 =
+ ACAMERA_DEMOSAIC_START,
+ ACAMERA_DEMOSAIC_END,
+
+ ACAMERA_EDGE_MODE = // byte (enum)
+ ACAMERA_EDGE_START,
+ ACAMERA_EDGE_RESERVED_1,
+ ACAMERA_EDGE_AVAILABLE_EDGE_MODES, // byte[n]
+ ACAMERA_EDGE_END,
+
+ ACAMERA_FLASH_RESERVED_0 =
+ ACAMERA_FLASH_START,
+ ACAMERA_FLASH_RESERVED_1,
+ ACAMERA_FLASH_MODE, // byte (enum)
+ ACAMERA_FLASH_RESERVED_3,
+ ACAMERA_FLASH_RESERVED_4,
+ ACAMERA_FLASH_STATE, // byte (enum)
+ ACAMERA_FLASH_END,
+
+ ACAMERA_FLASH_INFO_AVAILABLE = // byte (enum)
+ ACAMERA_FLASH_INFO_START,
+ ACAMERA_FLASH_INFO_RESERVED_1,
+ ACAMERA_FLASH_INFO_END,
+
+ ACAMERA_HOT_PIXEL_MODE = // byte (enum)
+ ACAMERA_HOT_PIXEL_START,
+ ACAMERA_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, // byte[n]
+ ACAMERA_HOT_PIXEL_END,
+
+ ACAMERA_JPEG_GPS_COORDINATES = // double[3]
+ ACAMERA_JPEG_START,
+ ACAMERA_JPEG_GPS_PROCESSING_METHOD, // byte
+ ACAMERA_JPEG_GPS_TIMESTAMP, // int64
+ ACAMERA_JPEG_ORIENTATION, // int32
+ ACAMERA_JPEG_QUALITY, // byte
+ ACAMERA_JPEG_THUMBNAIL_QUALITY, // byte
+ ACAMERA_JPEG_THUMBNAIL_SIZE, // int32[2]
+ ACAMERA_JPEG_AVAILABLE_THUMBNAIL_SIZES, // int32[2*n]
+ ACAMERA_JPEG_RESERVED_8,
+ ACAMERA_JPEG_RESERVED_9,
+ ACAMERA_JPEG_END,
+
+ ACAMERA_LENS_APERTURE = // float
+ ACAMERA_LENS_START,
+ ACAMERA_LENS_FILTER_DENSITY, // float
+ ACAMERA_LENS_FOCAL_LENGTH, // float
+ ACAMERA_LENS_FOCUS_DISTANCE, // float
+ ACAMERA_LENS_OPTICAL_STABILIZATION_MODE, // byte (enum)
+ ACAMERA_LENS_FACING, // byte (enum)
+ ACAMERA_LENS_POSE_ROTATION, // float[4]
+ ACAMERA_LENS_POSE_TRANSLATION, // float[3]
+ ACAMERA_LENS_FOCUS_RANGE, // float[2]
+ ACAMERA_LENS_STATE, // byte (enum)
+ ACAMERA_LENS_INTRINSIC_CALIBRATION, // float[5]
+ ACAMERA_LENS_RADIAL_DISTORTION, // float[6]
+ ACAMERA_LENS_END,
+
+ ACAMERA_LENS_INFO_AVAILABLE_APERTURES = // float[n]
+ ACAMERA_LENS_INFO_START,
+ ACAMERA_LENS_INFO_AVAILABLE_FILTER_DENSITIES, // float[n]
+ ACAMERA_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, // float[n]
+ ACAMERA_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION, // byte[n]
+ ACAMERA_LENS_INFO_HYPERFOCAL_DISTANCE, // float
+ ACAMERA_LENS_INFO_MINIMUM_FOCUS_DISTANCE, // float
+ ACAMERA_LENS_INFO_SHADING_MAP_SIZE, // int32[2]
+ ACAMERA_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, // byte (enum)
+ ACAMERA_LENS_INFO_END,
+
+ ACAMERA_NOISE_REDUCTION_MODE = // byte (enum)
+ ACAMERA_NOISE_REDUCTION_START,
+ ACAMERA_NOISE_REDUCTION_RESERVED_1,
+ ACAMERA_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES, // byte[n]
+ ACAMERA_NOISE_REDUCTION_END,
+
+ ACAMERA_QUIRKS_RESERVED_0 =
+ ACAMERA_QUIRKS_START,
+ ACAMERA_QUIRKS_RESERVED_1,
+ ACAMERA_QUIRKS_RESERVED_2,
+ ACAMERA_QUIRKS_USE_PARTIAL_RESULT, // Deprecated! DO NOT USE
+ ACAMERA_QUIRKS_PARTIAL_RESULT, // Deprecated! DO NOT USE
+ ACAMERA_QUIRKS_END,
+
+ ACAMERA_REQUEST_FRAME_COUNT = // Deprecated! DO NOT USE
+ ACAMERA_REQUEST_START,
+ ACAMERA_REQUEST_ID, // int32
+ ACAMERA_REQUEST_RESERVED_2,
+ ACAMERA_REQUEST_RESERVED_3,
+ ACAMERA_REQUEST_RESERVED_4,
+ ACAMERA_REQUEST_RESERVED_5,
+ ACAMERA_REQUEST_MAX_NUM_OUTPUT_STREAMS, // int32[3]
+ ACAMERA_REQUEST_RESERVED_7,
+ ACAMERA_REQUEST_MAX_NUM_INPUT_STREAMS, // int32
+ ACAMERA_REQUEST_PIPELINE_DEPTH, // byte
+ ACAMERA_REQUEST_PIPELINE_MAX_DEPTH, // byte
+ ACAMERA_REQUEST_PARTIAL_RESULT_COUNT, // int32
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES, // byte[n] (enum)
+ ACAMERA_REQUEST_AVAILABLE_REQUEST_KEYS, // int32[n]
+ ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS, // int32[n]
+ ACAMERA_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, // int32[n]
+ ACAMERA_REQUEST_END,
+
+ ACAMERA_SCALER_CROP_REGION = // int32[4]
+ ACAMERA_SCALER_START,
+ ACAMERA_SCALER_AVAILABLE_FORMATS, // Deprecated! DO NOT USE
+ ACAMERA_SCALER_AVAILABLE_JPEG_MIN_DURATIONS, // Deprecated! DO NOT USE
+ ACAMERA_SCALER_AVAILABLE_JPEG_SIZES, // Deprecated! DO NOT USE
+ ACAMERA_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, // float
+ ACAMERA_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS, // Deprecated! DO NOT USE
+ ACAMERA_SCALER_AVAILABLE_PROCESSED_SIZES, // Deprecated! DO NOT USE
+ ACAMERA_SCALER_RESERVED_7,
+ ACAMERA_SCALER_RESERVED_8,
+ ACAMERA_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP, // int32
+ ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, // int32[n*4] (enum)
+ ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS, // int64[4*n]
+ ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS, // int64[4*n]
+ ACAMERA_SCALER_CROPPING_TYPE, // byte (enum)
+ ACAMERA_SCALER_END,
+
+ ACAMERA_SENSOR_EXPOSURE_TIME = // int64
+ ACAMERA_SENSOR_START,
+ ACAMERA_SENSOR_FRAME_DURATION, // int64
+ ACAMERA_SENSOR_SENSITIVITY, // int32
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1, // byte (enum)
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT2, // byte
+ ACAMERA_SENSOR_CALIBRATION_TRANSFORM1, // rational[3*3]
+ ACAMERA_SENSOR_CALIBRATION_TRANSFORM2, // rational[3*3]
+ ACAMERA_SENSOR_COLOR_TRANSFORM1, // rational[3*3]
+ ACAMERA_SENSOR_COLOR_TRANSFORM2, // rational[3*3]
+ ACAMERA_SENSOR_FORWARD_MATRIX1, // rational[3*3]
+ ACAMERA_SENSOR_FORWARD_MATRIX2, // rational[3*3]
+ ACAMERA_SENSOR_RESERVED_11,
+ ACAMERA_SENSOR_BLACK_LEVEL_PATTERN, // int32[4]
+ ACAMERA_SENSOR_MAX_ANALOG_SENSITIVITY, // int32
+ ACAMERA_SENSOR_ORIENTATION, // int32
+ ACAMERA_SENSOR_RESERVED_15,
+ ACAMERA_SENSOR_TIMESTAMP, // int64
+ ACAMERA_SENSOR_RESERVED_17,
+ ACAMERA_SENSOR_NEUTRAL_COLOR_POINT, // rational[3]
+ ACAMERA_SENSOR_NOISE_PROFILE, // double[2*CFA Channels]
+ ACAMERA_SENSOR_RESERVED_20,
+ ACAMERA_SENSOR_RESERVED_21,
+ ACAMERA_SENSOR_GREEN_SPLIT, // float
+ ACAMERA_SENSOR_TEST_PATTERN_DATA, // int32[4]
+ ACAMERA_SENSOR_TEST_PATTERN_MODE, // int32 (enum)
+ ACAMERA_SENSOR_AVAILABLE_TEST_PATTERN_MODES, // int32[n]
+ ACAMERA_SENSOR_ROLLING_SHUTTER_SKEW, // int64
+ ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS, // int32[4*num_regions]
+ ACAMERA_SENSOR_DYNAMIC_BLACK_LEVEL, // float[4]
+ ACAMERA_SENSOR_DYNAMIC_WHITE_LEVEL, // int32
+ ACAMERA_SENSOR_RESERVED_30,
+ ACAMERA_SENSOR_END,
+
+ ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE = // int32[4]
+ ACAMERA_SENSOR_INFO_START,
+ ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE, // int32[2]
+ ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT, // byte (enum)
+ ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE, // int64[2]
+ ACAMERA_SENSOR_INFO_MAX_FRAME_DURATION, // int64
+ ACAMERA_SENSOR_INFO_PHYSICAL_SIZE, // float[2]
+ ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE, // int32[2]
+ ACAMERA_SENSOR_INFO_WHITE_LEVEL, // int32
+ ACAMERA_SENSOR_INFO_TIMESTAMP_SOURCE, // byte (enum)
+ ACAMERA_SENSOR_INFO_LENS_SHADING_APPLIED, // byte (enum)
+ ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, // int32[4]
+ ACAMERA_SENSOR_INFO_END,
+
+ ACAMERA_SHADING_MODE = // byte (enum)
+ ACAMERA_SHADING_START,
+ ACAMERA_SHADING_RESERVED_1,
+ ACAMERA_SHADING_AVAILABLE_MODES, // byte[n]
+ ACAMERA_SHADING_END,
+
+ ACAMERA_STATISTICS_FACE_DETECT_MODE = // byte (enum)
+ ACAMERA_STATISTICS_START,
+ ACAMERA_STATISTICS_RESERVED_1,
+ ACAMERA_STATISTICS_RESERVED_2,
+ ACAMERA_STATISTICS_HOT_PIXEL_MAP_MODE, // byte (enum)
+ ACAMERA_STATISTICS_FACE_IDS, // int32[n]
+ ACAMERA_STATISTICS_FACE_LANDMARKS, // int32[n*6]
+ ACAMERA_STATISTICS_FACE_RECTANGLES, // int32[n*4]
+ ACAMERA_STATISTICS_FACE_SCORES, // byte[n]
+ ACAMERA_STATISTICS_RESERVED_8,
+ ACAMERA_STATISTICS_RESERVED_9,
+ ACAMERA_STATISTICS_LENS_SHADING_CORRECTION_MAP, // byte
+ ACAMERA_STATISTICS_LENS_SHADING_MAP, // float[4*n*m]
+ ACAMERA_STATISTICS_PREDICTED_COLOR_GAINS, // Deprecated! DO NOT USE
+ ACAMERA_STATISTICS_PREDICTED_COLOR_TRANSFORM, // Deprecated! DO NOT USE
+ ACAMERA_STATISTICS_SCENE_FLICKER, // byte (enum)
+ ACAMERA_STATISTICS_HOT_PIXEL_MAP, // int32[2*n]
+ ACAMERA_STATISTICS_LENS_SHADING_MAP_MODE, // byte (enum)
+ ACAMERA_STATISTICS_END,
+
+ ACAMERA_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES = // byte[n]
+ ACAMERA_STATISTICS_INFO_START,
+ ACAMERA_STATISTICS_INFO_RESERVED_1,
+ ACAMERA_STATISTICS_INFO_MAX_FACE_COUNT, // int32
+ ACAMERA_STATISTICS_INFO_RESERVED_3,
+ ACAMERA_STATISTICS_INFO_RESERVED_4,
+ ACAMERA_STATISTICS_INFO_RESERVED_5,
+ ACAMERA_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES, // byte[n]
+ ACAMERA_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES, // byte[n]
+ ACAMERA_STATISTICS_INFO_END,
+
+ ACAMERA_TONEMAP_CURVE_BLUE = // float[n*2]
+ ACAMERA_TONEMAP_START,
+ ACAMERA_TONEMAP_CURVE_GREEN, // float[n*2]
+ ACAMERA_TONEMAP_CURVE_RED, // float[n*2]
+ ACAMERA_TONEMAP_MODE, // byte (enum)
+ ACAMERA_TONEMAP_MAX_CURVE_POINTS, // int32
+ ACAMERA_TONEMAP_AVAILABLE_TONE_MAP_MODES, // byte[n]
+ ACAMERA_TONEMAP_GAMMA, // float
+ ACAMERA_TONEMAP_PRESET_CURVE, // byte (enum)
+ ACAMERA_TONEMAP_END,
+
+ ACAMERA_LED_TRANSMIT = // byte (enum)
+ ACAMERA_LED_START,
+ ACAMERA_LED_AVAILABLE_LEDS, // byte[n] (enum)
+ ACAMERA_LED_END,
+
+ ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL = // byte (enum)
+ ACAMERA_INFO_START,
+ ACAMERA_INFO_END,
+
+ ACAMERA_BLACK_LEVEL_LOCK = // byte (enum)
+ ACAMERA_BLACK_LEVEL_START,
+ ACAMERA_BLACK_LEVEL_END,
+
+ ACAMERA_SYNC_FRAME_NUMBER = // int64 (enum)
+ ACAMERA_SYNC_START,
+ ACAMERA_SYNC_MAX_LATENCY, // int32 (enum)
+ ACAMERA_SYNC_END,
+
+ ACAMERA_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR = // float
+ ACAMERA_REPROCESS_START,
+ ACAMERA_REPROCESS_MAX_CAPTURE_STALL, // int32
+ ACAMERA_REPROCESS_END,
+
+ ACAMERA_DEPTH_RESERVED_0 =
+ ACAMERA_DEPTH_START,
+ ACAMERA_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, // int32[n*4] (enum)
+ ACAMERA_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS, // int64[4*n]
+ ACAMERA_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS, // int64[4*n]
+ ACAMERA_DEPTH_DEPTH_IS_EXCLUSIVE, // byte (enum)
+ ACAMERA_DEPTH_END,
+
+} acamera_metadata_tag_t;
+
+/**
+ * Enumeration definitions for the various entries that need them
+ */
+
+// ACAMERA_COLOR_CORRECTION_MODE
+typedef enum acamera_metadata_enum_acamera_color_correction_mode {
+ ACAMERA_COLOR_CORRECTION_MODE_TRANSFORM_MATRIX,
+ ACAMERA_COLOR_CORRECTION_MODE_FAST,
+ ACAMERA_COLOR_CORRECTION_MODE_HIGH_QUALITY,
+} acamera_metadata_enum_android_color_correction_mode_t;
+
+// ACAMERA_COLOR_CORRECTION_ABERRATION_MODE
+typedef enum acamera_metadata_enum_acamera_color_correction_aberration_mode {
+ ACAMERA_COLOR_CORRECTION_ABERRATION_MODE_OFF,
+ ACAMERA_COLOR_CORRECTION_ABERRATION_MODE_FAST,
+ ACAMERA_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY,
+} acamera_metadata_enum_android_color_correction_aberration_mode_t;
+
+
+// ACAMERA_CONTROL_AE_ANTIBANDING_MODE
+typedef enum acamera_metadata_enum_acamera_control_ae_antibanding_mode {
+ ACAMERA_CONTROL_AE_ANTIBANDING_MODE_OFF,
+ ACAMERA_CONTROL_AE_ANTIBANDING_MODE_50HZ,
+ ACAMERA_CONTROL_AE_ANTIBANDING_MODE_60HZ,
+ ACAMERA_CONTROL_AE_ANTIBANDING_MODE_AUTO,
+} acamera_metadata_enum_android_control_ae_antibanding_mode_t;
+
+// ACAMERA_CONTROL_AE_LOCK
+typedef enum acamera_metadata_enum_acamera_control_ae_lock {
+ ACAMERA_CONTROL_AE_LOCK_OFF,
+ ACAMERA_CONTROL_AE_LOCK_ON,
+} acamera_metadata_enum_android_control_ae_lock_t;
+
+// ACAMERA_CONTROL_AE_MODE
+typedef enum acamera_metadata_enum_acamera_control_ae_mode {
+ ACAMERA_CONTROL_AE_MODE_OFF,
+ ACAMERA_CONTROL_AE_MODE_ON,
+ ACAMERA_CONTROL_AE_MODE_ON_AUTO_FLASH,
+ ACAMERA_CONTROL_AE_MODE_ON_ALWAYS_FLASH,
+ ACAMERA_CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE,
+} acamera_metadata_enum_android_control_ae_mode_t;
+
+// ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER
+typedef enum acamera_metadata_enum_acamera_control_ae_precapture_trigger {
+ ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE,
+ ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER_START,
+ ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL,
+} acamera_metadata_enum_android_control_ae_precapture_trigger_t;
+
+// ACAMERA_CONTROL_AF_MODE
+typedef enum acamera_metadata_enum_acamera_control_af_mode {
+ ACAMERA_CONTROL_AF_MODE_OFF,
+ ACAMERA_CONTROL_AF_MODE_AUTO,
+ ACAMERA_CONTROL_AF_MODE_MACRO,
+ ACAMERA_CONTROL_AF_MODE_CONTINUOUS_VIDEO,
+ ACAMERA_CONTROL_AF_MODE_CONTINUOUS_PICTURE,
+ ACAMERA_CONTROL_AF_MODE_EDOF,
+} acamera_metadata_enum_android_control_af_mode_t;
+
+// ACAMERA_CONTROL_AF_TRIGGER
+typedef enum acamera_metadata_enum_acamera_control_af_trigger {
+ ACAMERA_CONTROL_AF_TRIGGER_IDLE,
+ ACAMERA_CONTROL_AF_TRIGGER_START,
+ ACAMERA_CONTROL_AF_TRIGGER_CANCEL,
+} acamera_metadata_enum_android_control_af_trigger_t;
+
+// ACAMERA_CONTROL_AWB_LOCK
+typedef enum acamera_metadata_enum_acamera_control_awb_lock {
+ ACAMERA_CONTROL_AWB_LOCK_OFF,
+ ACAMERA_CONTROL_AWB_LOCK_ON,
+} acamera_metadata_enum_android_control_awb_lock_t;
+
+// ACAMERA_CONTROL_AWB_MODE
+typedef enum acamera_metadata_enum_acamera_control_awb_mode {
+ ACAMERA_CONTROL_AWB_MODE_OFF,
+ ACAMERA_CONTROL_AWB_MODE_AUTO,
+ ACAMERA_CONTROL_AWB_MODE_INCANDESCENT,
+ ACAMERA_CONTROL_AWB_MODE_FLUORESCENT,
+ ACAMERA_CONTROL_AWB_MODE_WARM_FLUORESCENT,
+ ACAMERA_CONTROL_AWB_MODE_DAYLIGHT,
+ ACAMERA_CONTROL_AWB_MODE_CLOUDY_DAYLIGHT,
+ ACAMERA_CONTROL_AWB_MODE_TWILIGHT,
+ ACAMERA_CONTROL_AWB_MODE_SHADE,
+} acamera_metadata_enum_android_control_awb_mode_t;
+
+// ACAMERA_CONTROL_CAPTURE_INTENT
+typedef enum acamera_metadata_enum_acamera_control_capture_intent {
+ ACAMERA_CONTROL_CAPTURE_INTENT_CUSTOM,
+ ACAMERA_CONTROL_CAPTURE_INTENT_PREVIEW,
+ ACAMERA_CONTROL_CAPTURE_INTENT_STILL_CAPTURE,
+ ACAMERA_CONTROL_CAPTURE_INTENT_VIDEO_RECORD,
+ ACAMERA_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT,
+ ACAMERA_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG,
+ ACAMERA_CONTROL_CAPTURE_INTENT_MANUAL,
+} acamera_metadata_enum_android_control_capture_intent_t;
+
+// ACAMERA_CONTROL_EFFECT_MODE
+typedef enum acamera_metadata_enum_acamera_control_effect_mode {
+ ACAMERA_CONTROL_EFFECT_MODE_OFF,
+ ACAMERA_CONTROL_EFFECT_MODE_MONO,
+ ACAMERA_CONTROL_EFFECT_MODE_NEGATIVE,
+ ACAMERA_CONTROL_EFFECT_MODE_SOLARIZE,
+ ACAMERA_CONTROL_EFFECT_MODE_SEPIA,
+ ACAMERA_CONTROL_EFFECT_MODE_POSTERIZE,
+ ACAMERA_CONTROL_EFFECT_MODE_WHITEBOARD,
+ ACAMERA_CONTROL_EFFECT_MODE_BLACKBOARD,
+ ACAMERA_CONTROL_EFFECT_MODE_AQUA,
+} acamera_metadata_enum_android_control_effect_mode_t;
+
+// ACAMERA_CONTROL_MODE
+typedef enum acamera_metadata_enum_acamera_control_mode {
+ ACAMERA_CONTROL_MODE_OFF,
+ ACAMERA_CONTROL_MODE_AUTO,
+ ACAMERA_CONTROL_MODE_USE_SCENE_MODE,
+ ACAMERA_CONTROL_MODE_OFF_KEEP_STATE,
+} acamera_metadata_enum_android_control_mode_t;
+
+// ACAMERA_CONTROL_SCENE_MODE
+typedef enum acamera_metadata_enum_acamera_control_scene_mode {
+ ACAMERA_CONTROL_SCENE_MODE_DISABLED = 0,
+ ACAMERA_CONTROL_SCENE_MODE_FACE_PRIORITY,
+ ACAMERA_CONTROL_SCENE_MODE_ACTION,
+ ACAMERA_CONTROL_SCENE_MODE_PORTRAIT,
+ ACAMERA_CONTROL_SCENE_MODE_LANDSCAPE,
+ ACAMERA_CONTROL_SCENE_MODE_NIGHT,
+ ACAMERA_CONTROL_SCENE_MODE_NIGHT_PORTRAIT,
+ ACAMERA_CONTROL_SCENE_MODE_THEATRE,
+ ACAMERA_CONTROL_SCENE_MODE_BEACH,
+ ACAMERA_CONTROL_SCENE_MODE_SNOW,
+ ACAMERA_CONTROL_SCENE_MODE_SUNSET,
+ ACAMERA_CONTROL_SCENE_MODE_STEADYPHOTO,
+ ACAMERA_CONTROL_SCENE_MODE_FIREWORKS,
+ ACAMERA_CONTROL_SCENE_MODE_SPORTS,
+ ACAMERA_CONTROL_SCENE_MODE_PARTY,
+ ACAMERA_CONTROL_SCENE_MODE_CANDLELIGHT,
+ ACAMERA_CONTROL_SCENE_MODE_BARCODE,
+ ACAMERA_CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO,
+ ACAMERA_CONTROL_SCENE_MODE_HDR,
+ ACAMERA_CONTROL_SCENE_MODE_FACE_PRIORITY_LOW_LIGHT,
+} acamera_metadata_enum_android_control_scene_mode_t;
+
+// ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE
+typedef enum acamera_metadata_enum_acamera_control_video_stabilization_mode {
+ ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE_OFF,
+ ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE_ON,
+} acamera_metadata_enum_android_control_video_stabilization_mode_t;
+
+// ACAMERA_CONTROL_AE_STATE
+typedef enum acamera_metadata_enum_acamera_control_ae_state {
+ ACAMERA_CONTROL_AE_STATE_INACTIVE,
+ ACAMERA_CONTROL_AE_STATE_SEARCHING,
+ ACAMERA_CONTROL_AE_STATE_CONVERGED,
+ ACAMERA_CONTROL_AE_STATE_LOCKED,
+ ACAMERA_CONTROL_AE_STATE_FLASH_REQUIRED,
+ ACAMERA_CONTROL_AE_STATE_PRECAPTURE,
+} acamera_metadata_enum_android_control_ae_state_t;
+
+// ACAMERA_CONTROL_AF_STATE
+typedef enum acamera_metadata_enum_acamera_control_af_state {
+ ACAMERA_CONTROL_AF_STATE_INACTIVE,
+ ACAMERA_CONTROL_AF_STATE_PASSIVE_SCAN,
+ ACAMERA_CONTROL_AF_STATE_PASSIVE_FOCUSED,
+ ACAMERA_CONTROL_AF_STATE_ACTIVE_SCAN,
+ ACAMERA_CONTROL_AF_STATE_FOCUSED_LOCKED,
+ ACAMERA_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED,
+ ACAMERA_CONTROL_AF_STATE_PASSIVE_UNFOCUSED,
+} acamera_metadata_enum_android_control_af_state_t;
+
+// ACAMERA_CONTROL_AWB_STATE
+typedef enum acamera_metadata_enum_acamera_control_awb_state {
+ ACAMERA_CONTROL_AWB_STATE_INACTIVE,
+ ACAMERA_CONTROL_AWB_STATE_SEARCHING,
+ ACAMERA_CONTROL_AWB_STATE_CONVERGED,
+ ACAMERA_CONTROL_AWB_STATE_LOCKED,
+} acamera_metadata_enum_android_control_awb_state_t;
+
+// ACAMERA_CONTROL_AE_LOCK_AVAILABLE
+typedef enum acamera_metadata_enum_acamera_control_ae_lock_available {
+ ACAMERA_CONTROL_AE_LOCK_AVAILABLE_FALSE,
+ ACAMERA_CONTROL_AE_LOCK_AVAILABLE_TRUE,
+} acamera_metadata_enum_android_control_ae_lock_available_t;
+
+// ACAMERA_CONTROL_AWB_LOCK_AVAILABLE
+typedef enum acamera_metadata_enum_acamera_control_awb_lock_available {
+ ACAMERA_CONTROL_AWB_LOCK_AVAILABLE_FALSE,
+ ACAMERA_CONTROL_AWB_LOCK_AVAILABLE_TRUE,
+} acamera_metadata_enum_android_control_awb_lock_available_t;
+
+
+
+// ACAMERA_EDGE_MODE
+typedef enum acamera_metadata_enum_acamera_edge_mode {
+ ACAMERA_EDGE_MODE_OFF,
+ ACAMERA_EDGE_MODE_FAST,
+ ACAMERA_EDGE_MODE_HIGH_QUALITY,
+ ACAMERA_EDGE_MODE_ZERO_SHUTTER_LAG,
+} acamera_metadata_enum_android_edge_mode_t;
+
+
+// ACAMERA_FLASH_MODE
+typedef enum acamera_metadata_enum_acamera_flash_mode {
+ ACAMERA_FLASH_MODE_OFF,
+ ACAMERA_FLASH_MODE_SINGLE,
+ ACAMERA_FLASH_MODE_TORCH,
+} acamera_metadata_enum_android_flash_mode_t;
+
+// ACAMERA_FLASH_STATE
+typedef enum acamera_metadata_enum_acamera_flash_state {
+ ACAMERA_FLASH_STATE_UNAVAILABLE,
+ ACAMERA_FLASH_STATE_CHARGING,
+ ACAMERA_FLASH_STATE_READY,
+ ACAMERA_FLASH_STATE_FIRED,
+ ACAMERA_FLASH_STATE_PARTIAL,
+} acamera_metadata_enum_android_flash_state_t;
+
+
+// ACAMERA_FLASH_INFO_AVAILABLE
+typedef enum acamera_metadata_enum_acamera_flash_info_available {
+ ACAMERA_FLASH_INFO_AVAILABLE_FALSE,
+ ACAMERA_FLASH_INFO_AVAILABLE_TRUE,
+} acamera_metadata_enum_android_flash_info_available_t;
+
+
+// ACAMERA_HOT_PIXEL_MODE
+typedef enum acamera_metadata_enum_acamera_hot_pixel_mode {
+ ACAMERA_HOT_PIXEL_MODE_OFF,
+ ACAMERA_HOT_PIXEL_MODE_FAST,
+ ACAMERA_HOT_PIXEL_MODE_HIGH_QUALITY,
+} acamera_metadata_enum_android_hot_pixel_mode_t;
+
+
+
+// ACAMERA_LENS_OPTICAL_STABILIZATION_MODE
+typedef enum acamera_metadata_enum_acamera_lens_optical_stabilization_mode {
+ ACAMERA_LENS_OPTICAL_STABILIZATION_MODE_OFF,
+ ACAMERA_LENS_OPTICAL_STABILIZATION_MODE_ON,
+} acamera_metadata_enum_android_lens_optical_stabilization_mode_t;
+
+// ACAMERA_LENS_FACING
+typedef enum acamera_metadata_enum_acamera_lens_facing {
+ ACAMERA_LENS_FACING_FRONT,
+ ACAMERA_LENS_FACING_BACK,
+ ACAMERA_LENS_FACING_EXTERNAL,
+} acamera_metadata_enum_android_lens_facing_t;
+
+// ACAMERA_LENS_STATE
+typedef enum acamera_metadata_enum_acamera_lens_state {
+ ACAMERA_LENS_STATE_STATIONARY,
+ ACAMERA_LENS_STATE_MOVING,
+} acamera_metadata_enum_android_lens_state_t;
+
+
+// ACAMERA_LENS_INFO_FOCUS_DISTANCE_CALIBRATION
+typedef enum acamera_metadata_enum_acamera_lens_info_focus_distance_calibration {
+ ACAMERA_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED,
+ ACAMERA_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE,
+ ACAMERA_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED,
+} acamera_metadata_enum_android_lens_info_focus_distance_calibration_t;
+
+
+// ACAMERA_NOISE_REDUCTION_MODE
+typedef enum acamera_metadata_enum_acamera_noise_reduction_mode {
+ ACAMERA_NOISE_REDUCTION_MODE_OFF,
+ ACAMERA_NOISE_REDUCTION_MODE_FAST,
+ ACAMERA_NOISE_REDUCTION_MODE_HIGH_QUALITY,
+ ACAMERA_NOISE_REDUCTION_MODE_MINIMAL,
+ ACAMERA_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG,
+} acamera_metadata_enum_android_noise_reduction_mode_t;
+
+
+// ACAMERA_QUIRKS_PARTIAL_RESULT
+typedef enum acamera_metadata_enum_acamera_quirks_partial_result {
+ ACAMERA_QUIRKS_PARTIAL_RESULT_FINAL,
+ ACAMERA_QUIRKS_PARTIAL_RESULT_PARTIAL,
+} acamera_metadata_enum_android_quirks_partial_result_t;
+
+
+// ACAMERA_REQUEST_AVAILABLE_CAPABILITIES
+typedef enum acamera_metadata_enum_acamera_request_available_capabilities {
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR,
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING,
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_RAW,
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING,
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS,
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE,
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT,
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO,
+} acamera_metadata_enum_android_request_available_capabilities_t;
+
+
+// ACAMERA_SCALER_AVAILABLE_FORMATS
+typedef enum acamera_metadata_enum_acamera_scaler_available_formats {
+ ACAMERA_SCALER_AVAILABLE_FORMATS_RAW16 = 0x20,
+ ACAMERA_SCALER_AVAILABLE_FORMATS_RAW_OPAQUE = 0x24,
+ ACAMERA_SCALER_AVAILABLE_FORMATS_YV12 = 0x32315659,
+ ACAMERA_SCALER_AVAILABLE_FORMATS_YCrCb_420_SP = 0x11,
+ ACAMERA_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED = 0x22,
+ ACAMERA_SCALER_AVAILABLE_FORMATS_YCbCr_420_888 = 0x23,
+ ACAMERA_SCALER_AVAILABLE_FORMATS_BLOB = 0x21,
+} acamera_metadata_enum_android_scaler_available_formats_t;
+
+// ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+typedef enum acamera_metadata_enum_acamera_scaler_available_stream_configurations {
+ ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT,
+} acamera_metadata_enum_android_scaler_available_stream_configurations_t;
+
+// ACAMERA_SCALER_CROPPING_TYPE
+typedef enum acamera_metadata_enum_acamera_scaler_cropping_type {
+ ACAMERA_SCALER_CROPPING_TYPE_CENTER_ONLY,
+ ACAMERA_SCALER_CROPPING_TYPE_FREEFORM,
+} acamera_metadata_enum_android_scaler_cropping_type_t;
+
+
+// ACAMERA_SENSOR_REFERENCE_ILLUMINANT1
+typedef enum acamera_metadata_enum_acamera_sensor_reference_illuminant1 {
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT = 1,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_FLUORESCENT = 2,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_TUNGSTEN = 3,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_FLASH = 4,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_FINE_WEATHER = 9,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_CLOUDY_WEATHER = 10,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_SHADE = 11,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT_FLUORESCENT = 12,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_DAY_WHITE_FLUORESCENT = 13,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_COOL_WHITE_FLUORESCENT = 14,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_WHITE_FLUORESCENT = 15,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_STANDARD_A = 17,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_STANDARD_B = 18,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_STANDARD_C = 19,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_D55 = 20,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_D65 = 21,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_D75 = 22,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_D50 = 23,
+ ACAMERA_SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN = 24,
+} acamera_metadata_enum_android_sensor_reference_illuminant1_t;
+
+// ACAMERA_SENSOR_TEST_PATTERN_MODE
+typedef enum acamera_metadata_enum_acamera_sensor_test_pattern_mode {
+ ACAMERA_SENSOR_TEST_PATTERN_MODE_OFF,
+ ACAMERA_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR,
+ ACAMERA_SENSOR_TEST_PATTERN_MODE_COLOR_BARS,
+ ACAMERA_SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY,
+ ACAMERA_SENSOR_TEST_PATTERN_MODE_PN9,
+ ACAMERA_SENSOR_TEST_PATTERN_MODE_CUSTOM1 = 256,
+} acamera_metadata_enum_android_sensor_test_pattern_mode_t;
+
+
+// ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+typedef enum acamera_metadata_enum_acamera_sensor_info_color_filter_arrangement {
+ ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB,
+ ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG,
+ ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG,
+ ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR,
+ ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB,
+} acamera_metadata_enum_android_sensor_info_color_filter_arrangement_t;
+
+// ACAMERA_SENSOR_INFO_TIMESTAMP_SOURCE
+typedef enum acamera_metadata_enum_acamera_sensor_info_timestamp_source {
+ ACAMERA_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN,
+ ACAMERA_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME,
+} acamera_metadata_enum_android_sensor_info_timestamp_source_t;
+
+// ACAMERA_SENSOR_INFO_LENS_SHADING_APPLIED
+typedef enum acamera_metadata_enum_acamera_sensor_info_lens_shading_applied {
+ ACAMERA_SENSOR_INFO_LENS_SHADING_APPLIED_FALSE,
+ ACAMERA_SENSOR_INFO_LENS_SHADING_APPLIED_TRUE,
+} acamera_metadata_enum_android_sensor_info_lens_shading_applied_t;
+
+
+// ACAMERA_SHADING_MODE
+typedef enum acamera_metadata_enum_acamera_shading_mode {
+ ACAMERA_SHADING_MODE_OFF,
+ ACAMERA_SHADING_MODE_FAST,
+ ACAMERA_SHADING_MODE_HIGH_QUALITY,
+} acamera_metadata_enum_android_shading_mode_t;
+
+
+// ACAMERA_STATISTICS_FACE_DETECT_MODE
+typedef enum acamera_metadata_enum_acamera_statistics_face_detect_mode {
+ ACAMERA_STATISTICS_FACE_DETECT_MODE_OFF,
+ ACAMERA_STATISTICS_FACE_DETECT_MODE_SIMPLE,
+ ACAMERA_STATISTICS_FACE_DETECT_MODE_FULL,
+} acamera_metadata_enum_android_statistics_face_detect_mode_t;
+
+// ACAMERA_STATISTICS_HOT_PIXEL_MAP_MODE
+typedef enum acamera_metadata_enum_acamera_statistics_hot_pixel_map_mode {
+ ACAMERA_STATISTICS_HOT_PIXEL_MAP_MODE_OFF,
+ ACAMERA_STATISTICS_HOT_PIXEL_MAP_MODE_ON,
+} acamera_metadata_enum_android_statistics_hot_pixel_map_mode_t;
+
+// ACAMERA_STATISTICS_SCENE_FLICKER
+typedef enum acamera_metadata_enum_acamera_statistics_scene_flicker {
+ ACAMERA_STATISTICS_SCENE_FLICKER_NONE,
+ ACAMERA_STATISTICS_SCENE_FLICKER_50HZ,
+ ACAMERA_STATISTICS_SCENE_FLICKER_60HZ,
+} acamera_metadata_enum_android_statistics_scene_flicker_t;
+
+// ACAMERA_STATISTICS_LENS_SHADING_MAP_MODE
+typedef enum acamera_metadata_enum_acamera_statistics_lens_shading_map_mode {
+ ACAMERA_STATISTICS_LENS_SHADING_MAP_MODE_OFF,
+ ACAMERA_STATISTICS_LENS_SHADING_MAP_MODE_ON,
+} acamera_metadata_enum_android_statistics_lens_shading_map_mode_t;
+
+
+
+// ACAMERA_TONEMAP_MODE
+typedef enum acamera_metadata_enum_acamera_tonemap_mode {
+ ACAMERA_TONEMAP_MODE_CONTRAST_CURVE,
+ ACAMERA_TONEMAP_MODE_FAST,
+ ACAMERA_TONEMAP_MODE_HIGH_QUALITY,
+ ACAMERA_TONEMAP_MODE_GAMMA_VALUE,
+ ACAMERA_TONEMAP_MODE_PRESET_CURVE,
+} acamera_metadata_enum_android_tonemap_mode_t;
+
+// ACAMERA_TONEMAP_PRESET_CURVE
+typedef enum acamera_metadata_enum_acamera_tonemap_preset_curve {
+ ACAMERA_TONEMAP_PRESET_CURVE_SRGB,
+ ACAMERA_TONEMAP_PRESET_CURVE_REC709,
+} acamera_metadata_enum_android_tonemap_preset_curve_t;
+
+
+// ACAMERA_LED_TRANSMIT
+typedef enum acamera_metadata_enum_acamera_led_transmit {
+ ACAMERA_LED_TRANSMIT_OFF,
+ ACAMERA_LED_TRANSMIT_ON,
+} acamera_metadata_enum_android_led_transmit_t;
+
+// ACAMERA_LED_AVAILABLE_LEDS
+typedef enum acamera_metadata_enum_acamera_led_available_leds {
+ ACAMERA_LED_AVAILABLE_LEDS_TRANSMIT,
+} acamera_metadata_enum_android_led_available_leds_t;
+
+
+// ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL
+typedef enum acamera_metadata_enum_acamera_info_supported_hardware_level {
+ ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
+ ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
+ ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,
+} acamera_metadata_enum_android_info_supported_hardware_level_t;
+
+
+// ACAMERA_BLACK_LEVEL_LOCK
+typedef enum acamera_metadata_enum_acamera_black_level_lock {
+ ACAMERA_BLACK_LEVEL_LOCK_OFF,
+ ACAMERA_BLACK_LEVEL_LOCK_ON,
+} acamera_metadata_enum_android_black_level_lock_t;
+
+
+// ACAMERA_SYNC_FRAME_NUMBER
+typedef enum acamera_metadata_enum_acamera_sync_frame_number {
+ ACAMERA_SYNC_FRAME_NUMBER_CONVERGING = -1,
+ ACAMERA_SYNC_FRAME_NUMBER_UNKNOWN = -2,
+} acamera_metadata_enum_android_sync_frame_number_t;
+
+// ACAMERA_SYNC_MAX_LATENCY
+typedef enum acamera_metadata_enum_acamera_sync_max_latency {
+ ACAMERA_SYNC_MAX_LATENCY_PER_FRAME_CONTROL = 0,
+ ACAMERA_SYNC_MAX_LATENCY_UNKNOWN = -1,
+} acamera_metadata_enum_android_sync_max_latency_t;
+
+
+
+// ACAMERA_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS
+typedef enum acamera_metadata_enum_acamera_depth_available_depth_stream_configurations {
+ ACAMERA_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_OUTPUT,
+ ACAMERA_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_INPUT,
+} acamera_metadata_enum_android_depth_available_depth_stream_configurations_t;
+
+// ACAMERA_DEPTH_DEPTH_IS_EXCLUSIVE
+typedef enum acamera_metadata_enum_acamera_depth_depth_is_exclusive {
+ ACAMERA_DEPTH_DEPTH_IS_EXCLUSIVE_FALSE,
+ ACAMERA_DEPTH_DEPTH_IS_EXCLUSIVE_TRUE,
+} acamera_metadata_enum_android_depth_depth_is_exclusive_t;
+
+
+
+#endif //_NDK_CAMERA_METADATA_TAGS_H
diff --git a/include/camera/ndk/NdkCaptureRequest.h b/include/camera/ndk/NdkCaptureRequest.h
new file mode 100644
index 0000000..566d78f
--- /dev/null
+++ b/include/camera/ndk/NdkCaptureRequest.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+#include <android/native_window.h>
+#include "NdkCameraError.h"
+#include "NdkCameraMetadata.h"
+
+#ifndef _NDK_CAPTURE_REQUEST_H
+#define _NDK_CAPTURE_REQUEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Container for output targets
+typedef struct ACameraOutputTargets ACameraOutputTargets;
+
+// Container for a single output target
+typedef struct ACameraOutputTarget ACameraOutputTarget;
+
+typedef struct ACaptureRequest ACaptureRequest;
+
+camera_status_t ACameraOutputTarget_create(ANativeWindow* window, ACameraOutputTarget** out);
+void ACameraOutputTarget_free(ACameraOutputTarget*);
+
+camera_status_t ACaptureRequest_addTarget(ACaptureRequest*, const ACameraOutputTarget*);
+camera_status_t ACaptureRequest_removeTarget(ACaptureRequest*, const ACameraOutputTarget*);
+//TODO: do we need API to query added targets?
+
+/*
+ * Get a metadata entry
+ */
+camera_status_t ACaptureRequest_getConstEntry(
+ const ACaptureRequest*, uint32_t tag, ACameraMetadata_const_entry* entry);
+/*
+ * Set an entry of corresponding type.
+ * The entry tag's type must match corresponding set API or an
+ * ACAMERA_ERROR_INVALID_PARAMETER error will occur.
+ * Also, the input ACameraMetadata* must belong to a capture request or an
+ * ACAMERA_ERROR_INVALID_PARAMETER error will occur.
+ */
+camera_status_t ACaptureRequest_setEntry_u8(
+ ACaptureRequest*, uint32_t tag, uint32_t count, const uint8_t* data);
+camera_status_t ACaptureRequest_setEntry_i32(
+ ACaptureRequest*, uint32_t tag, uint32_t count, const int32_t* data);
+camera_status_t ACaptureRequest_setEntry_float(
+ ACaptureRequest*, uint32_t tag, uint32_t count, const float* data);
+camera_status_t ACaptureRequest_setEntry_i64(
+ ACaptureRequest*, uint32_t tag, uint32_t count, const int64_t* data);
+camera_status_t ACaptureRequest_setEntry_double(
+ ACaptureRequest*, uint32_t tag, uint32_t count, const double* data);
+camera_status_t ACaptureRequest_setEntry_rational(
+ ACaptureRequest*, uint32_t tag, uint32_t count, const ACameraMetadata_rational* data);
+
+// free the capture request created by ACameraDevice_createCaptureRequest
+void ACaptureRequest_free(ACaptureRequest* request);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _NDK_CAPTURE_REQUEST_H
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index c375dff..64e3660 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -95,6 +95,7 @@
VIDEO_ENCODER_H264 = 2,
VIDEO_ENCODER_MPEG_4_SP = 3,
VIDEO_ENCODER_VP8 = 4,
+ VIDEO_ENCODER_HEVC = 5,
VIDEO_ENCODER_LIST_END // must be the last - used to validate the video encoder type
};
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 6c14a94..91341b8 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -185,6 +185,9 @@
// MPEG user data offsets
kKeyMpegUserData = 'mpud', // size_t[]
+
+ // Size of NALU length in mkv/mp4
+ kKeyNalLengthSize = 'nals', // int32_t
};
enum {
diff --git a/include/media/stagefright/NuMediaExtractor.h b/include/media/stagefright/NuMediaExtractor.h
index 1ba9545..b8bb824 100644
--- a/include/media/stagefright/NuMediaExtractor.h
+++ b/include/media/stagefright/NuMediaExtractor.h
@@ -114,6 +114,7 @@
bool getTotalBitrate(int64_t *bitRate) const;
void updateDurationAndBitrate();
+ status_t appendVorbisNumPageSamples(TrackInfo *info, const sp<ABuffer> &buffer);
DISALLOW_EVIL_CONSTRUCTORS(NuMediaExtractor);
};
diff --git a/include/ndk/NdkMediaCodec.h b/include/ndk/NdkMediaCodec.h
index 034cb35..c6035bd 100644
--- a/include/ndk/NdkMediaCodec.h
+++ b/include/ndk/NdkMediaCodec.h
@@ -154,6 +154,18 @@
media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec*, size_t idx, bool render);
/**
+ * Dynamically sets the output surface of a codec.
+ *
+ * This can only be used if the codec was configured with an output surface. The
+ * new output surface should have a compatible usage type to the original output surface.
+ * E.g. codecs may not support switching from a SurfaceTexture (GPU readable) output
+ * to ImageReader (software readable) output.
+ *
+ * For more details, see the Java documentation for MediaCodec.setOutputSurface.
+ */
+media_status_t AMediaCodec_setOutputSurface(AMediaCodec*, ANativeWindow* surface);
+
+/**
* If you are done with a buffer, use this call to update its surface timestamp
* and return it to the codec to render it on the output surface. If you
* have not specified an output surface when configuring this video codec,
@@ -164,7 +176,6 @@
media_status_t AMediaCodec_releaseOutputBufferAtTime(
AMediaCodec *mData, size_t idx, int64_t timestampNs);
-
typedef enum {
AMEDIACODECRYPTOINFO_MODE_CLEAR = 0,
AMEDIACODECRYPTOINFO_MODE_AES_CTR = 1
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 42f1f40..f48bac1 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -89,6 +89,7 @@
preproc_session_t *session; // session the effect is on
const preproc_ops_t *ops; // effect ops table
preproc_fx_handle_t engine; // handle on webRTC engine
+ uint32_t type; // subtype of effect
#ifdef DUAL_MIC_TEST
bool aux_channels_on; // support auxiliary channels
size_t cur_channel_config; // current auciliary channel configuration
@@ -559,6 +560,21 @@
ALOGV("NsInit");
webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
ns->set_level(kNsDefaultLevel);
+ webrtc::Config config;
+ std::vector<webrtc::Point> geometry;
+ // TODO(aluebs): Make the geometry settable.
+ geometry.push_back(webrtc::Point(-0.03f, 0.f, 0.f));
+ geometry.push_back(webrtc::Point(-0.01f, 0.f, 0.f));
+ geometry.push_back(webrtc::Point(0.01f, 0.f, 0.f));
+ geometry.push_back(webrtc::Point(0.03f, 0.f, 0.f));
+ // The geometry needs to be set with Beamforming enabled.
+ config.Set<webrtc::Beamforming>(
+ new webrtc::Beamforming(true, geometry));
+ effect->session->apm->SetExtraOptions(config);
+ config.Set<webrtc::Beamforming>(
+ new webrtc::Beamforming(false, geometry));
+ effect->session->apm->SetExtraOptions(config);
+ effect->type = NS_TYPE_SINGLE_CHANNEL;
return 0;
}
@@ -584,11 +600,35 @@
return status;
}
-int NsSetParameter (preproc_effect_t *effect __unused,
- void *pParam __unused,
- void *pValue __unused)
+int NsSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
{
int status = 0;
+ webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
+ uint32_t param = *(uint32_t *)pParam;
+ uint32_t value = *(uint32_t *)pValue;
+ switch(param) {
+ case NS_PARAM_LEVEL:
+ ns->set_level((webrtc::NoiseSuppression::Level)value);
+ ALOGV("NsSetParameter() level %d", value);
+ break;
+ case NS_PARAM_TYPE:
+ {
+ webrtc::Config config;
+ std::vector<webrtc::Point> geometry;
+ bool is_beamforming_enabled =
+ value == NS_TYPE_MULTI_CHANNEL && ns->is_enabled();
+ config.Set<webrtc::Beamforming>(
+ new webrtc::Beamforming(is_beamforming_enabled, geometry));
+ effect->session->apm->SetExtraOptions(config);
+ effect->type = value;
+ ALOGV("NsSetParameter() type %d", value);
+ break;
+ }
+ default:
+ ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
+ status = -EINVAL;
+ }
+
return status;
}
@@ -597,6 +637,12 @@
webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
ALOGV("NsEnable ns %p", ns);
ns->Enable(true);
+ if (effect->type == NS_TYPE_MULTI_CHANNEL) {
+ webrtc::Config config;
+ std::vector<webrtc::Point> geometry;
+ config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
+ effect->session->apm->SetExtraOptions(config);
+ }
}
void NsDisable(preproc_effect_t *effect)
@@ -604,6 +650,10 @@
ALOGV("NsDisable");
webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
ns->Enable(false);
+ webrtc::Config config;
+ std::vector<webrtc::Point> geometry;
+ config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry));
+ effect->session->apm->SetExtraOptions(config);
}
static const preproc_ops_t sNsOps = {
@@ -897,17 +947,6 @@
config->inputCfg.samplingRate, config->inputCfg.channels);
int status;
- // if at least one process is enabled, do not accept configuration changes
- if (session->enabledMsk) {
- if (session->samplingRate != config->inputCfg.samplingRate ||
- session->inChannelCount != inCnl ||
- session->outChannelCount != outCnl) {
- return -ENOSYS;
- } else {
- return 0;
- }
- }
-
// AEC implementation is limited to 16kHz
if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
session->apmSamplingRate = 32000;
@@ -1294,8 +1333,7 @@
}
session->framesIn = 0;
}
- session->procFrame->samples_per_channel_ =
- session->apmFrameCount * session->inChannelCount;
+ session->procFrame->samples_per_channel_ = session->apmFrameCount;
effect->session->apm->ProcessStream(session->procFrame);
@@ -1822,8 +1860,7 @@
}
session->framesRev = 0;
}
- session->revFrame->samples_per_channel_ =
- session->apmFrameCount * session->inChannelCount;
+ session->revFrame->samples_per_channel_ = session->apmFrameCount;
effect->session->apm->AnalyzeReverseStream(session->revFrame);
return 0;
} else {
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 2a17696..ff0e52e 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -37,7 +37,8 @@
const MediaProfiles::NameToTagMap MediaProfiles::sVideoEncoderNameMap[] = {
{"h263", VIDEO_ENCODER_H263},
{"h264", VIDEO_ENCODER_H264},
- {"m4v", VIDEO_ENCODER_MPEG_4_SP}
+ {"m4v", VIDEO_ENCODER_MPEG_4_SP},
+ {"hevc", VIDEO_ENCODER_HEVC}
};
const MediaProfiles::NameToTagMap MediaProfiles::sAudioEncoderNameMap[] = {
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 73d07a0..405df06 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1226,6 +1226,7 @@
(mVideoEncoder == VIDEO_ENCODER_H263 ? MEDIA_MIMETYPE_VIDEO_H263 :
mVideoEncoder == VIDEO_ENCODER_MPEG_4_SP ? MEDIA_MIMETYPE_VIDEO_MPEG4 :
mVideoEncoder == VIDEO_ENCODER_VP8 ? MEDIA_MIMETYPE_VIDEO_VP8 :
+ mVideoEncoder == VIDEO_ENCODER_HEVC ? MEDIA_MIMETYPE_VIDEO_HEVC :
mVideoEncoder == VIDEO_ENCODER_H264 ? MEDIA_MIMETYPE_VIDEO_AVC : ""),
false /* decoder */, true /* hwCodec */, &codecs);
@@ -1515,6 +1516,10 @@
format->setString("mime", MEDIA_MIMETYPE_VIDEO_VP8);
break;
+ case VIDEO_ENCODER_HEVC:
+ format->setString("mime", MEDIA_MIMETYPE_VIDEO_HEVC);
+ break;
+
default:
CHECK(!"Should not be here, unsupported video encoding.");
break;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 5c13633..cede584 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -2142,11 +2142,7 @@
mPausedForBuffering = true;
onPause();
}
- // fall-thru
- }
- case Source::kWhatBufferingStart:
- {
notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0);
break;
}
@@ -2164,11 +2160,7 @@
onResume();
}
}
- // fall-thru
- }
- case Source::kWhatBufferingEnd:
- {
notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0);
break;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index ce87f87..4678956 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -525,7 +525,10 @@
ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
msg->setBuffer("buffer", buffer);
mCSDsToSubmit.removeAt(0);
- CHECK(onInputBufferFetched(msg));
+ if (!onInputBufferFetched(msg)) {
+ handleError(UNKNOWN_ERROR);
+ return false;
+ }
return true;
}
@@ -862,7 +865,11 @@
// copy into codec buffer
if (buffer != codecBuffer) {
- CHECK_LE(buffer->size(), codecBuffer->capacity());
+ if (buffer->size() > codecBuffer->capacity()) {
+ handleError(ERROR_BUFFER_TOO_SMALL);
+ mDequeuedInputBuffers.push_back(bufferIx);
+ return false;
+ }
codecBuffer->setRange(0, buffer->size());
memcpy(codecBuffer->data(), buffer->data(), buffer->size());
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 65e3a6e..332fef6 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -334,8 +334,8 @@
// down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
// current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
// getCurrentPosition here.
- int msec;
- getCurrentPosition(&msec);
+ int unused;
+ getCurrentPosition(&unused);
Mutex::Autolock autoLock(mLock);
@@ -364,11 +364,12 @@
status_t NuPlayerDriver::setPlaybackSettings(const AudioPlaybackRate &rate) {
status_t err = mPlayer->setPlaybackSettings(rate);
if (err == OK) {
+ // try to update position
+ int unused;
+ getCurrentPosition(&unused);
Mutex::Autolock autoLock(mLock);
if (rate.mSpeed == 0.f && mState == STATE_RUNNING) {
mState = STATE_PAUSED;
- // try to update position
- (void)mPlayer->getCurrentPosition(&mPositionUs);
notifyListener_l(MEDIA_PAUSED);
} else if (rate.mSpeed != 0.f && mState == STATE_PAUSED) {
mState = STATE_RUNNING;
@@ -423,7 +424,7 @@
int64_t tempUs = 0;
{
Mutex::Autolock autoLock(mLock);
- if (mSeekInProgress || mState == STATE_PAUSED) {
+ if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) {
tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
*msec = (int)divRound(tempUs, (int64_t)(1000));
return OK;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index fba4540..0176eafa 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -46,8 +46,6 @@
kWhatFlagsChanged,
kWhatVideoSizeChanged,
kWhatBufferingUpdate,
- kWhatBufferingStart,
- kWhatBufferingEnd,
kWhatPauseOnBufferingStart,
kWhatResumeOnBufferingEnd,
kWhatCacheStats,
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index c861fd1..2ecab6d 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -725,7 +725,7 @@
mBuffering = true;
sp<AMessage> notify = dupNotify();
- notify->setInt32("what", kWhatBufferingStart);
+ notify->setInt32("what", kWhatPauseOnBufferingStart);
notify->post();
}
}
@@ -741,7 +741,7 @@
mBuffering = false;
sp<AMessage> notify = dupNotify();
- notify->setInt32("what", kWhatBufferingEnd);
+ notify->setInt32("what", kWhatResumeOnBufferingEnd);
notify->post();
}
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ed5cd85..fefd0ef 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -3533,8 +3533,8 @@
hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
}
-
- // TODO: Need OMX structure definition for setting iFrameInterval
+ // TODO: finer control?
+ hevcType.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
err = mOMX->setParameter(
mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 9a4a350..14a0c66 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -24,6 +24,7 @@
FLACExtractor.cpp \
FrameRenderTracker.cpp \
HTTPBase.cpp \
+ HevcUtils.cpp \
JPEGSource.cpp \
MP3Extractor.cpp \
MPEG2TSWriter.cpp \
diff --git a/media/libstagefright/HevcUtils.cpp b/media/libstagefright/HevcUtils.cpp
new file mode 100644
index 0000000..087c903
--- /dev/null
+++ b/media/libstagefright/HevcUtils.cpp
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "HevcUtils"
+
+#include <cstring>
+
+#include "include/HevcUtils.h"
+#include "include/avc_utils.h"
+
+#include <media/stagefright/foundation/ABitReader.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+static const uint8_t kHevcNalUnitTypes[5] = {
+ kHevcNalUnitTypeVps,
+ kHevcNalUnitTypeSps,
+ kHevcNalUnitTypePps,
+ kHevcNalUnitTypePrefixSei,
+ kHevcNalUnitTypeSuffixSei,
+};
+
+HevcParameterSets::HevcParameterSets() {
+}
+
+status_t HevcParameterSets::addNalUnit(const uint8_t* data, size_t size) {
+ uint8_t nalUnitType = (data[0] >> 1) & 0x3f;
+ status_t err = OK;
+ switch (nalUnitType) {
+ case 32: // VPS
+ err = parseVps(data + 2, size - 2);
+ break;
+ case 33: // SPS
+ err = parseSps(data + 2, size - 2);
+ break;
+ case 34: // PPS
+ err = parsePps(data + 2, size - 2);
+ break;
+ case 39: // Prefix SEI
+ case 40: // Suffix SEI
+ // Ignore
+ break;
+ default:
+ ALOGE("Unrecognized NAL unit type.");
+ return ERROR_MALFORMED;
+ }
+
+ if (err != OK) {
+ return err;
+ }
+
+ sp<ABuffer> buffer = ABuffer::CreateAsCopy(data, size);
+ buffer->setInt32Data(nalUnitType);
+ mNalUnits.push(buffer);
+ return OK;
+}
+
+template <typename T>
+static bool findParam(uint32_t key, T *param,
+ KeyedVector<uint32_t, uint64_t> ¶ms) {
+ CHECK(param);
+ if (params.indexOfKey(key) < 0) {
+ return false;
+ }
+ *param = (T) params[key];
+ return true;
+}
+
+bool HevcParameterSets::findParam8(uint32_t key, uint8_t *param) {
+ return findParam(key, param, mParams);
+}
+
+bool HevcParameterSets::findParam16(uint32_t key, uint16_t *param) {
+ return findParam(key, param, mParams);
+}
+
+bool HevcParameterSets::findParam32(uint32_t key, uint32_t *param) {
+ return findParam(key, param, mParams);
+}
+
+bool HevcParameterSets::findParam64(uint32_t key, uint64_t *param) {
+ return findParam(key, param, mParams);
+}
+
+size_t HevcParameterSets::getNumNalUnitsOfType(uint8_t type) {
+ size_t num = 0;
+ for (size_t i = 0; i < mNalUnits.size(); ++i) {
+ if (getType(i) == type) {
+ ++num;
+ }
+ }
+ return num;
+}
+
+uint8_t HevcParameterSets::getType(size_t index) {
+ CHECK_LT(index, mNalUnits.size());
+ return mNalUnits[index]->int32Data();
+}
+
+size_t HevcParameterSets::getSize(size_t index) {
+ CHECK_LT(index, mNalUnits.size());
+ return mNalUnits[index]->size();
+}
+
+bool HevcParameterSets::write(size_t index, uint8_t* dest, size_t size) {
+ CHECK_LT(index, mNalUnits.size());
+ const sp<ABuffer>& nalUnit = mNalUnits[index];
+ if (size < nalUnit->size()) {
+ ALOGE("dest buffer size too small: %zu vs. %zu to be written",
+ size, nalUnit->size());
+ return false;
+ }
+ memcpy(dest, nalUnit->data(), nalUnit->size());
+ return true;
+}
+
+status_t HevcParameterSets::parseVps(const uint8_t* data, size_t size) {
+ // See Rec. ITU-T H.265 v3 (04/2015) Chapter 7.3.2.1 for reference
+ NALBitReader reader(data, size);
+ // Skip vps_video_parameter_set_id
+ reader.skipBits(4);
+ // Skip vps_base_layer_internal_flag
+ reader.skipBits(1);
+ // Skip vps_base_layer_available_flag
+ reader.skipBits(1);
+ // Skip vps_max_layers_minus_1
+ reader.skipBits(6);
+ // Skip vps_temporal_id_nesting_flags
+ reader.skipBits(1);
+ // Skip reserved
+ reader.skipBits(16);
+
+ mParams.add(kGeneralProfileSpace, reader.getBits(2));
+ mParams.add(kGeneralTierFlag, reader.getBits(1));
+ mParams.add(kGeneralProfileIdc, reader.getBits(5));
+ mParams.add(kGeneralProfileCompatibilityFlags, reader.getBits(32));
+ mParams.add(
+ kGeneralConstraintIndicatorFlags,
+ ((uint64_t)reader.getBits(16) << 32) | reader.getBits(32));
+ mParams.add(kGeneralLevelIdc, reader.getBits(8));
+ // 96 bits total for general profile.
+
+ return OK;
+}
+
+status_t HevcParameterSets::parseSps(const uint8_t* data, size_t size) {
+ // See Rec. ITU-T H.265 v3 (04/2015) Chapter 7.3.2.2 for reference
+ NALBitReader reader(data, size);
+ // Skip sps_video_parameter_set_id
+ reader.skipBits(4);
+ uint8_t maxSubLayersMinus1 = reader.getBits(3);
+ // Skip sps_temporal_id_nesting_flag;
+ reader.skipBits(1);
+ // Skip general profile
+ reader.skipBits(96);
+ if (maxSubLayersMinus1 > 0) {
+ bool subLayerProfilePresentFlag[8];
+ bool subLayerLevelPresentFlag[8];
+ for (int i = 0; i < maxSubLayersMinus1; ++i) {
+ subLayerProfilePresentFlag[i] = reader.getBits(1);
+ subLayerLevelPresentFlag[i] = reader.getBits(1);
+ }
+ // Skip reserved
+ reader.skipBits(2 * (8 - maxSubLayersMinus1));
+ for (int i = 0; i < maxSubLayersMinus1; ++i) {
+ if (subLayerProfilePresentFlag[i]) {
+ // Skip profile
+ reader.skipBits(88);
+ }
+ if (subLayerLevelPresentFlag[i]) {
+ // Skip sub_layer_level_idc[i]
+ reader.skipBits(8);
+ }
+ }
+ }
+ // Skip sps_seq_parameter_set_id
+ parseUE(&reader);
+ uint8_t chromaFormatIdc = parseUE(&reader);
+ mParams.add(kChromaFormatIdc, chromaFormatIdc);
+ if (chromaFormatIdc == 3) {
+ // Skip separate_colour_plane_flag
+ reader.skipBits(1);
+ }
+ // Skip pic_width_in_luma_samples
+ parseUE(&reader);
+ // Skip pic_height_in_luma_samples
+ parseUE(&reader);
+ if (reader.getBits(1) /* i.e. conformance_window_flag */) {
+ // Skip conf_win_left_offset
+ parseUE(&reader);
+ // Skip conf_win_right_offset
+ parseUE(&reader);
+ // Skip conf_win_top_offset
+ parseUE(&reader);
+ // Skip conf_win_bottom_offset
+ parseUE(&reader);
+ }
+ mParams.add(kBitDepthLumaMinus8, parseUE(&reader));
+ mParams.add(kBitDepthChromaMinus8, parseUE(&reader));
+
+ return OK;
+}
+
+status_t HevcParameterSets::parsePps(
+ const uint8_t* data __unused, size_t size __unused) {
+ return OK;
+}
+
+status_t HevcParameterSets::makeHvcc(uint8_t *hvcc, size_t *hvccSize,
+ size_t nalSizeLength) {
+ if (hvcc == NULL || hvccSize == NULL
+ || (nalSizeLength != 4 && nalSizeLength != 2)) {
+ return BAD_VALUE;
+ }
+ // ISO 14496-15: HEVC file format
+ size_t size = 23; // 23 bytes in the header
+ size_t numOfArrays = 0;
+ const size_t numNalUnits = getNumNalUnits();
+ for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
+ uint8_t type = kHevcNalUnitTypes[i];
+ size_t numNalus = getNumNalUnitsOfType(type);
+ if (numNalus == 0) {
+ continue;
+ }
+ ++numOfArrays;
+ size += 3;
+ for (size_t j = 0; j < numNalUnits; ++j) {
+ if (getType(j) != type) {
+ continue;
+ }
+ size += 2 + getSize(j);
+ }
+ }
+ uint8_t generalProfileSpace, generalTierFlag, generalProfileIdc;
+ if (!findParam8(kGeneralProfileSpace, &generalProfileSpace)
+ || !findParam8(kGeneralTierFlag, &generalTierFlag)
+ || !findParam8(kGeneralProfileIdc, &generalProfileIdc)) {
+ return ERROR_MALFORMED;
+ }
+ uint32_t compatibilityFlags;
+ uint64_t constraintIdcFlags;
+ if (!findParam32(kGeneralProfileCompatibilityFlags, &compatibilityFlags)
+ || !findParam64(kGeneralConstraintIndicatorFlags, &constraintIdcFlags)) {
+ return ERROR_MALFORMED;
+ }
+ uint8_t generalLevelIdc;
+ if (!findParam8(kGeneralLevelIdc, &generalLevelIdc)) {
+ return ERROR_MALFORMED;
+ }
+ uint8_t chromaFormatIdc, bitDepthLumaMinus8, bitDepthChromaMinus8;
+ if (!findParam8(kChromaFormatIdc, &chromaFormatIdc)
+ || !findParam8(kBitDepthLumaMinus8, &bitDepthLumaMinus8)
+ || !findParam8(kBitDepthChromaMinus8, &bitDepthChromaMinus8)) {
+ return ERROR_MALFORMED;
+ }
+ if (size > *hvccSize) {
+ return NO_MEMORY;
+ }
+ *hvccSize = size;
+
+ uint8_t *header = hvcc;
+ header[0] = 1;
+ header[1] = (kGeneralProfileSpace << 6) | (kGeneralTierFlag << 5) | kGeneralProfileIdc;
+ header[2] = (compatibilityFlags >> 24) & 0xff;
+ header[3] = (compatibilityFlags >> 16) & 0xff;
+ header[4] = (compatibilityFlags >> 8) & 0xff;
+ header[5] = compatibilityFlags & 0xff;
+ header[6] = (constraintIdcFlags >> 40) & 0xff;
+ header[7] = (constraintIdcFlags >> 32) & 0xff;
+ header[8] = (constraintIdcFlags >> 24) & 0xff;
+ header[9] = (constraintIdcFlags >> 16) & 0xff;
+ header[10] = (constraintIdcFlags >> 8) & 0xff;
+ header[11] = constraintIdcFlags & 0xff;
+ header[12] = generalLevelIdc;
+ // FIXME: parse min_spatial_segmentation_idc.
+ header[13] = 0xf0;
+ header[14] = 0;
+ // FIXME: derive parallelismType properly.
+ header[15] = 0xfc;
+ header[16] = 0xfc | chromaFormatIdc;
+ header[17] = 0xf8 | bitDepthLumaMinus8;
+ header[18] = 0xf8 | bitDepthChromaMinus8;
+ // FIXME: derive avgFrameRate
+ header[19] = 0;
+ header[20] = 0;
+ // constantFrameRate, numTemporalLayers, temporalIdNested all set to 0.
+ header[21] = nalSizeLength - 1;
+ header[22] = numOfArrays;
+ header += 23;
+ for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
+ uint8_t type = kHevcNalUnitTypes[i];
+ size_t numNalus = getNumNalUnitsOfType(type);
+ if (numNalus == 0) {
+ continue;
+ }
+ // array_completeness set to 0.
+ header[0] = type;
+ header[1] = (numNalus >> 8) & 0xff;
+ header[2] = numNalus & 0xff;
+ header += 3;
+ for (size_t j = 0; j < numNalUnits; ++j) {
+ if (getType(j) != type) {
+ continue;
+ }
+ header[0] = (getSize(j) >> 8) & 0xff;
+ header[1] = getSize(j) & 0xff;
+ if (!write(j, header + 2, size - (header - (uint8_t *)hvcc))) {
+ return NO_MEMORY;
+ }
+ header += (2 + getSize(j));
+ }
+ }
+ CHECK_EQ(header - size, hvcc);
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index ea4a7ac..a5d9484 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -41,7 +41,7 @@
#include <cutils/properties.h>
#include "include/ESDS.h"
-
+#include "include/HevcUtils.h"
#ifndef __predict_false
#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
@@ -70,6 +70,18 @@
#endif
static const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
+static const uint8_t kMandatoryHevcNalUnitTypes[3] = {
+ kHevcNalUnitTypeVps,
+ kHevcNalUnitTypeSps,
+ kHevcNalUnitTypePps,
+};
+static const uint8_t kHevcNalUnitTypes[5] = {
+ kHevcNalUnitTypeVps,
+ kHevcNalUnitTypeSps,
+ kHevcNalUnitTypePps,
+ kHevcNalUnitTypePrefixSei,
+ kHevcNalUnitTypeSuffixSei,
+};
/* uncomment to include model and build in meta */
//#define SHOW_MODEL_BUILD 1
@@ -89,6 +101,7 @@
void writeTrackHeader(bool use32BitOffset = true);
void bufferChunk(int64_t timestampUs);
bool isAvc() const { return mIsAvc; }
+ bool isHevc() const { return mIsHevc; }
bool isAudio() const { return mIsAudio; }
bool isMPEG4() const { return mIsMPEG4; }
void addChunkOffset(off64_t offset);
@@ -234,6 +247,7 @@
volatile bool mResumed;
volatile bool mStarted;
bool mIsAvc;
+ bool mIsHevc;
bool mIsAudio;
bool mIsMPEG4;
int32_t mTrackId;
@@ -299,10 +313,17 @@
const uint8_t *parseParamSet(
const uint8_t *data, size_t length, int type, size_t *paramSetLen);
+ status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0);
+
status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
+ status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size);
+ status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size);
+ status_t parseHEVCCodecSpecificData(
+ const uint8_t *data, size_t size, HevcParameterSets ¶mSets);
+
// Track authoring progress status
void trackProgressStatus(int64_t timeUs, status_t err = OK);
void initTrackingProgressStatus(MetaData *params);
@@ -340,6 +361,7 @@
void writeD263Box();
void writePaspBox();
void writeAvccBox();
+ void writeHvccBox();
void writeUrlBox();
void writeDrefBox();
void writeDinfBox();
@@ -463,6 +485,8 @@
return "s263";
} else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
return "avc1";
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
+ return "hvc1";
}
} else {
ALOGE("Track (%s) other than video or audio is not supported", mime);
@@ -1465,6 +1489,7 @@
const char *mime;
mMeta->findCString(kKeyMIMEType, &mime);
mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
+ mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
mIsAudio = !strncasecmp(mime, "audio/", 6);
mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
@@ -1560,31 +1585,26 @@
const char *mime;
CHECK(mMeta->findCString(kKeyMIMEType, &mime));
+ uint32_t type;
+ const void *data = NULL;
+ size_t size = 0;
if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
- uint32_t type;
- const void *data;
- size_t size;
- if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
- mCodecSpecificData = malloc(size);
- mCodecSpecificDataSize = size;
- memcpy(mCodecSpecificData, data, size);
- mGotAllCodecSpecificData = true;
- }
+ mMeta->findData(kKeyAVCC, &type, &data, &size);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
+ mMeta->findData(kKeyHVCC, &type, &data, &size);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
|| !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
- uint32_t type;
- const void *data;
- size_t size;
if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
ESDS esds(data, size);
- if (esds.getCodecSpecificInfo(&data, &size) == OK) {
- mCodecSpecificData = malloc(size);
- mCodecSpecificDataSize = size;
- memcpy(mCodecSpecificData, data, size);
- mGotAllCodecSpecificData = true;
+ if (esds.getCodecSpecificInfo(&data, &size) != OK) {
+ data = NULL;
+ size = 0;
}
}
}
+ if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
+ mGotAllCodecSpecificData = true;
+ }
}
MPEG4Writer::Track::~Track() {
@@ -1661,7 +1681,7 @@
while (!chunk->mSamples.empty()) {
List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
- off64_t offset = chunk->mTrack->isAvc()
+ off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc())
? addLengthPrefixedSample_l(*it)
: addSample_l(*it);
@@ -1968,13 +1988,30 @@
// 2 bytes for each of the parameter set length field
// plus the 7 bytes for the header
- if (size < 4 + 7) {
+ return copyCodecSpecificData(data, size, 4 + 7);
+}
+
+status_t MPEG4Writer::Track::copyHEVCCodecSpecificData(
+ const uint8_t *data, size_t size) {
+ ALOGV("copyHEVCCodecSpecificData");
+
+ // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2)
+ return copyCodecSpecificData(data, size, 23);
+}
+
+status_t MPEG4Writer::Track::copyCodecSpecificData(
+ const uint8_t *data, size_t size, size_t minLength) {
+ if (size < minLength) {
ALOGE("Codec specific data length too short: %zu", size);
return ERROR_MALFORMED;
}
- mCodecSpecificDataSize = size;
mCodecSpecificData = malloc(size);
+ if (mCodecSpecificData == NULL) {
+ ALOGE("Failed allocating codec specific data");
+ return NO_MEMORY;
+ }
+ mCodecSpecificDataSize = size;
memcpy(mCodecSpecificData, data, size);
return OK;
}
@@ -2097,6 +2134,11 @@
// ISO 14496-15: AVC file format
mCodecSpecificDataSize += 7; // 7 more bytes in the header
mCodecSpecificData = malloc(mCodecSpecificDataSize);
+ if (mCodecSpecificData == NULL) {
+ mCodecSpecificDataSize = 0;
+ ALOGE("Failed allocating codec specific data");
+ return NO_MEMORY;
+ }
uint8_t *header = (uint8_t *)mCodecSpecificData;
header[0] = 1; // version
header[1] = mProfileIdc; // profile indication
@@ -2145,6 +2187,96 @@
return OK;
}
+
+status_t MPEG4Writer::Track::parseHEVCCodecSpecificData(
+ const uint8_t *data, size_t size, HevcParameterSets ¶mSets) {
+
+ ALOGV("parseHEVCCodecSpecificData");
+ const uint8_t *tmp = data;
+ const uint8_t *nextStartCode = data;
+ size_t bytesLeft = size;
+ while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
+ nextStartCode = findNextStartCode(tmp + 4, bytesLeft - 4);
+ if (nextStartCode == NULL) {
+ return ERROR_MALFORMED;
+ }
+ status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4);
+ if (err != OK) {
+ return ERROR_MALFORMED;
+ }
+
+ // Move on to find the next parameter set
+ bytesLeft -= nextStartCode - tmp;
+ tmp = nextStartCode;
+ }
+
+ size_t csdSize = 23;
+ const size_t numNalUnits = paramSets.getNumNalUnits();
+ for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) {
+ int type = kMandatoryHevcNalUnitTypes[i];
+ size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
+ if (numParamSets == 0) {
+ ALOGE("Cound not find NAL unit of type %d", type);
+ return ERROR_MALFORMED;
+ }
+ }
+ for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
+ int type = kHevcNalUnitTypes[i];
+ size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
+ if (numParamSets > 0xffff) {
+ ALOGE("Too many seq parameter sets (%zu) found", numParamSets);
+ return ERROR_MALFORMED;
+ }
+ csdSize += 3;
+ for (size_t j = 0; j < numNalUnits; ++j) {
+ if (paramSets.getType(j) != type) {
+ continue;
+ }
+ csdSize += 2 + paramSets.getSize(j);
+ }
+ }
+ mCodecSpecificDataSize = csdSize;
+ return OK;
+}
+
+status_t MPEG4Writer::Track::makeHEVCCodecSpecificData(
+ const uint8_t *data, size_t size) {
+
+ if (mCodecSpecificData != NULL) {
+ ALOGE("Already have codec specific data");
+ return ERROR_MALFORMED;
+ }
+
+ if (size < 4) {
+ ALOGE("Codec specific data length too short: %zu", size);
+ return ERROR_MALFORMED;
+ }
+
+ // Data is in the form of HEVCCodecSpecificData
+ if (memcmp("\x00\x00\x00\x01", data, 4)) {
+ return copyHEVCCodecSpecificData(data, size);
+ }
+
+ HevcParameterSets paramSets;
+ if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) {
+ return ERROR_MALFORMED;
+ }
+
+ mCodecSpecificData = malloc(mCodecSpecificDataSize);
+ if (mCodecSpecificData == NULL) {
+ mCodecSpecificDataSize = 0;
+ ALOGE("Failed allocating codec specific data");
+ return NO_MEMORY;
+ }
+ status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
+ &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 5 : 2);
+ if (err != OK) {
+ return err;
+ }
+
+ return OK;
+}
+
/*
* Updates the drift time from the audio track so that
* the video track can get the updated drift time information
@@ -2228,13 +2360,15 @@
+ buffer->range_offset(),
buffer->range_length());
CHECK_EQ((status_t)OK, err);
- } else if (mIsMPEG4) {
- mCodecSpecificDataSize = buffer->range_length();
- mCodecSpecificData = malloc(mCodecSpecificDataSize);
- memcpy(mCodecSpecificData,
+ } else if (mIsHevc) {
+ status_t err = makeHEVCCodecSpecificData(
(const uint8_t *)buffer->data()
+ buffer->range_offset(),
- buffer->range_length());
+ buffer->range_length());
+ CHECK_EQ((status_t)OK, err);
+ } else if (mIsMPEG4) {
+ copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
+ buffer->range_length());
}
buffer->release();
@@ -2254,10 +2388,10 @@
buffer->release();
buffer = NULL;
- if (mIsAvc) StripStartcode(copy);
+ if (mIsAvc || mIsHevc) StripStartcode(copy);
size_t sampleSize = copy->range_length();
- if (mIsAvc) {
+ if (mIsAvc || mIsHevc) {
if (mOwner->useNalLengthFour()) {
sampleSize += 4;
} else {
@@ -2457,7 +2591,7 @@
trackProgressStatus(timestampUs);
}
if (!hasMultipleTracks) {
- off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
+ off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addLengthPrefixedSample_l(copy)
: mOwner->addSample_l(copy);
uint32_t count = (mOwner->use32BitFileOffset()
@@ -2709,7 +2843,8 @@
CHECK(mMeta->findCString(kKeyMIMEType, &mime));
if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
- !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
+ !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
+ !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
if (!mCodecSpecificData ||
mCodecSpecificDataSize <= 0) {
ALOGE("Missing codec specific data");
@@ -2815,6 +2950,8 @@
writeD263Box();
} else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
writeAvccBox();
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
+ writeHvccBox();
}
writePaspBox();
@@ -3070,6 +3207,20 @@
mOwner->endBox(); // avcC
}
+
+void MPEG4Writer::Track::writeHvccBox() {
+ CHECK(mCodecSpecificData);
+ CHECK_GE(mCodecSpecificDataSize, 5);
+
+ // Patch avcc's lengthSize field to match the number
+ // of bytes we use to indicate the size of a nal unit.
+ uint8_t *ptr = (uint8_t *)mCodecSpecificData;
+ ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
+ mOwner->beginBox("hvcC");
+ mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
+ mOwner->endBox(); // hvcC
+}
+
void MPEG4Writer::Track::writeD263Box() {
mOwner->beginBox("d263");
mOwner->writeInt32(0); // vendor
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 67d9921..8809640 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -449,6 +449,59 @@
return OK;
}
+status_t NuMediaExtractor::appendVorbisNumPageSamples(TrackInfo *info, const sp<ABuffer> &buffer) {
+ int32_t numPageSamples;
+ if (!info->mSample->meta_data()->findInt32(
+ kKeyValidSamples, &numPageSamples)) {
+ numPageSamples = -1;
+ }
+
+ memcpy((uint8_t *)buffer->data() + info->mSample->range_length(),
+ &numPageSamples,
+ sizeof(numPageSamples));
+
+ uint32_t type;
+ const void *data;
+ size_t size, size2;
+ if (info->mSample->meta_data()->findData(kKeyEncryptedSizes, &type, &data, &size)) {
+ // Signal numPageSamples (a plain int32_t) is appended at the end,
+ // i.e. sizeof(numPageSamples) plain bytes + 0 encrypted bytes
+ if (SIZE_MAX - size < sizeof(int32_t)) {
+ return -ENOMEM;
+ }
+
+ size_t newSize = size + sizeof(int32_t);
+ sp<ABuffer> abuf = new ABuffer(newSize);
+ uint8_t *adata = static_cast<uint8_t *>(abuf->data());
+ if (adata == NULL) {
+ return -ENOMEM;
+ }
+
+ // append 0 to encrypted sizes
+ int32_t zero = 0;
+ memcpy(adata, data, size);
+ memcpy(adata + size, &zero, sizeof(zero));
+ info->mSample->meta_data()->setData(kKeyEncryptedSizes, type, adata, newSize);
+
+ if (info->mSample->meta_data()->findData(kKeyPlainSizes, &type, &data, &size2)) {
+ if (size2 != size) {
+ return ERROR_MALFORMED;
+ }
+ memcpy(adata, data, size);
+ } else {
+ // if sample meta data does not include plain size array, assume filled with zeros,
+ // i.e. entire buffer is encrypted
+ memset(adata, 0, size);
+ }
+ // append sizeof(numPageSamples) to plain sizes.
+ int32_t int32Size = sizeof(numPageSamples);
+ memcpy(adata + size, &int32Size, sizeof(int32Size));
+ info->mSample->meta_data()->setData(kKeyPlainSizes, type, adata, newSize);
+ }
+
+ return OK;
+}
+
status_t NuMediaExtractor::readSampleData(const sp<ABuffer> &buffer) {
Mutex::Autolock autoLock(mLock);
@@ -478,21 +531,16 @@
memcpy((uint8_t *)buffer->data(), src, info->mSample->range_length());
+ status_t err = OK;
if (info->mTrackFlags & kIsVorbis) {
- int32_t numPageSamples;
- if (!info->mSample->meta_data()->findInt32(
- kKeyValidSamples, &numPageSamples)) {
- numPageSamples = -1;
- }
-
- memcpy((uint8_t *)buffer->data() + info->mSample->range_length(),
- &numPageSamples,
- sizeof(numPageSamples));
+ err = appendVorbisNumPageSamples(info, buffer);
}
- buffer->setRange(0, sampleSize);
+ if (err == OK) {
+ buffer->setRange(0, sampleSize);
+ }
- return OK;
+ return err;
}
status_t NuMediaExtractor::getSampleTrackIndex(size_t *trackIndex) {
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index 6b62e43..9940822 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -55,11 +55,17 @@
return err;
}
+ int consumerUsage = 0;
+ err = nativeWindow->query(nativeWindow, NATIVE_WINDOW_CONSUMER_USAGE_BITS, &consumerUsage);
+ if (err != NO_ERROR) {
+ ALOGW("failed to get consumer usage bits. ignoring");
+ err = NO_ERROR;
+ }
+
// Make sure to check whether either Stagefright or the video decoder
// requested protected buffers.
if (usage & GRALLOC_USAGE_PROTECTED) {
- // Verify that the ANativeWindow sends images directly to
- // SurfaceFlinger.
+ // Check if the ANativeWindow sends images directly to SurfaceFlinger.
int queuesToNativeWindow = 0;
err = nativeWindow->query(
nativeWindow, NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &queuesToNativeWindow);
@@ -67,19 +73,14 @@
ALOGE("error authenticating native window: %s (%d)", strerror(-err), -err);
return err;
}
- if (queuesToNativeWindow != 1) {
+
+ // Check if the ANativeWindow uses hardware protected buffers.
+ if (queuesToNativeWindow != 1 && !(consumerUsage & GRALLOC_USAGE_PROTECTED)) {
ALOGE("native window could not be authenticated");
return PERMISSION_DENIED;
}
}
- int consumerUsage = 0;
- err = nativeWindow->query(nativeWindow, NATIVE_WINDOW_CONSUMER_USAGE_BITS, &consumerUsage);
- if (err != NO_ERROR) {
- ALOGW("failed to get consumer usage bits. ignoring");
- err = NO_ERROR;
- }
-
int finalUsage = usage | consumerUsage;
ALOGV("gralloc usage: %#x(producer) + %#x(consumer) = %#x", usage, consumerUsage, finalUsage);
err = native_window_set_usage(nativeWindow, finalUsage);
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 2a8b635..14f6e2b 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -22,6 +22,7 @@
#include <sys/stat.h>
#include "include/ESDS.h"
+#include "include/HevcUtils.h"
#include <arpa/inet.h>
#include <cutils/properties.h>
@@ -461,6 +462,13 @@
msg->setBuffer("csd-2", buffer);
}
+ // TODO expose "crypto-key"/kKeyCryptoKey through public api
+ if (meta->findData(kKeyCryptoKey, &type, &data, &size)) {
+ sp<ABuffer> buffer = new (std::nothrow) ABuffer(size);
+ msg->setBuffer("crypto-key", buffer);
+ memcpy(buffer->data(), data, size);
+ }
+
*format = msg;
return OK;
@@ -575,6 +583,41 @@
}
+static size_t reassembleHVCC(const sp<ABuffer> &csd0, uint8_t *hvcc, size_t hvccSize, size_t nalSizeLength) {
+ HevcParameterSets paramSets;
+ uint8_t* data = csd0->data();
+ if (csd0->size() < 4) {
+ ALOGE("csd0 too small");
+ return 0;
+ }
+ if (memcmp(data, "\x00\x00\x00\x01", 4) != 0) {
+ ALOGE("csd0 doesn't start with a start code");
+ return 0;
+ }
+ size_t prevNalOffset = 4;
+ status_t err = OK;
+ for (size_t i = 1; i < csd0->size() - 4; ++i) {
+ if (memcmp(&data[i], "\x00\x00\x00\x01", 4) != 0) {
+ continue;
+ }
+ err = paramSets.addNalUnit(&data[prevNalOffset], i - prevNalOffset);
+ if (err != OK) {
+ return 0;
+ }
+ prevNalOffset = i + 4;
+ }
+ err = paramSets.addNalUnit(&data[prevNalOffset], csd0->size() - prevNalOffset);
+ if (err != OK) {
+ return 0;
+ }
+ size_t size = hvccSize;
+ err = paramSets.makeHvcc(hvcc, &size, nalSizeLength);
+ if (err != OK) {
+ return 0;
+ }
+ return size;
+}
+
void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
AString mime;
if (msg->findString("mime", &mime)) {
@@ -693,6 +736,10 @@
// for transporting the CSD to muxers.
reassembleESDS(csd0, esds);
meta->setData(kKeyESDS, kKeyESDS, esds, sizeof(esds));
+ } else if (mime == MEDIA_MIMETYPE_VIDEO_HEVC) {
+ uint8_t hvcc[1024]; // that oughta be enough, right?
+ size_t outsize = reassembleHVCC(csd0, hvcc, 1024, 4);
+ meta->setData(kKeyHVCC, kKeyHVCC, hvcc, outsize);
}
}
diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk
index 4d12f82..77a7b1e 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.mk
+++ b/media/libstagefright/codecs/amrwbenc/Android.mk
@@ -102,7 +102,7 @@
LOCAL_CFLAGS += -Werror
LOCAL_CLANG := true
-#LOCAL_SANITIZE := signed-integer-overflow
+LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_STATIC_LIBRARY)
@@ -120,7 +120,7 @@
LOCAL_CFLAGS += -Werror
LOCAL_CLANG := true
-#LOCAL_SANITIZE := signed-integer-overflow
+LOCAL_SANITIZE := signed-integer-overflow
LOCAL_STATIC_LIBRARIES := \
libstagefright_amrwbenc
diff --git a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
index b9a9e26..e3b2f6c 100644
--- a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
+++ b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
@@ -1014,8 +1014,8 @@
{
ps2 = add1(ps1, dn[y]);
- alp2 = alp1 + ((*p1++)<<13);
- alp2 = alp2 + ((*p2++)<<14);
+ alp2 = L_add(alp1, ((*p1++)<<13));
+ alp2 = L_add(alp2, ((*p2++)<<14));
alp_16 = extract_h(alp2);
sq = vo_mult(ps2, ps2);
s = vo_L_mult(alpk, sq) - ((sqk * alp_16)<<1);
diff --git a/media/libstagefright/include/HevcUtils.h b/media/libstagefright/include/HevcUtils.h
new file mode 100644
index 0000000..0d7bb2f
--- /dev/null
+++ b/media/libstagefright/include/HevcUtils.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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 HEVC_UTILS_H_
+
+#define HEVC_UTILS_H_
+
+#include <stdint.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/StrongPointer.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+enum {
+ kHevcNalUnitTypeVps = 32,
+ kHevcNalUnitTypeSps = 33,
+ kHevcNalUnitTypePps = 34,
+ kHevcNalUnitTypePrefixSei = 39,
+ kHevcNalUnitTypeSuffixSei = 40,
+};
+
+enum {
+ // uint8_t
+ kGeneralProfileSpace,
+ // uint8_t
+ kGeneralTierFlag,
+ // uint8_t
+ kGeneralProfileIdc,
+ // uint32_t
+ kGeneralProfileCompatibilityFlags,
+ // uint64_t
+ kGeneralConstraintIndicatorFlags,
+ // uint8_t
+ kGeneralLevelIdc,
+ // uint8_t
+ kChromaFormatIdc,
+ // uint8_t
+ kBitDepthLumaMinus8,
+ // uint8_t
+ kBitDepthChromaMinus8,
+};
+
+class HevcParameterSets {
+public:
+ HevcParameterSets();
+
+ status_t addNalUnit(const uint8_t* data, size_t size);
+
+ bool findParam8(uint32_t key, uint8_t *param);
+ bool findParam16(uint32_t key, uint16_t *param);
+ bool findParam32(uint32_t key, uint32_t *param);
+ bool findParam64(uint32_t key, uint64_t *param);
+
+ inline size_t getNumNalUnits() { return mNalUnits.size(); }
+ size_t getNumNalUnitsOfType(uint8_t type);
+ uint8_t getType(size_t index);
+ size_t getSize(size_t index);
+ // Note that this method does not write the start code.
+ bool write(size_t index, uint8_t* dest, size_t size);
+ status_t makeHvcc(uint8_t *hvcc, size_t *hvccSize, size_t nalSizeLength);
+
+private:
+ status_t parseVps(const uint8_t* data, size_t size);
+ status_t parseSps(const uint8_t* data, size_t size);
+ status_t parsePps(const uint8_t* data, size_t size);
+
+ KeyedVector<uint32_t, uint64_t> mParams;
+ Vector<sp<ABuffer>> mNalUnits;
+
+ DISALLOW_EVIL_CONSTRUCTORS(HevcParameterSets);
+};
+
+} // namespace android
+
+#endif // HEVC_UTILS_H_
diff --git a/media/libstagefright/matroska/Android.mk b/media/libstagefright/matroska/Android.mk
index 193408c..b0cbf08 100644
--- a/media/libstagefright/matroska/Android.mk
+++ b/media/libstagefright/matroska/Android.mk
@@ -7,6 +7,7 @@
LOCAL_C_INCLUDES:= \
$(TOP)/external/libvpx/libwebm \
$(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/frameworks/av/media/libstagefright/include \
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
LOCAL_CLANG := true
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index 82b471f..861bdc5 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -19,9 +19,11 @@
#include <utils/Log.h>
#include "MatroskaExtractor.h"
+#include "avc_utils.h"
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaBuffer.h>
@@ -144,12 +146,13 @@
Type mType;
bool mIsAudio;
BlockIterator mBlockIter;
- size_t mNALSizeLen; // for type AVC
+ ssize_t mNALSizeLen; // for type AVC
List<MediaBuffer *> mPendingFrames;
status_t advance();
+ status_t setWebmBlockCryptoInfo(MediaBuffer *mbuf);
status_t readBlock();
void clearPendingFrames();
@@ -213,7 +216,7 @@
mBlockIter(mExtractor.get(),
mExtractor->mTracks.itemAt(index).mTrackNum,
index),
- mNALSizeLen(0) {
+ mNALSizeLen(-1) {
sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta;
const char *mime;
@@ -227,13 +230,18 @@
uint32_t dummy;
const uint8_t *avcc;
size_t avccSize;
- CHECK(meta->findData(
- kKeyAVCC, &dummy, (const void **)&avcc, &avccSize));
-
- CHECK_GE(avccSize, 5u);
-
- mNALSizeLen = 1 + (avcc[4] & 3);
- ALOGV("mNALSizeLen = %zu", mNALSizeLen);
+ int32_t nalSizeLen = 0;
+ if (meta->findInt32(kKeyNalLengthSize, &nalSizeLen)) {
+ if (nalSizeLen >= 0 && nalSizeLen <= 4) {
+ mNALSizeLen = nalSizeLen;
+ }
+ } else if (meta->findData(kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)
+ && avccSize >= 5u) {
+ mNALSizeLen = 1 + (avcc[4] & 3);
+ ALOGV("mNALSizeLen = %zd", mNALSizeLen);
+ } else {
+ ALOGE("No mNALSizeLen");
+ }
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
mType = AAC;
}
@@ -244,6 +252,10 @@
}
status_t MatroskaSource::start(MetaData * /* params */) {
+ if (mType == AVC && mNALSizeLen < 0) {
+ return ERROR_MALFORMED;
+ }
+
mBlockIter.reset();
return OK;
@@ -492,6 +504,9 @@
}
int64_t BlockIterator::blockTimeUs() const {
+ if (mCluster == NULL || mBlockEntry == NULL) {
+ return -1;
+ }
return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
}
@@ -511,6 +526,72 @@
}
}
+status_t MatroskaSource::setWebmBlockCryptoInfo(MediaBuffer *mbuf) {
+ if (mbuf->range_length() < 1 || mbuf->range_length() - 1 > INT32_MAX) {
+ // 1-byte signal
+ return ERROR_MALFORMED;
+ }
+
+ const uint8_t *data = (const uint8_t *)mbuf->data() + mbuf->range_offset();
+ bool blockEncrypted = data[0] & 0x1;
+ if (blockEncrypted && mbuf->range_length() < 9) {
+ // 1-byte signal + 8-byte IV
+ return ERROR_MALFORMED;
+ }
+
+ sp<MetaData> meta = mbuf->meta_data();
+ if (blockEncrypted) {
+ /*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Signal Byte | |
+ * +-+-+-+-+-+-+-+-+ IV |
+ * | |
+ * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | |
+ * |-+-+-+-+-+-+-+-+ |
+ * : Bytes 1..N of encrypted frame :
+ * | |
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ int32_t plainSizes[] = { 0 };
+ int32_t encryptedSizes[] = { static_cast<int32_t>(mbuf->range_length() - 9) };
+ uint8_t ctrCounter[16] = { 0 };
+ uint32_t type;
+ const uint8_t *keyId;
+ size_t keyIdSize;
+ sp<MetaData> trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
+ CHECK(trackMeta->findData(kKeyCryptoKey, &type, (const void **)&keyId, &keyIdSize));
+ meta->setData(kKeyCryptoKey, 0, keyId, keyIdSize);
+ memcpy(ctrCounter, data + 1, 8);
+ meta->setData(kKeyCryptoIV, 0, ctrCounter, 16);
+ meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
+ meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
+ mbuf->set_range(9, mbuf->range_length() - 9);
+ } else {
+ /*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Signal Byte | |
+ * +-+-+-+-+-+-+-+-+ |
+ * : Bytes 1..N of unencrypted frame :
+ * | |
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ int32_t plainSizes[] = { static_cast<int32_t>(mbuf->range_length() - 1) };
+ int32_t encryptedSizes[] = { 0 };
+ meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
+ meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
+ mbuf->set_range(1, mbuf->range_length() - 1);
+ }
+
+ return OK;
+}
+
status_t MatroskaSource::readBlock() {
CHECK(mPendingFrames.empty());
@@ -529,13 +610,19 @@
mbuf->meta_data()->setInt64(kKeyTime, timeUs);
mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
- long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data());
- if (n != 0) {
+ status_t err = frame.Read(mExtractor->mReader, static_cast<uint8_t *>(mbuf->data()));
+ if (err == OK
+ && mExtractor->mIsWebm
+ && mExtractor->mTracks.itemAt(mTrackIndex).mEncrypted) {
+ err = setWebmBlockCryptoInfo(mbuf);
+ }
+
+ if (err != OK) {
mPendingFrames.clear();
mBlockIter.advance();
mbuf->release();
- return ERROR_IO;
+ return err;
}
mPendingFrames.push_back(mbuf);
@@ -582,7 +669,7 @@
MediaBuffer *frame = *mPendingFrames.begin();
mPendingFrames.erase(mPendingFrames.begin());
- if (mType != AVC) {
+ if (mType != AVC || mNALSizeLen == 0) {
if (targetSampleTimeUs >= 0ll) {
frame->meta_data()->setInt64(
kKeyTargetTime, targetSampleTimeUs);
@@ -598,6 +685,9 @@
// followed by a corresponding number of bytes containing the fragment.
// We output all these fragments into a single large buffer separated
// by startcodes (0x00 0x00 0x00 0x01).
+ //
+ // When mNALSizeLen is 0, we assume the data is already in the format
+ // desired.
const uint8_t *srcPtr =
(const uint8_t *)frame->data() + frame->range_offset();
@@ -939,6 +1029,35 @@
return OK;
}
+status_t MatroskaExtractor::synthesizeAVCC(TrackInfo *trackInfo, size_t index) {
+ BlockIterator iter(this, trackInfo->mTrackNum, index);
+ if (iter.eos()) {
+ return ERROR_MALFORMED;
+ }
+
+ const mkvparser::Block *block = iter.block();
+ if (block->GetFrameCount() <= 0) {
+ return ERROR_MALFORMED;
+ }
+
+ const mkvparser::Block::Frame &frame = block->GetFrame(0);
+ sp<ABuffer> abuf = new ABuffer(frame.len);
+ long n = frame.Read(mReader, abuf->data());
+ if (n != 0) {
+ return ERROR_MALFORMED;
+ }
+
+ sp<MetaData> avcMeta = MakeAVCCodecSpecificData(abuf);
+ if (avcMeta == NULL) {
+ return ERROR_MALFORMED;
+ }
+
+ // Override the synthesized nal length size, which is arbitrary
+ avcMeta->setInt32(kKeyNalLengthSize, 0);
+ trackInfo->mMeta = avcMeta;
+ return OK;
+}
+
void MatroskaExtractor::addTracks() {
const mkvparser::Tracks *tracks = mSegment->GetTracks();
@@ -1051,10 +1170,31 @@
meta->setInt64(kKeyDuration, (durationNs + 500) / 1000);
mTracks.push();
- TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1);
+ size_t n = mTracks.size() - 1;
+ TrackInfo *trackInfo = &mTracks.editItemAt(n);
trackInfo->mTrackNum = track->GetNumber();
trackInfo->mMeta = meta;
trackInfo->mExtractor = this;
+
+ trackInfo->mEncrypted = false;
+ for(size_t i = 0; i < track->GetContentEncodingCount() && !trackInfo->mEncrypted; i++) {
+ const mkvparser::ContentEncoding *encoding = track->GetContentEncodingByIndex(i);
+ for(size_t j = 0; j < encoding->GetEncryptionCount(); j++) {
+ const mkvparser::ContentEncoding::ContentEncryption *encryption;
+ encryption = encoding->GetEncryptionByIndex(j);
+ meta->setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len);
+ trackInfo->mEncrypted = true;
+ break;
+ }
+ }
+
+ if (!strcmp("V_MPEG4/ISO/AVC", codecID) && codecPrivateSize == 0) {
+ // Attempt to recover from AVC track without codec private data
+ err = synthesizeAVCC(trackInfo, n);
+ if (err != OK) {
+ mTracks.pop();
+ }
+ }
}
}
diff --git a/media/libstagefright/matroska/MatroskaExtractor.h b/media/libstagefright/matroska/MatroskaExtractor.h
index 120ef82..a1d6b00 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.h
+++ b/media/libstagefright/matroska/MatroskaExtractor.h
@@ -55,6 +55,7 @@
struct TrackInfo {
unsigned long mTrackNum;
+ bool mEncrypted;
sp<MetaData> mMeta;
const MatroskaExtractor *mExtractor;
Vector<const mkvparser::CuePoint*> mCuePoints;
@@ -74,6 +75,7 @@
bool mIsWebm;
int64_t mSeekPreRollNs;
+ status_t synthesizeAVCC(TrackInfo *trackInfo, size_t index);
void addTracks();
void findThumbnails();
diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp
index 8e36065..5bb2dcd 100644
--- a/media/ndk/NdkMediaCodec.cpp
+++ b/media/ndk/NdkMediaCodec.cpp
@@ -359,6 +359,15 @@
return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx, timestampNs));
}
+EXPORT
+media_status_t AMediaCodec_setOutputSurface(AMediaCodec *mData, ANativeWindow* window) {
+ sp<Surface> surface = NULL;
+ if (window != NULL) {
+ surface = (Surface*) window;
+ }
+ return translate_error(mData->mCodec->setSurface(surface));
+}
+
//EXPORT
media_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback,
void *userdata) {
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index 0f3f138..8218edd 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -24,7 +24,7 @@
$(call include-path-for, audio-utils) \
$(TOPDIR)frameworks/av/services/audiopolicy/common/include \
$(TOPDIR)frameworks/av/services/audiopolicy/engine/interface \
- $(TOPDIR)frameworks/av/services/audiopolicy/utilities \
+ $(TOPDIR)frameworks/av/services/audiopolicy/utilities
LOCAL_SHARED_LIBRARIES := \
libcutils \
@@ -56,8 +56,7 @@
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= \
- managerdefault/AudioPolicyManager.cpp \
+LOCAL_SRC_FILES:= managerdefault/AudioPolicyManager.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
@@ -75,8 +74,7 @@
parameter-framework.policy \
audio_policy_criteria.conf \
-LOCAL_C_INCLUDES += \
- $(TOPDIR)frameworks/av/services/audiopolicy/engineconfigurable/include
+LOCAL_C_INCLUDES += $(TOPDIR)frameworks/av/services/audiopolicy/engineconfigurable/include
LOCAL_SHARED_LIBRARIES += libaudiopolicyengineconfigurable
@@ -84,7 +82,7 @@
LOCAL_SHARED_LIBRARIES += libaudiopolicyenginedefault
-endif
+endif # ifeq ($(USE_CONFIGURABLE_AUDIO_POLICY), 1)
LOCAL_C_INCLUDES += \
$(TOPDIR)frameworks/av/services/audiopolicy/common/include \
@@ -122,7 +120,7 @@
LOCAL_C_INCLUDES += \
$(TOPDIR)frameworks/av/services/audiopolicy/common/include \
- $(TOPDIR)frameworks/av/services/audiopolicy/engine/interface \
+ $(TOPDIR)frameworks/av/services/audiopolicy/engine/interface
LOCAL_MODULE:= libaudiopolicymanager
diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk
index 429f20a..5c81410 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.mk
+++ b/services/audiopolicy/common/managerdefinitions/Android.mk
@@ -5,7 +5,6 @@
LOCAL_SRC_FILES:= \
src/DeviceDescriptor.cpp \
src/AudioGain.cpp \
- src/StreamDescriptor.cpp \
src/HwModule.cpp \
src/IOProfile.cpp \
src/AudioPort.cpp \
@@ -20,6 +19,7 @@
src/SoundTriggerSession.cpp \
src/SessionRoute.cpp \
src/AudioSourceDescriptor.cpp \
+ src/VolumeCurve.cpp \
src/TypeConverter.cpp \
src/AudioSession.cpp
@@ -35,9 +35,10 @@
$(TOPDIR)frameworks/av/services/audiopolicy/utilities \
ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+
LOCAL_SRC_FILES += src/Serializer.cpp
-LOCAL_STATIC_LIBRARIES := libxml2
+LOCAL_STATIC_LIBRARIES += libxml2
LOCAL_SHARED_LIBRARIES += libicuuc
@@ -46,7 +47,12 @@
$(TOPDIR)external/icu/icu4c/source/common
else
-LOCAL_SRC_FILES += src/ConfigParsingUtils.cpp
+
+LOCAL_SRC_FILES += \
+ src/ConfigParsingUtils.cpp \
+ src/StreamDescriptor.cpp \
+ src/Gains.cpp
+
endif #ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
LOCAL_EXPORT_C_INCLUDE_DIRS := \
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 6959420..bb56ca1 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -28,7 +28,6 @@
#include <AudioPolicyMix.h>
#include <EffectDescriptor.h>
#include <SoundTriggerSession.h>
-#include <StreamDescriptor.h>
#include <SessionRoute.h>
namespace android {
@@ -40,14 +39,24 @@
DeviceVector &availableOutputDevices,
DeviceVector &availableInputDevices,
sp<DeviceDescriptor> &defaultOutputDevices,
- bool &isSpeakerDrcEnabled)
+ bool &isSpeakerDrcEnabled,
+ VolumeCurvesCollection *volumes = nullptr)
: mHwModules(hwModules),
mAvailableOutputDevices(availableOutputDevices),
mAvailableInputDevices(availableInputDevices),
mDefaultOutputDevices(defaultOutputDevices),
+ mVolumeCurves(volumes),
mIsSpeakerDrcEnabled(isSpeakerDrcEnabled)
{}
+ void setVolumes(const VolumeCurvesCollection &volumes)
+ {
+ if (mVolumeCurves != nullptr) {
+ *mVolumeCurves = volumes;
+ mVolumeCurves->setDefaultCurves();
+ }
+ }
+
void setHwModules(const HwModuleCollection &hwModules)
{
mHwModules = hwModules;
@@ -131,6 +140,7 @@
DeviceVector &mAvailableOutputDevices;
DeviceVector &mAvailableInputDevices;
sp<DeviceDescriptor> &mDefaultOutputDevices;
+ VolumeCurvesCollection *mVolumeCurves;
bool &mIsSpeakerDrcEnabled;
};
diff --git a/services/audiopolicy/enginedefault/src/Gains.h b/services/audiopolicy/common/managerdefinitions/include/Gains.h
similarity index 88%
rename from services/audiopolicy/enginedefault/src/Gains.h
rename to services/audiopolicy/common/managerdefinitions/include/Gains.h
index 4bd5edd..34afc8c 100644
--- a/services/audiopolicy/enginedefault/src/Gains.h
+++ b/services/audiopolicy/common/managerdefinitions/include/Gains.h
@@ -29,12 +29,7 @@
class Gains
{
public :
- static float volIndexToAmpl(device_category deviceCategory,
- const StreamDescriptor& streamDesc,
- int indexInUi);
-
- static float volIndexToDb(device_category deviceCategory,
- const StreamDescriptor& streamDesc,
+ static float volIndexToDb(const VolumeCurvePoint *point, int indexMin, int indexMax,
int indexInUi);
// default volume curve
diff --git a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurvesCollection.h b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurvesCollection.h
new file mode 100644
index 0000000..8dc3eda
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurvesCollection.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+#pragma once
+
+#include <system/audio.h>
+#include <Volume.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+class IVolumeCurvesCollection
+{
+public:
+ virtual void clearCurrentVolumeIndex(audio_stream_type_t stream) = 0;
+ virtual void addCurrentVolumeIndex(audio_stream_type_t stream, audio_devices_t device,
+ int index) = 0;
+ virtual bool canBeMuted(audio_stream_type_t stream) = 0;
+ virtual int getVolumeIndexMin(audio_stream_type_t stream) const = 0;
+ virtual int getVolumeIndex(audio_stream_type_t stream, audio_devices_t device) = 0;
+ virtual int getVolumeIndexMax(audio_stream_type_t stream) const = 0;
+ virtual float volIndexToDb(audio_stream_type_t stream, device_category device,
+ int indexInUi) const = 0;
+ virtual status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax) = 0;
+
+ virtual void initializeVolumeCurves(bool /*isSpeakerDrcEnabled*/) {}
+ virtual void switchVolumeCurve(audio_stream_type_t src, audio_stream_type_t dst) = 0;
+ virtual void restoreOriginVolumeCurve(audio_stream_type_t stream)
+ {
+ switchVolumeCurve(stream, stream);
+ }
+
+ virtual status_t dump(int fd) const = 0;
+
+protected:
+ virtual ~IVolumeCurvesCollection() {}
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/Serializer.h b/services/audiopolicy/common/managerdefinitions/include/Serializer.h
index b152dd5..6c22761 100644
--- a/services/audiopolicy/common/managerdefinitions/include/Serializer.h
+++ b/services/audiopolicy/common/managerdefinitions/include/Serializer.h
@@ -202,7 +202,7 @@
typedef VolumeCurve Element;
typedef sp<VolumeCurve> PtrElement;
- typedef VolumeCurveCollection Collection;
+ typedef VolumeCurvesCollection Collection;
typedef void *PtrSerializingCtx;
static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
diff --git a/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
index fbc942c..af178f9 100644
--- a/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
@@ -16,7 +16,7 @@
#pragma once
-#include <Volume.h>
+#include "IVolumeCurvesCollection.h"
#include <utils/KeyedVector.h>
#include <utils/StrongPointer.h>
#include <utils/SortedVector.h>
@@ -58,28 +58,43 @@
/**
* stream descriptors collection for volume control
*/
-class StreamDescriptorCollection : public DefaultKeyedVector<audio_stream_type_t, StreamDescriptor>
+class StreamDescriptorCollection : public DefaultKeyedVector<audio_stream_type_t, StreamDescriptor>,
+ public IVolumeCurvesCollection
{
public:
StreamDescriptorCollection();
- void clearCurrentVolumeIndex(audio_stream_type_t stream);
- void addCurrentVolumeIndex(audio_stream_type_t stream, audio_devices_t device, int index);
+ virtual void clearCurrentVolumeIndex(audio_stream_type_t stream);
+ virtual void addCurrentVolumeIndex(audio_stream_type_t stream, audio_devices_t device,
+ int index);
+ virtual bool canBeMuted(audio_stream_type_t stream);
+ virtual int getVolumeIndexMin(audio_stream_type_t stream) const
+ {
+ return valueFor(stream).getVolumeIndexMin();
+ }
+ virtual int getVolumeIndex(audio_stream_type_t stream, audio_devices_t device)
+ {
+ return valueFor(stream).getVolumeIndex(device);
+ }
+ virtual int getVolumeIndexMax(audio_stream_type_t stream) const
+ {
+ return valueFor(stream).getVolumeIndexMax();
+ }
+ virtual float volIndexToDb(audio_stream_type_t stream, device_category device,
+ int indexInUi) const;
+ virtual status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax);
+ virtual void initializeVolumeCurves(bool isSpeakerDrcEnabled);
+ virtual void switchVolumeCurve(audio_stream_type_t streamSrc, audio_stream_type_t streamDst);
- bool canBeMuted(audio_stream_type_t stream);
+ virtual status_t dump(int fd) const;
- status_t dump(int fd) const;
-
- void setVolumeCurvePoint(audio_stream_type_t stream,
- device_category deviceCategory,
+private:
+ void setVolumeCurvePoint(audio_stream_type_t stream, device_category deviceCategory,
const VolumeCurvePoint *point);
-
const VolumeCurvePoint *getVolumeCurvePoint(audio_stream_type_t stream,
device_category deviceCategory) const;
-
void setVolumeIndexMin(audio_stream_type_t stream,int volIndexMin);
void setVolumeIndexMax(audio_stream_type_t stream,int volIndexMax);
-
};
}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
index cccf1c8..e72baf8 100644
--- a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
+++ b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
@@ -16,12 +16,13 @@
#pragma once
-#include <Volume.h>
+#include "IVolumeCurvesCollection.h"
+#include <policy.h>
#include <hardware/audio.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
-#include <utils/Errors.h>
-#include <utils/Vector.h>
+#include <utils/SortedVector.h>
+#include <utils/KeyedVector.h>
#include <system/audio.h>
#include <cutils/config_utils.h>
#include <string>
@@ -29,26 +30,213 @@
namespace android {
-typedef std::pair<uint32_t, uint32_t> CurvePoint;
-typedef Vector<CurvePoint> CurvePoints;
+struct CurvePoint
+{
+ CurvePoint() {}
+ CurvePoint(int index, int attenuationInMb) :
+ mIndex(index), mAttenuationInMb(attenuationInMb) {}
+ uint32_t mIndex;
+ int mAttenuationInMb;
+};
+inline bool operator< (const CurvePoint &lhs, const CurvePoint &rhs)
+{
+ return lhs.mIndex < rhs.mIndex;
+}
+
+// A volume curve for a given use case and device cateory
+// It contains of list of points of this cuive expressing the atteunation in Millibels for
+// a given volume index from 0 to 100
class VolumeCurve : public RefBase
{
public:
- void setStreamType(audio_stream_type_t streamType) { mStreamType = streamType; }
+ VolumeCurve(device_category device, audio_stream_type_t stream) :
+ mDeviceCategory(device), mStreamType(stream) {}
+
+ device_category getDeviceCategory() const { return mDeviceCategory; }
audio_stream_type_t getStreamType() const { return mStreamType; }
- void setDeviceCategory(device_category devCat) { mDeviceCategory = devCat; }
- device_category getDeviceCategory() const { return mDeviceCategory; }
+ void add(const CurvePoint &point) { mCurvePoints.add(point); }
- void setCurvePoints(const CurvePoints &points) { mCurvePoints = points; }
+ float volIndexToDb(int indexInUi, int volIndexMin, int volIndexMax) const;
+
+ void dump(int fd) const;
private:
- CurvePoints mCurvePoints;
+ SortedVector<CurvePoint> mCurvePoints;
device_category mDeviceCategory;
audio_stream_type_t mStreamType;
};
-typedef Vector<sp<VolumeCurve> > VolumeCurveCollection;
+// Volume Curves for a given use case indexed by device category
+class VolumeCurvesForStream : public KeyedVector<device_category, sp<VolumeCurve> >
+{
+public:
+ VolumeCurvesForStream() : mIndexMin(0), mIndexMax(1), mCanBeMuted(true)
+ {
+ mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0);
+ }
+
+ sp<VolumeCurve> getCurvesFor(device_category device) const
+ {
+ if (indexOfKey(device) < 0) {
+ return 0;
+ }
+ return valueFor(device);
+ }
+
+ int getVolumeIndex(audio_devices_t device) const
+ {
+ device = Volume::getDeviceForVolume(device);
+ // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT
+ if (mIndexCur.indexOfKey(device) < 0) {
+ device = AUDIO_DEVICE_OUT_DEFAULT;
+ }
+ return mIndexCur.valueFor(device);
+ }
+
+ bool canBeMuted() const { return mCanBeMuted; }
+ void clearCurrentVolumeIndex() { mIndexCur.clear(); }
+ void addCurrentVolumeIndex(audio_devices_t device, int index) { mIndexCur.add(device, index); }
+
+ void setVolumeIndexMin(int volIndexMin) { mIndexMin = volIndexMin; }
+ int getVolumeIndexMin() const { return mIndexMin; }
+
+ void setVolumeIndexMax(int volIndexMax) { mIndexMax = volIndexMax; }
+ int getVolumeIndexMax() const { return mIndexMax; }
+
+ const sp<VolumeCurve> getOriginVolumeCurve(device_category deviceCategory) const
+ {
+ ALOG_ASSERT(mOriginVolumeCurves.indexOfKey(deviceCategory) >= 0, "Invalid device category");
+ return mOriginVolumeCurves.valueFor(deviceCategory);
+ }
+ void setVolumeCurve(device_category deviceCategory, const sp<VolumeCurve> &volumeCurve)
+ {
+ ALOG_ASSERT(indexOfKey(deviceCategory) >= 0, "Invalid device category for Volume Curve");
+ replaceValueFor(deviceCategory, volumeCurve);
+ }
+
+ ssize_t add(const sp<VolumeCurve> &volumeCurve)
+ {
+ device_category deviceCategory = volumeCurve->getDeviceCategory();
+ ssize_t index = indexOfKey(deviceCategory);
+ if (index < 0) {
+ // Keep track of original Volume Curves per device category in order to switch curves.
+ mOriginVolumeCurves.add(deviceCategory, volumeCurve);
+ return KeyedVector::add(deviceCategory, volumeCurve);
+ }
+ return index;
+ }
+
+ float volIndexToDb(device_category deviceCat, int indexInUi) const
+ {
+ return getCurvesFor(deviceCat)->volIndexToDb(indexInUi, mIndexMin, mIndexMax);
+ }
+
+ void dump(int fd, int spaces, bool curvePoints = false) const;
+
+private:
+ KeyedVector<device_category, sp<VolumeCurve> > mOriginVolumeCurves;
+ KeyedVector<audio_devices_t, int> mIndexCur; /**< current volume index per device. */
+ int mIndexMin; /**< min volume index. */
+ int mIndexMax; /**< max volume index. */
+ bool mCanBeMuted; /**< true is the stream can be muted. */
+};
+
+// Collection of Volume Curves indexed by use case
+class VolumeCurvesCollection : public KeyedVector<audio_stream_type_t, VolumeCurvesForStream>,
+ public IVolumeCurvesCollection
+{
+public:
+ VolumeCurvesCollection()
+ {
+ // Create an empty collection of curves even for CNT stream (used for default curves)
+ for (ssize_t i = 0 ; i <= AUDIO_STREAM_CNT; i++) {
+ audio_stream_type_t stream = static_cast<audio_stream_type_t>(i);
+ KeyedVector::add(stream, VolumeCurvesForStream());
+ }
+ }
+
+ // Once XML has been parsed, must be call first to sanity check table and initialize indexes
+ virtual status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax)
+ {
+ editValueAt(stream).setVolumeIndexMin(indexMin);
+ editValueAt(stream).setVolumeIndexMax(indexMax);
+ return NO_ERROR;
+ }
+ virtual void clearCurrentVolumeIndex(audio_stream_type_t stream)
+ {
+ editCurvesFor(stream).clearCurrentVolumeIndex();
+ }
+ virtual void addCurrentVolumeIndex(audio_stream_type_t stream, audio_devices_t device, int index)
+ {
+ editCurvesFor(stream).addCurrentVolumeIndex(device, index);
+ }
+ virtual bool canBeMuted(audio_stream_type_t stream) { return getCurvesFor(stream).canBeMuted(); }
+
+ virtual int getVolumeIndexMin(audio_stream_type_t stream) const
+ {
+ return getCurvesFor(stream).getVolumeIndexMin();
+ }
+ virtual int getVolumeIndexMax(audio_stream_type_t stream) const
+ {
+ return getCurvesFor(stream).getVolumeIndexMax();
+ }
+ virtual int getVolumeIndex(audio_stream_type_t stream, audio_devices_t device)
+ {
+ return getCurvesFor(stream).getVolumeIndex(device);
+ }
+ virtual void switchVolumeCurve(audio_stream_type_t streamSrc, audio_stream_type_t streamDst)
+ {
+ const VolumeCurvesForStream &sourceCurves = getCurvesFor(streamSrc);
+ VolumeCurvesForStream &dstCurves = editCurvesFor(streamDst);
+ ALOG_ASSERT(sourceCurves.size() == dstCurves.size(), "device category not aligned");
+ for (size_t index = 0; index < sourceCurves.size(); index++) {
+ device_category cat = sourceCurves.keyAt(index);
+ dstCurves.setVolumeCurve(cat, sourceCurves.getOriginVolumeCurve(cat));
+ }
+ }
+ virtual float volIndexToDb(audio_stream_type_t stream, device_category cat, int indexInUi) const
+ {
+ return getCurvesFor(stream).volIndexToDb(cat, indexInUi);
+ }
+
+ virtual status_t dump(int fd) const;
+
+ ssize_t add(const sp<VolumeCurve> &volumeCurve)
+ {
+ audio_stream_type_t streamType = volumeCurve->getStreamType();
+ return editCurvesFor(streamType).add(volumeCurve);
+ }
+ VolumeCurvesForStream &editCurvesFor(audio_stream_type_t stream)
+ {
+ ALOG_ASSERT(indexOfKey(stream) >= 0, "Invalid stream type for Volume Curve");
+ return editValueAt(stream);
+ }
+ const VolumeCurvesForStream &getCurvesFor(audio_stream_type_t stream) const
+ {
+ ALOG_ASSERT(indexOfKey(stream) >= 0, "Invalid stream type for Volume Curve");
+ return valueFor(stream);
+ }
+ void setDefaultCurves()
+ {
+ for (size_t i = 0 ; i < AUDIO_STREAM_CNT; i++) {
+ audio_stream_type_t stream = static_cast<audio_stream_type_t>(i);
+ ALOG_ASSERT(indexOfKey(stream) >= 0, "No Default volume table found!");
+
+ VolumeCurvesForStream &curvesForStream = editValueAt(stream);
+ // Sanity check on All device categories
+ for (int i = 0; i < DEVICE_CATEGORY_CNT; i++) {
+ device_category cat = (device_category)i;
+ if (curvesForStream.getCurvesFor(cat) == 0) {
+ ALOG_ASSERT(valueAt(AUDIO_STREAM_CNT).getCurvesFor(cat) != 0,
+ "No Default volume table found for device category %d", cat);
+ ALOGW("Switching to default table for stream %d category %d", stream, cat);
+ curvesForStream.add(valueAt(AUDIO_STREAM_CNT).getCurvesFor(cat));
+ }
+ }
+ }
+ }
+};
}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp
index fc7b0cc..e454941 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp
@@ -25,7 +25,6 @@
#endif
#include "AudioGain.h"
-#include "StreamDescriptor.h"
#include <utils/Log.h>
#include <utils/String8.h>
diff --git a/services/audiopolicy/enginedefault/src/Gains.cpp b/services/audiopolicy/common/managerdefinitions/src/Gains.cpp
similarity index 91%
rename from services/audiopolicy/enginedefault/src/Gains.cpp
rename to services/audiopolicy/common/managerdefinitions/src/Gains.cpp
index 0aace36..e3fc9a8 100644
--- a/services/audiopolicy/enginedefault/src/Gains.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Gains.cpp
@@ -197,17 +197,11 @@
};
//static
-float Gains::volIndexToDb(device_category deviceCategory,
- const StreamDescriptor& streamDesc,
- int indexInUi)
+float Gains::volIndexToDb(const VolumeCurvePoint *curve, int indexMin, int indexMax, int indexInUi)
{
- const VolumeCurvePoint *curve = streamDesc.getVolumeCurvePoint(deviceCategory);
-
// the volume index in the UI is relative to the min and max volume indices for this stream type
- int nbSteps = 1 + curve[Volume::VOLMAX].mIndex -
- curve[Volume::VOLMIN].mIndex;
- int volIdx = (nbSteps * (indexInUi - streamDesc.getVolumeIndexMin())) /
- (streamDesc.getVolumeIndexMax() - streamDesc.getVolumeIndexMin());
+ int nbSteps = 1 + curve[Volume::VOLMAX].mIndex - curve[Volume::VOLMIN].mIndex;
+ int volIdx = (nbSteps * (indexInUi - indexMin)) / (indexMax - indexMin);
// find what part of the curve this index volume belongs to, or if it's out of bounds
int segment = 0;
@@ -241,15 +235,4 @@
return decibels;
}
-
-//static
-float Gains::volIndexToAmpl(device_category deviceCategory,
- const StreamDescriptor& streamDesc,
- int indexInUi)
-{
- return Volume::DbToAmpl(volIndexToDb(deviceCategory, streamDesc, indexInUi));
-}
-
-
-
}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 77824df..48e96a1 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -60,13 +60,14 @@
root = root->next;
continue;
}
- if (!xmlStrcmp(root->name, (const xmlChar *)Trait::collectionTag)) {
- root = root->xmlChildrenNode;
+ const xmlNode *child = root;
+ if (!xmlStrcmp(child->name, (const xmlChar *)Trait::collectionTag)) {
+ child = child->xmlChildrenNode;
}
- while (root != NULL) {
- if (!xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+ while (child != NULL) {
+ if (!xmlStrcmp(child->name, (const xmlChar *)Trait::tag)) {
typename Trait::PtrElement element;
- status_t status = Trait::deserialize(doc, root, element, serializingContext);
+ status_t status = Trait::deserialize(doc, child, element, serializingContext);
if (status != NO_ERROR) {
return status;
}
@@ -75,12 +76,14 @@
Trait::collectionTag);
}
}
- root = root->next;
+ child = child->next;
}
- return NO_ERROR;
+ if (!xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+ return NO_ERROR;
+ }
+ root = root->next;
}
- ALOGV("%s: No %s collection found", __FUNCTION__, Trait::collectionTag);
- return BAD_VALUE;
+ return NO_ERROR;
}
const char *const AudioGainTraits::tag = "gain";
@@ -513,7 +516,8 @@
deviceCategoryLiteral.c_str());
return BAD_VALUE;
}
- CurvePoints points;
+ element = new Element(deviceCategory, streamType);
+
const xmlNode *child = root->xmlChildrenNode;
while (child != NULL) {
if (!xmlStrcmp(child->name, (const xmlChar *)volumePointTag)) {
@@ -529,15 +533,11 @@
(const char*)pointDefinition);
return BAD_VALUE;
}
- points.add(std::make_pair(point[0], point[1]));
+ element->add(CurvePoint(point[0], point[1]));
xmlFree(pointDefinition);
}
child = child->next;
}
- element = new Element();
- element->setDeviceCategory(deviceCategory);
- element->setStreamType(streamType);
- element->setCurvePoints(points);
return NO_ERROR;
}
@@ -592,7 +592,8 @@
// deserialize volume section
VolumeTraits::Collection volumes;
- deserializeCollection<VolumeTraits>(doc, cur, volumes, NULL);
+ deserializeCollection<VolumeTraits>(doc, cur, volumes, &config);
+ config.setVolumes(volumes);
// Global Configuration
GlobalConfigTraits::deserialize(cur, config);
diff --git a/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
index 12c7930..8388a50 100644
--- a/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
@@ -25,6 +25,7 @@
#endif
#include "StreamDescriptor.h"
+#include "Gains.h"
#include <utils/Log.h>
#include <utils/String8.h>
@@ -143,6 +144,65 @@
return editValueAt(stream).setVolumeIndexMax(volIndexMax);
}
+float StreamDescriptorCollection::volIndexToDb(audio_stream_type_t stream, device_category category,
+ int indexInUi) const
+{
+ const StreamDescriptor &streamDesc = valueAt(stream);
+ return Gains::volIndexToDb(streamDesc.getVolumeCurvePoint(category),
+ streamDesc.getVolumeIndexMin(), streamDesc.getVolumeIndexMax(),
+ indexInUi);
+}
+
+status_t StreamDescriptorCollection::initStreamVolume(audio_stream_type_t stream,
+ int indexMin, int indexMax)
+{
+ ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
+ if (indexMin < 0 || indexMin >= indexMax) {
+ ALOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d",
+ stream , indexMin, indexMax);
+ return BAD_VALUE;
+ }
+ setVolumeIndexMin(stream, indexMin);
+ setVolumeIndexMax(stream, indexMax);
+ return NO_ERROR;
+}
+
+void StreamDescriptorCollection::initializeVolumeCurves(bool isSpeakerDrcEnabled)
+{
+ for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
+ for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
+ setVolumeCurvePoint(static_cast<audio_stream_type_t>(i),
+ static_cast<device_category>(j),
+ Gains::sVolumeProfiles[i][j]);
+ }
+ }
+
+ // Check availability of DRC on speaker path: if available, override some of the speaker curves
+ if (isSpeakerDrcEnabled) {
+ setVolumeCurvePoint(AUDIO_STREAM_SYSTEM, DEVICE_CATEGORY_SPEAKER,
+ Gains::sDefaultSystemVolumeCurveDrc);
+ setVolumeCurvePoint(AUDIO_STREAM_RING, DEVICE_CATEGORY_SPEAKER,
+ Gains::sSpeakerSonificationVolumeCurveDrc);
+ setVolumeCurvePoint(AUDIO_STREAM_ALARM, DEVICE_CATEGORY_SPEAKER,
+ Gains::sSpeakerSonificationVolumeCurveDrc);
+ setVolumeCurvePoint(AUDIO_STREAM_NOTIFICATION, DEVICE_CATEGORY_SPEAKER,
+ Gains::sSpeakerSonificationVolumeCurveDrc);
+ setVolumeCurvePoint(AUDIO_STREAM_MUSIC, DEVICE_CATEGORY_SPEAKER,
+ Gains::sSpeakerMediaVolumeCurveDrc);
+ setVolumeCurvePoint(AUDIO_STREAM_ACCESSIBILITY, DEVICE_CATEGORY_SPEAKER,
+ Gains::sSpeakerMediaVolumeCurveDrc);
+ }
+}
+
+void StreamDescriptorCollection::switchVolumeCurve(audio_stream_type_t streamSrc,
+ audio_stream_type_t streamDst)
+{
+ for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
+ setVolumeCurvePoint(streamDst, static_cast<device_category>(j),
+ Gains::sVolumeProfiles[streamSrc][j]);
+ }
+}
+
status_t StreamDescriptorCollection::dump(int fd) const
{
const size_t SIZE = 256;
diff --git a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
index 74d8809..a2975b9 100644
--- a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
@@ -219,7 +219,9 @@
MAKE_STRING_FROM_ENUM(AUDIO_STREAM_TTS),
MAKE_STRING_FROM_ENUM(AUDIO_STREAM_ACCESSIBILITY),
MAKE_STRING_FROM_ENUM(AUDIO_STREAM_REROUTING),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_PATCH)
+ MAKE_STRING_FROM_ENUM(AUDIO_STREAM_PATCH),
+
+ MAKE_STRING_FROM_ENUM(AUDIO_STREAM_CNT) // Required to manage default volume tables
};
template<>
diff --git a/services/audiopolicy/common/managerdefinitions/src/VolumeCurve.cpp b/services/audiopolicy/common/managerdefinitions/src/VolumeCurve.cpp
new file mode 100644
index 0000000..ab2b51f
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/VolumeCurve.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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.
+ */
+
+#define LOG_TAG "APM::VolumeCurve"
+//#define LOG_NDEBUG 0
+
+#include "VolumeCurve.h"
+#include "TypeConverter.h"
+
+namespace android {
+
+float VolumeCurve::volIndexToDb(int indexInUi, int volIndexMin, int volIndexMax) const
+{
+ ALOG_ASSERT(!mCurvePoints.isEmpty(), "Invalid volume curve");
+
+ size_t nbCurvePoints = mCurvePoints.size();
+ // the volume index in the UI is relative to the min and max volume indices for this stream
+ int nbSteps = 1 + mCurvePoints[nbCurvePoints - 1].mIndex - mCurvePoints[0].mIndex;
+ int volIdx = (nbSteps * (indexInUi - volIndexMin)) / (volIndexMax - volIndexMin);
+
+ // Where would this volume index been inserted in the curve point
+ size_t indexInUiPosition = mCurvePoints.orderOf(CurvePoint(volIdx, 0));
+ if (indexInUiPosition >= nbCurvePoints) {
+ return 0.0f; // out of bounds
+ }
+ if (indexInUiPosition == 0) {
+ if (indexInUiPosition != mCurvePoints[0].mIndex) {
+ return VOLUME_MIN_DB; // out of bounds
+ }
+ return mCurvePoints[0].mAttenuationInMb / 100.0f;
+ }
+ // linear interpolation in the attenuation table in dB
+ float decibels = (mCurvePoints[indexInUiPosition - 1].mAttenuationInMb / 100.0f) +
+ ((float)(volIdx - mCurvePoints[indexInUiPosition - 1].mIndex)) *
+ ( ((mCurvePoints[indexInUiPosition].mAttenuationInMb / 100.0f) -
+ (mCurvePoints[indexInUiPosition - 1].mAttenuationInMb / 100.0f)) /
+ ((float)(mCurvePoints[indexInUiPosition].mIndex -
+ mCurvePoints[indexInUiPosition - 1].mIndex)) );
+
+ ALOGV("VOLUME mDeviceCategory %d, mStreamType %d vol index=[%d %d %d], dB=[%.1f %.1f %.1f]",
+ mDeviceCategory, mStreamType,
+ mCurvePoints[indexInUiPosition - 1].mIndex, volIdx,
+ mCurvePoints[indexInUiPosition].mIndex,
+ ((float)mCurvePoints[indexInUiPosition - 1].mAttenuationInMb / 100.0f), decibels,
+ ((float)mCurvePoints[indexInUiPosition].mAttenuationInMb / 100.0f));
+
+ return decibels;
+}
+
+void VolumeCurve::dump(int fd) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ snprintf(buffer, SIZE, " {");
+ result.append(buffer);
+ for (size_t i = 0; i < mCurvePoints.size(); i++) {
+ snprintf(buffer, SIZE, "(%3d, %5d)",
+ mCurvePoints[i].mIndex, mCurvePoints[i].mAttenuationInMb);
+ result.append(buffer);
+ result.append(i == (mCurvePoints.size() - 1) ? " }\n" : ", ");
+ }
+ write(fd, result.string(), result.size());
+}
+
+void VolumeCurvesForStream::dump(int fd, int spaces = 0, bool curvePoints) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ if (!curvePoints) {
+ snprintf(buffer, SIZE, "%s %02d %02d ",
+ mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
+ result.append(buffer);
+ for (size_t i = 0; i < mIndexCur.size(); i++) {
+ snprintf(buffer, SIZE, "%04x : %02d, ", mIndexCur.keyAt(i), mIndexCur.valueAt(i));
+ result.append(buffer);
+ }
+ result.append("\n");
+ write(fd, result.string(), result.size());
+ return;
+ }
+
+ for (size_t i = 0; i < size(); i++) {
+ std::string deviceCatLiteral;
+ DeviceCategoryConverter::toString(keyAt(i), deviceCatLiteral);
+ snprintf(buffer, SIZE, "%*s %s :",
+ spaces, "", deviceCatLiteral.c_str());
+ write(fd, buffer, strlen(buffer));
+ valueAt(i)->dump(fd);
+ }
+ result.append("\n");
+ write(fd, result.string(), result.size());
+}
+
+status_t VolumeCurvesCollection::dump(int fd) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+
+ snprintf(buffer, SIZE, "\nStreams dump:\n");
+ write(fd, buffer, strlen(buffer));
+ snprintf(buffer, SIZE,
+ " Stream Can be muted Index Min Index Max Index Cur [device : index]...\n");
+ write(fd, buffer, strlen(buffer));
+ for (size_t i = 0; i < size(); i++) {
+ snprintf(buffer, SIZE, " %02zu ", i);
+ write(fd, buffer, strlen(buffer));
+ valueAt(i).dump(fd);
+ }
+ snprintf(buffer, SIZE, "\nVolume Curves for Use Cases (aka Stream types) dump:\n");
+ write(fd, buffer, strlen(buffer));
+ for (size_t i = 0; i < size(); i++) {
+ std::string streamTypeLiteral;
+ StreamTypeConverter::toString(keyAt(i), streamTypeLiteral);
+ snprintf(buffer, SIZE,
+ " %s (%02zu): Curve points for device category (index, attenuation in millibel)\n",
+ streamTypeLiteral.c_str(), i);
+ write(fd, buffer, strlen(buffer));
+ valueAt(i).dump(fd, 2, true);
+ }
+
+ return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/config/audio_policy_configuration.xml b/services/audiopolicy/config/audio_policy_configuration.xml
index dccc3a8..e17ebc6 100644
--- a/services/audiopolicy/config/audio_policy_configuration.xml
+++ b/services/audiopolicy/config/audio_policy_configuration.xml
@@ -206,25 +206,10 @@
</modules>
<!-- End of Modules section -->
- <!-- Volume section defines a volume curve for a given use case and device category.
- It contains a list of points of this curve expressing the attenuation in Millibels for a given
- volume index from 0 to 100.
- <volume stream=”AUDIO_STREAM_MUSIC” deviceCategory=””>
- <point>0, -9600</point>
- <point>100, 0</point>
- </volume>
- -->
- <volumes>
- <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER">
- <point>0,-9600</point>
- <point>100,0</point>
- </volume>
- <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_EARPIECE">
- <point>0,-9800</point>
- <point>50,-1000</point>
- <point>100,0</point>
- </volume>
- </volumes>
+ <!-- Volume section -->
+
+ <xi:include href="audio_policy_volumes.xml"/>
+ <xi:include href="default_volume_tables.xml"/>
<!-- End of Volume section -->
diff --git a/services/audiopolicy/config/audio_policy_volumes.xml b/services/audiopolicy/config/audio_policy_volumes.xml
new file mode 100644
index 0000000..4373740
--- /dev/null
+++ b/services/audiopolicy/config/audio_policy_volumes.xml
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2015 The Android Open Source 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.
+-->
+<!-- Volume section defines a volume curve for a given use case and device category.
+It contains a list of points of this curve expressing the attenuation in Millibels for a given
+volume index from 0 to 100.
+<volume stream=”AUDIO_STREAM_MUSIC” deviceCategory=””>
+<point>0,-9600</point>
+<point>100,0</point>
+</volume>
+-->
+
+<volumes>
+ <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-2400</point>
+ <point>33,-1600</point>
+ <point>66,-800</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>0,-2400</point>
+ <point>33,-1600</point>
+ <point>66,-800</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+ <point>1,-5800</point>
+ <point>20,-4000</point>
+ <point>60,-1700</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>1,-3000</point>
+ <point>33,-2600</point>
+ <point>66,-2200</point>
+ <point>100,-1800</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>1,-2400</point>
+ <point>33,-1800</point>
+ <point>66,-1200</point>
+ <point>100,-600</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>1,-2400</point>
+ <point>33,-1800</point>
+ <point>66,-1200</point>
+ <point>100,-600</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>1,-2970</point>
+ <point>33,-2010</point>
+ <point>66,-1020</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>1,-5800</point>
+ <point>20,-4000</point>
+ <point>60,-1700</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>1,-5800</point>
+ <point>20,-4000</point>
+ <point>60,-1700</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+ <point>1,-5800</point>
+ <point>20,-4000</point>
+ <point>60,-1700</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_ALARM" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>1,-2970</point>
+ <point>33,-2010</point>
+ <point>66,-1020</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_NOTIFICATION" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>1,-2970</point>
+ <point>33,-2010</point>
+ <point>66,-1020</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_BLUETOOTH_SCO" deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_BLUETOOTH_SCO" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-2400</point>
+ <point>33,-1600</point>
+ <point>66,-800</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_BLUETOOTH_SCO" deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_BLUETOOTH_SCO" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+ <point>1,-5800</point>
+ <point>33,-4000</point>
+ <point>66,-1700</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_ENFORCED_AUDIBLE" deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>1,-3000</point>
+ <point>33,-2600</point>
+ <point>66,-2200</point>
+ <point>100,-1800</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_ENFORCED_AUDIBLE" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>1,-2400</point>
+ <point>33,-1800</point>
+ <point>66,-1200</point>
+ <point>100,-600</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_ENFORCED_AUDIBLE" deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>1,-2400</point>
+ <point>33,-1800</point>
+ <point>66,-1200</point>
+ <point>100,-600</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_DTMF" deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>1,-3000</point>
+ <point>33,-2600</point>
+ <point>66,-2200</point>
+ <point>100,-1800</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_DTMF" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>1,-2400</point>
+ <point>33,-1800</point>
+ <point>66,-1200</point>
+ <point>100,-600</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_DTMF" deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>1,-2400</point>
+ <point>33,-1800</point>
+ <point>66,-1200</point>
+ <point>100,-600</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_TTS" deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,-9600</point>
+ <point>100,-9600</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_TTS" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,0</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_TTS" deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>0,-9600</point>
+ <point>100,-9600</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_TTS" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+ <point>0,-9600</point>
+ <point>100,-9600</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_ACCESSIBILITY" deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>1,-5800</point>
+ <point>33,-4000</point>
+ <point>66,-1700</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_ACCESSIBILITY" deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>1,-5800</point>
+ <point>33,-4000</point>
+ <point>66,-1700</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_ACCESSIBILITY" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+ <point>1,-5800</point>
+ <point>33,-4000</point>
+ <point>66,-1700</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,0</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,0</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>0,0</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+ <point>0,0</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_PATCH" deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,0</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_PATCH" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,0</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_PATCH" deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>0,0</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_PATCH" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+ <point>0,0</point>
+ <point>100,0</point>
+ </volume>
+</volumes>
+
diff --git a/services/audiopolicy/config/default_volume_tables.xml b/services/audiopolicy/config/default_volume_tables.xml
new file mode 100644
index 0000000..f7a8016
--- /dev/null
+++ b/services/audiopolicy/config/default_volume_tables.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2015 The Android Open Source 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.
+-->
+<!-- Default Volume Tables included by Audio Policy Configuration file -->
+<!-- Full Default Volume table for all device category -->
+<volumes>
+ <volume stream="AUDIO_STREAM_CNT" deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <!--Default Volume Curve -->
+ <point>1,-4950</point>
+ <point>33,-3350</point>
+ <point>66,-1700</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_CNT" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <!-- Default is Speaker Media Volume Curve -->
+ <point>1,-5600</point>
+ <point>20,-3400</point>
+ <point>60,-1100</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_CNT" deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <!--Default Volume Curve -->
+ <point>1,-4950</point>
+ <point>33,-3350</point>
+ <point>66,-1700</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_CNT" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+ <!-- Default is Ext Media System Volume Curve -->
+ <point>1,-5800</point>
+ <point>20,-4000</point>
+ <point>60,-2100</point>
+ <point>100,-1000</point>
+ </volume>
+</volumes>
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
index 3a3bdbf..567ff9e 100755
--- a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
+++ b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
@@ -133,37 +133,6 @@
virtual status_t setDeviceConnectionState(const android::sp<android::DeviceDescriptor> devDesc,
audio_policy_dev_state_t state) = 0;
- /**
- * Translate a volume index given by the UI to an amplification value in dB for a stream type
- * and a device category.
- *
- * @param[in] deviceCategory for which the conversion is requested.
- * @param[in] stream type for which the conversion is requested.
- * @param[in] indexInUi index received from the UI to be translated.
- *
- * @return amplification value in dB matching the UI index for this given device and stream.
- */
- virtual float volIndexToDb(device_category deviceCategory, audio_stream_type_t stream,
- int indexInUi) = 0;
-
- /**
- * Initialize the min / max index of volume applicable for a given stream type. These indexes
- * will be used upon conversion of UI index to volume amplification.
- *
- * @param[in] stream type for which the indexes need to be set
- * @param[in] indexMin Minimum index allowed for this stream.
- * @param[in] indexMax Maximum index allowed for this stream.
- */
- virtual status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax) = 0;
-
- /**
- * Initialize volume curves for each strategy and device category
- *
- * @param[in] isSpeakerDrcEnabled true on devices that use DRC on the DEVICE_CATEGORY_SPEAKER
- path to boost soft sounds, used to adjust volume curves accordingly
- */
- virtual void initializeVolumeCurves(bool isSpeakerDrcEnabled) = 0;
-
protected:
virtual ~AudioPolicyManagerInterface() {}
};
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h b/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h
index 6d43df2..846fa48 100755
--- a/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h
+++ b/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h
@@ -16,6 +16,7 @@
#pragma once
+#include <IVolumeCurvesCollection.h>
#include <AudioGain.h>
#include <AudioPort.h>
#include <AudioPatch.h>
@@ -25,7 +26,6 @@
#include <AudioOutputDescriptor.h>
#include <AudioPolicyMix.h>
#include <SoundTriggerSession.h>
-#include <StreamDescriptor.h>
namespace android {
@@ -51,7 +51,7 @@
virtual const DeviceVector &getAvailableInputDevices() const = 0;
- virtual StreamDescriptorCollection &getStreamDescriptors() = 0;
+ virtual IVolumeCurvesCollection &getVolumeCurves() = 0;
virtual const sp<DeviceDescriptor> &getDefaultOutputDevice() const = 0;
diff --git a/services/audiopolicy/engineconfigurable/Android.mk b/services/audiopolicy/engineconfigurable/Android.mk
index 06d00ca..e6b5f85 100755
--- a/services/audiopolicy/engineconfigurable/Android.mk
+++ b/services/audiopolicy/engineconfigurable/Android.mk
@@ -42,10 +42,7 @@
libmedia_helper \
libaudiopolicypfwwrapper \
libaudiopolicycomponents \
-
-ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
-LOCAL_STATIC_LIBRARIES += libxml2
-endif
+ libxml2
LOCAL_SHARED_LIBRARIES := \
libcutils \
diff --git a/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h b/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
index 43d441e..759d0c9 100755
--- a/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
+++ b/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
@@ -111,13 +111,12 @@
* Set the strategy to be followed by a stream.
*
* @param[in] stream: name of the stream for which the strategy to use has to be set
- * @param[in] strategy to follow for the given stream.
+ * @param[in] volumeProfile to follow for the given stream.
*
- * @return true if the strategy were set correclty for this stream, false otherwise.
+ * @return true if the profile was set correclty for this stream, false otherwise.
*/
virtual bool setVolumeProfileForStream(const audio_stream_type_t &stream,
- device_category category,
- const VolumeCurvePoints &points) = 0;
+ const audio_stream_type_t &volumeProfile) = 0;
/**
* Set the strategy to be followed by a usage.
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/example/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/example/Android.mk
index 55da35e..e15e418 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/example/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/example/Android.mk
@@ -61,14 +61,6 @@
LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
-include $(CLEAR_VARS)
-LOCAL_MODULE := PolicySubsystem-Volume.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
######### Policy PFW Settings #########
include $(CLEAR_VARS)
LOCAL_MODULE := parameter-framework.policy
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/PolicyConfigurableDomains.xml b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/PolicyConfigurableDomains.xml
index 8cb0723..4ac466e 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/PolicyConfigurableDomains.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/PolicyConfigurableDomains.xml
@@ -9508,1544 +9508,56 @@
</Configuration>
</Configurations>
<ConfigurableElements>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation"/>
+ <ConfigurableElement Path="/Policy/policy/streams/voice_call/applicable_volume_profile/volume_profile"/>
+ <ConfigurableElement Path="/Policy/policy/streams/system/applicable_volume_profile/volume_profile"/>
+ <ConfigurableElement Path="/Policy/policy/streams/ring/applicable_volume_profile/volume_profile"/>
+ <ConfigurableElement Path="/Policy/policy/streams/music/applicable_volume_profile/volume_profile"/>
+ <ConfigurableElement Path="/Policy/policy/streams/alarm/applicable_volume_profile/volume_profile"/>
+ <ConfigurableElement Path="/Policy/policy/streams/notification/applicable_volume_profile/volume_profile"/>
+ <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/applicable_volume_profile/volume_profile"/>
+ <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/applicable_volume_profile/volume_profile"/>
+ <ConfigurableElement Path="/Policy/policy/streams/tts/applicable_volume_profile/volume_profile"/>
+ <ConfigurableElement Path="/Policy/policy/streams/accessibility/applicable_volume_profile/volume_profile"/>
+ <ConfigurableElement Path="/Policy/policy/streams/rerouting/applicable_volume_profile/volume_profile"/>
+ <ConfigurableElement Path="/Policy/policy/streams/patch/applicable_volume_profile/volume_profile"/>
</ConfigurableElements>
<Settings>
<Configuration Name="Calibration">
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/voice_call/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">voice_call</EnumParameter>
</ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/system/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">system</EnumParameter>
</ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/ring/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">ring</EnumParameter>
</ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/music/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">music</EnumParameter>
</ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/alarm/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">alarm</EnumParameter>
</ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-12.00000000</FixedPointParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/notification/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">notification</EnumParameter>
</ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">bluetooth_sco</EnumParameter>
</ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-6.00000000</FixedPointParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">enforced_audible</EnumParameter>
</ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/tts/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">tts</EnumParameter>
</ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/accessibility/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">accessibility</EnumParameter>
</ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/rerouting/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">rerouting</EnumParameter>
</ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-16.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-8.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-12.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-6.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/voice_call/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-30.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-26.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-22.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-12.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-6.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-12.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-6.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-21.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/system/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-10.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-49.50000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-33.50000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-35.69921875</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-26.10156250</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-13.19921875</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-49.50000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-33.50000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-27.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/ring/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-10.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-56.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-34.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-11.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/music/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-49.50000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-33.50000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-35.69921875</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-26.10156250</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-13.19921875</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-49.50000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-33.50000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-27.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/alarm/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-10.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-49.50000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-33.50000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-35.69921875</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-26.10156250</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-13.19921875</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-49.50000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-33.50000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-27.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/notification/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-10.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-12.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-6.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-16.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-8.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-12.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-6.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/bluetooth_sco/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-30.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-26.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-22.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-12.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-6.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-12.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-6.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-27.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/enforced_audible/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-10.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-96.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-96.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">2</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-96.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-96.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-96.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-68.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-34.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-96.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-96.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">2</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-96.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-96.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-96.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-96.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">2</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-96.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/tts/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-96.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-56.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-34.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-11.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/accessibility/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">2</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">2</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">2</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">2</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/rerouting/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">2</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">2</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">2</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">2</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/patch/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/patch/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">patch</EnumParameter>
</ConfigurableElement>
</Configuration>
</Settings>
@@ -11063,234 +9575,17 @@
</Configuration>
</Configurations>
<ConfigurableElements>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/0/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/1/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/2/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/3/index"/>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation"/>
+ <ConfigurableElement Path="/Policy/policy/streams/dtmf/applicable_volume_profile/volume_profile"/>
</ConfigurableElements>
<Settings>
<Configuration Name="InCall">
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-30.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-26.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-22.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-12.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-6.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-12.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-6.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-27.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-10.00000000</FixedPointParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/dtmf/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">voice_call</EnumParameter>
</ConfigurableElement>
</Configuration>
<Configuration Name="OutOfCall">
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-12.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/headset_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-6.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-16.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-8.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/speaker_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/0/index">
- <IntegerParameter Name="index">0</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-24.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-18.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-12.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/earpiece_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-6.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/0/index">
- <IntegerParameter Name="index">1</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/0/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-58.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/1/index">
- <IntegerParameter Name="index">33</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/1/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-40.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/2/index">
- <IntegerParameter Name="index">66</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/2/db_attenuation">
- <FixedPointParameter Name="db_attenuation">-17.00000000</FixedPointParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/3/index">
- <IntegerParameter Name="index">100</IntegerParameter>
- </ConfigurableElement>
- <ConfigurableElement Path="/Policy/policy/streams/dtmf/volume_profiles/extmedia_device_category/curve_points/3/db_attenuation">
- <FixedPointParameter Name="db_attenuation">0.00000000</FixedPointParameter>
+ <ConfigurableElement Path="/Policy/policy/streams/dtmf/applicable_volume_profile/volume_profile">
+ <EnumParameter Name="volume_profile">dtmf</EnumParameter>
</ConfigurableElement>
</Configuration>
</Settings>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/volumes.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/volumes.pfw
index 1049564..7ac7d5f 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/volumes.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/volumes.pfw
@@ -1,462 +1,18 @@
supDomain: VolumeProfilesForStream
domain: Calibration
conf: Calibration
- component: /Policy/policy/streams
- component: voice_call/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -18.0
- 2/index = 66
- 2/db_attenuation = -12.0
- 3/index = 100
- 3/db_attenuation = -6.0
- component: speaker_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -16.0
- 2/index = 66
- 2/db_attenuation = -8.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: earpiece_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -18.0
- 2/index = 66
- 2/db_attenuation = -12.0
- 3/index = 100
- 3/db_attenuation = -6.0
- component: extmedia_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
-
- component: system/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -30.0
- 1/index = 33
- 1/db_attenuation = -26.0
- 2/index = 66
- 2/db_attenuation = -22.0
- 3/index = 100
- 3/db_attenuation = -18.0
- component: speaker_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -18.0
- 2/index = 66
- 2/db_attenuation = -12.0
- 3/index = 100
- 3/db_attenuation = -6.0
- component: earpiece_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -18.0
- 2/index = 66
- 2/db_attenuation = -12.0
- 3/index = 100
- 3/db_attenuation = -6.0
- component: extmedia_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -21.0
- 3/index = 100
- 3/db_attenuation = -10.0
-
- component: ring/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -49.5
- 1/index = 33
- 1/db_attenuation = -33.5
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: speaker_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -35.7
- 1/index = 33
- 1/db_attenuation = -26.1
- 2/index = 66
- 2/db_attenuation = -13.2
- 3/index = 100
- 3/db_attenuation = 0.0
- component: earpiece_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -49.5
- 1/index = 33
- 1/db_attenuation = -33.5
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: extmedia_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -27.0
- 3/index = 100
- 3/db_attenuation = -10.0
-
- component: music/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: speaker_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -56.0
- 1/index = 33
- 1/db_attenuation = -34.0
- 2/index = 66
- 2/db_attenuation = -11.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: earpiece_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: extmedia_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
-
- component: alarm/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -49.5
- 1/index = 33
- 1/db_attenuation = -33.5
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: speaker_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -35.7
- 1/index = 33
- 1/db_attenuation = -26.1
- 2/index = 66
- 2/db_attenuation = -13.2
- 3/index = 100
- 3/db_attenuation = 0.0
- component: earpiece_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -49.5
- 1/index = 33
- 1/db_attenuation = -33.5
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: extmedia_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -27.0
- 3/index = 100
- 3/db_attenuation = -10.0
-
- component: notification/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -49.5
- 1/index = 33
- 1/db_attenuation = -33.5
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: speaker_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -35.7
- 1/index = 33
- 1/db_attenuation = -26.1
- 2/index = 66
- 2/db_attenuation = -13.2
- 3/index = 100
- 3/db_attenuation = 0.0
- component: earpiece_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -49.5
- 1/index = 33
- 1/db_attenuation = -33.5
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: extmedia_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -27.0
- 3/index = 100
- 3/db_attenuation = -10.0
-
- component: bluetooth_sco/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -18.0
- 2/index = 66
- 2/db_attenuation = -12.0
- 3/index = 100
- 3/db_attenuation = -6.0
- component: speaker_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -16.0
- 2/index = 66
- 2/db_attenuation = -8.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: earpiece_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -18.0
- 2/index = 66
- 2/db_attenuation = -12.0
- 3/index = 100
- 3/db_attenuation = -6.0
- component: extmedia_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
-
- component: enforced_audible/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -30.0
- 1/index = 33
- 1/db_attenuation = -26.0
- 2/index = 66
- 2/db_attenuation = -22.0
- 3/index = 100
- 3/db_attenuation = -18.0
- component: speaker_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -18.0
- 2/index = 66
- 2/db_attenuation = -12.0
- 3/index = 100
- 3/db_attenuation = -6.0
- component: earpiece_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -18.0
- 2/index = 66
- 2/db_attenuation = -12.0
- 3/index = 100
- 3/db_attenuation = -6.0
- component: extmedia_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -27.0
- 3/index = 100
- 3/db_attenuation = -10.0
-
- component: tts/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = -96.0
- 1/index = 1
- 1/db_attenuation = -96.0
- 2/index = 2
- 2/db_attenuation = -96.0
- 3/index = 100
- 3/db_attenuation = -96.0
- component: speaker_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = -96.0
- 1/index = 33
- 1/db_attenuation = -68.0
- 2/index = 66
- 2/db_attenuation = -34.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: earpiece_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = -96.0
- 1/index = 1
- 1/db_attenuation = -96.0
- 2/index = 2
- 2/db_attenuation = -96.0
- 3/index = 100
- 3/db_attenuation = -96.0
- component: extmedia_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = -96.0
- 1/index = 1
- 1/db_attenuation = -96.0
- 2/index = 2
- 2/db_attenuation = -96.0
- 3/index = 100
- 3/db_attenuation = -96.0
-
- component: accessibility/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: speaker_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -56.0
- 1/index = 33
- 1/db_attenuation = -34.0
- 2/index = 66
- 2/db_attenuation = -11.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: earpiece_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: extmedia_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
-
- component: rerouting/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = 0.0
- 1/index = 1
- 1/db_attenuation = 0.0
- 2/index = 2
- 2/db_attenuation = 0.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: speaker_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = 0.0
- 1/index = 1
- 1/db_attenuation = 0.0
- 2/index = 2
- 2/db_attenuation = 0.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: earpiece_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = 0.0
- 1/index = 1
- 1/db_attenuation = 0.0
- 2/index = 2
- 2/db_attenuation = 0.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: extmedia_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = 0.0
- 1/index = 1
- 1/db_attenuation = 0.0
- 2/index = 2
- 2/db_attenuation = 0.0
- 3/index = 100
- 3/db_attenuation = 0.0
-
- component: patch/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = 0.0
- 1/index = 1
- 1/db_attenuation = 0.0
- 2/index = 2
- 2/db_attenuation = 0.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: speaker_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = 0.0
- 1/index = 1
- 1/db_attenuation = 0.0
- 2/index = 2
- 2/db_attenuation = 0.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: earpiece_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = 0.0
- 1/index = 1
- 1/db_attenuation = 0.0
- 2/index = 2
- 2/db_attenuation = 0.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: extmedia_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = 0.0
- 1/index = 1
- 1/db_attenuation = 0.0
- 2/index = 2
- 2/db_attenuation = 0.0
- 3/index = 100
- 3/db_attenuation = 0.0
+ /Policy/policy/streams/voice_call/applicable_volume_profile/volume_profile = voice_call
+ /Policy/policy/streams/system/applicable_volume_profile/volume_profile = system
+ /Policy/policy/streams/ring/applicable_volume_profile/volume_profile = ring
+ /Policy/policy/streams/music/applicable_volume_profile/volume_profile = music
+ /Policy/policy/streams/alarm/applicable_volume_profile/volume_profile = alarm
+ /Policy/policy/streams/notification/applicable_volume_profile/volume_profile = notification
+ /Policy/policy/streams/bluetooth_sco/applicable_volume_profile/volume_profile = bluetooth_sco
+ /Policy/policy/streams/enforced_audible/applicable_volume_profile/volume_profile = enforced_audible
+ /Policy/policy/streams/tts/applicable_volume_profile/volume_profile = tts
+ /Policy/policy/streams/accessibility/applicable_volume_profile/volume_profile = accessibility
+ /Policy/policy/streams/rerouting/applicable_volume_profile/volume_profile = rerouting
+ /Policy/policy/streams/patch/applicable_volume_profile/volume_profile = patch
domain: Dtmf
conf: InCall
@@ -464,82 +20,9 @@
TelephonyMode Is InCall
TelephonyMode Is InCommunication
- component: /Policy/policy/streams
- component: dtmf/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -30.0
- 1/index = 33
- 1/db_attenuation = -26.0
- 2/index = 66
- 2/db_attenuation = -22.0
- 3/index = 100
- 3/db_attenuation = -18.0
- component: speaker_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -18.0
- 2/index = 66
- 2/db_attenuation = -12.0
- 3/index = 100
- 3/db_attenuation = -6.0
- component: earpiece_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -18.0
- 2/index = 66
- 2/db_attenuation = -12.0
- 3/index = 100
- 3/db_attenuation = -6.0
- component: extmedia_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -27.0
- 3/index = 100
- 3/db_attenuation = -10.0
+ /Policy/policy/streams/dtmf/applicable_volume_profile/volume_profile = voice_call
conf: OutOfCall
- component: /Policy/policy/streams
- component: dtmf/volume_profiles
- component: headset_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -18.0
- 2/index = 66
- 2/db_attenuation = -12.0
- 3/index = 100
- 3/db_attenuation = -6.0
- component: speaker_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -16.0
- 2/index = 66
- 2/db_attenuation = -8.0
- 3/index = 100
- 3/db_attenuation = 0.0
- component: earpiece_device_category/curve_points
- 0/index = 0
- 0/db_attenuation = -24.0
- 1/index = 33
- 1/db_attenuation = -18.0
- 2/index = 66
- 2/db_attenuation = -12.0
- 3/index = 100
- 3/db_attenuation = -6.0
- component: extmedia_device_category/curve_points
- 0/index = 1
- 0/db_attenuation = -58.0
- 1/index = 33
- 1/db_attenuation = -40.0
- 2/index = 66
- 2/db_attenuation = -17.0
- 3/index = 100
- 3/db_attenuation = 0.0
+ /Policy/policy/streams/dtmf/applicable_volume_profile/volume_profile = dtmf
+
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem-CommonTypes.xml b/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem-CommonTypes.xml
index 821d6ad..cf7df60 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem-CommonTypes.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem-CommonTypes.xml
@@ -6,8 +6,6 @@
profile. It must match with the output device enum parameter.
-->
<!--#################### GLOBAL COMPONENTS BEGIN ####################-->
- <!-- Common Types defintion -->
- <xi:include href="PolicySubsystem-Volume.xml"/>
<!--#################### GLOBAL COMPONENTS END ####################-->
@@ -142,10 +140,28 @@
<!--#################### STREAM COMMON TYPES BEGIN ####################-->
+ <ComponentType Name="VolumeProfileType">
+ <EnumParameter Name="volume_profile" Size="32">
+ <ValuePair Literal="voice_call" Numerical="0"/>
+ <ValuePair Literal="system" Numerical="1"/>
+ <ValuePair Literal="ring" Numerical="2"/>
+ <ValuePair Literal="music" Numerical="3"/>
+ <ValuePair Literal="alarm" Numerical="4"/>
+ <ValuePair Literal="notification" Numerical="5"/>
+ <ValuePair Literal="bluetooth_sco" Numerical="6"/>
+ <ValuePair Literal="enforced_audible" Numerical="7"/>
+ <ValuePair Literal="dtmf" Numerical="8"/>
+ <ValuePair Literal="tts" Numerical="9"/>
+ <ValuePair Literal="accessibility" Numerical="10"/>
+ <ValuePair Literal="rerouting" Numerical="11"/>
+ <ValuePair Literal="patch" Numerical="12"/>
+ </EnumParameter>
+ </ComponentType>
+
<ComponentType Name="Stream">
- <Component Name="applicable_strategy" Type="Strategy" Mapping="Stream:'%1'"/>
- <Component Name="volume_profiles" Type="VolumeCurvesCategories"
- Description="A volume profile is refered by the stream type."/>
+ <Component Name="applicable_strategy" Type="Strategy"/>
+ <Component Name="applicable_volume_profile" Type="VolumeProfileType"
+ Description="Volume profile followed by a given stream type."/>
</ComponentType>
<!--#################### STREAM COMMON TYPES END ####################-->
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem-Volume.xml b/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem-Volume.xml
deleted file mode 100755
index cf39cc2..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem-Volume.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ComponentTypeSet xmlns:xi="http://www.w3.org/2001/XInclude"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="Schemas/ComponentTypeSet.xsd">
- <ComponentType Name="VolumeCurvePoints">
- <ParameterBlock Name="curve_points" ArrayLength="4" Mapping="VolumeProfile:'%1'"
- Description="4 points to define the volume attenuation curve, each
- characterized by the volume index (from 0 to 100) at which
- they apply, and the attenuation in dB at that index.
- We use 100 steps to avoid rounding errors when computing
- the volume">
- <IntegerParameter Name="index" Size="32"/>
- <FixedPointParameter Name="db_attenuation" Size="16" Integral="7" Fractional="8"/>
- </ParameterBlock>
- </ComponentType>
-
- <ComponentType Name="VolumeCurvesCategories">
- <Component Name="headset_device_category" Type="VolumeCurvePoints" Mapping="Category:0"/>
- <Component Name="speaker_device_category" Type="VolumeCurvePoints" Mapping="Category:1"/>
- <Component Name="earpiece_device_category" Type="VolumeCurvePoints" Mapping="Category:2"/>
- <Component Name="extmedia_device_category" Type="VolumeCurvePoints" Mapping="Category:3"/>
- </ComponentType>
-
-</ComponentTypeSet>
-
-
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem.xml b/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem.xml
index b21f6ae..f08d45f 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem.xml
@@ -38,29 +38,29 @@
<ComponentType Name="Streams" Description="associated to audio_stream_type_t definition,
identifier mapping must match the value of the enum">
- <Component Name="voice_call" Type="Stream" Mapping="Amend1:VoiceCall,Identifier:0"/>
- <Component Name="system" Type="Stream" Mapping="Amend1:System,Identifier:1"/>
- <Component Name="ring" Type="Stream" Mapping="Amend1:Ring,Identifier:2"/>
- <Component Name="music" Type="Stream" Mapping="Amend1:Music,Identifier:3"/>
- <Component Name="alarm" Type="Stream" Mapping="Amend1:Alarm,Identifier:4"/>
+ <Component Name="voice_call" Type="Stream" Mapping="Stream:VoiceCall,Identifier:0"/>
+ <Component Name="system" Type="Stream" Mapping="Stream:System,Identifier:1"/>
+ <Component Name="ring" Type="Stream" Mapping="Stream:Ring,Identifier:2"/>
+ <Component Name="music" Type="Stream" Mapping="Stream:Music,Identifier:3"/>
+ <Component Name="alarm" Type="Stream" Mapping="Stream:Alarm,Identifier:4"/>
<Component Name="notification" Type="Stream"
- Mapping="Amend1:Notification,Identifier:5"/>
+ Mapping="Stream:Notification,Identifier:5"/>
<Component Name="bluetooth_sco" Type="Stream"
- Mapping="Amend1:BluetoothSco,Identifier:6"/>
+ Mapping="Stream:BluetoothSco,Identifier:6"/>
<Component Name="enforced_audible" Type="Stream"
- Mapping="Amend1:EnforceAudible,Identifier:7"
+ Mapping="Stream:EnforceAudible,Identifier:7"
Description="Sounds that cannot be muted by user and must
be routed to speaker"/>
- <Component Name="dtmf" Type="Stream" Mapping="Amend1:Dtmf,Identifier:8"/>
- <Component Name="tts" Type="Stream" Mapping="Amend1:Tts,Identifier:9"
+ <Component Name="dtmf" Type="Stream" Mapping="Stream:Dtmf,Identifier:8"/>
+ <Component Name="tts" Type="Stream" Mapping="Stream:Tts,Identifier:9"
Description="Transmitted Through Speaker.
Plays over speaker only, silent on other devices"/>
<Component Name="accessibility" Type="Stream"
- Mapping="Amend1:Accessibility,Identifier:10"
+ Mapping="Stream:Accessibility,Identifier:10"
Description="For accessibility talk back prompts"/>
- <Component Name="rerouting" Type="Stream" Mapping="Amend1:Rerouting,Identifier:11"
+ <Component Name="rerouting" Type="Stream" Mapping="Stream:Rerouting,Identifier:11"
Description="For dynamic policy output mixes"/>
- <Component Name="patch" Type="Stream" Mapping="Amend1:Patch,Identifier:12"
+ <Component Name="patch" Type="Stream" Mapping="Stream:Patch,Identifier:12"
Description="For internal audio flinger tracks. Fixed volume"/>
</ComponentType>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
index a523656..c65de92 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
@@ -8,7 +8,6 @@
PolicySubsystem.cpp \
Strategy.cpp \
InputSource.cpp \
- VolumeProfile.cpp \
Stream.cpp \
Usage.cpp
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
index bf3906d..6412134 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
@@ -20,7 +20,6 @@
#include "Strategy.h"
#include "Stream.h"
#include "InputSource.h"
-#include "VolumeProfile.h"
#include "Usage.h"
#include <AudioPolicyPluginInterface.h>
#include <AudioPolicyEngineInstance.h>
@@ -40,7 +39,6 @@
const char *const PolicySubsystem::mStrategyComponentName = "Strategy";
const char *const PolicySubsystem::mInputSourceComponentName = "InputSource";
const char *const PolicySubsystem::mUsageComponentName = "Usage";
-const char *const PolicySubsystem::mVolumeProfileComponentName = "VolumeProfile";
PolicySubsystem::PolicySubsystem(const std::string &name)
: CSubsystem(name),
@@ -67,7 +65,7 @@
addSubsystemObjectFactory(
new TSubsystemObjectFactory<Stream>(
mStreamComponentName,
- (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
+ (1 << MappingKeyIdentifier))
);
addSubsystemObjectFactory(
new TSubsystemObjectFactory<Strategy>(
@@ -84,11 +82,6 @@
mInputSourceComponentName,
(1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
);
- addSubsystemObjectFactory(
- new TSubsystemObjectFactory<VolumeProfile>(
- mVolumeProfileComponentName,
- (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier) | (1 << MappingKeyIdentifier))
- );
}
// Retrieve Route interface
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.h b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.h
index 3c26fe1..e3143a5 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.h
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.h
@@ -56,5 +56,4 @@
static const char *const mStrategyComponentName;
static const char *const mInputSourceComponentName;
static const char *const mUsageComponentName;
- static const char *const mVolumeProfileComponentName;
};
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
index 575b0bb..4387634 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
@@ -24,15 +24,10 @@
Stream::Stream(const string &mappingValue,
CInstanceConfigurableElement *instanceConfigurableElement,
const CMappingContext &context)
- : CFormattedSubsystemObject(instanceConfigurableElement,
- mappingValue,
- MappingKeyAmend1,
- (MappingKeyAmendEnd - MappingKeyAmend1 + 1),
- context),
+ : CSubsystemObject(instanceConfigurableElement),
mPolicySubsystem(static_cast<const PolicySubsystem *>(
instanceConfigurableElement->getBelongingSubsystem())),
- mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface()),
- mApplicableStrategy(mDefaultApplicableStrategy)
+ mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
{
mId = static_cast<audio_stream_type_t>(context.getItemAsInteger(MappingKeyIdentifier));
@@ -40,17 +35,17 @@
mPolicyPluginInterface->addStream(getFormattedMappingValue(), mId);
}
-bool Stream::receiveFromHW(string & /*error*/)
-{
- blackboardWrite(&mApplicableStrategy, sizeof(mApplicableStrategy));
- return true;
-}
-
bool Stream::sendToHW(string & /*error*/)
{
- uint32_t applicableStrategy;
- blackboardRead(&applicableStrategy, sizeof(applicableStrategy));
- mApplicableStrategy = applicableStrategy;
- return mPolicyPluginInterface->setStrategyForStream(mId,
- static_cast<routing_strategy>(mApplicableStrategy));
+ Applicable params;
+ blackboardRead(¶ms, sizeof(params));
+
+ mPolicyPluginInterface->setStrategyForStream(mId,
+ static_cast<routing_strategy>(params.strategy));
+
+ mPolicyPluginInterface->setVolumeProfileForStream(mId,
+ static_cast<audio_stream_type_t>(params.volumeProfile));
+
+ return true;
+
}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.h b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.h
index 7d90c36..4b0e081 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.h
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.h
@@ -16,7 +16,7 @@
#pragma once
-#include "FormattedSubsystemObject.h"
+#include "SubsystemObject.h"
#include "InstanceConfigurableElement.h"
#include "MappingContext.h"
#include <AudioPolicyPluginInterface.h>
@@ -24,15 +24,21 @@
class PolicySubsystem;
-class Stream : public CFormattedSubsystemObject
+class Stream : public CSubsystemObject
{
+private:
+ struct Applicable
+ {
+ uint32_t strategy; /**< applicable strategy for this stream. */
+ uint32_t volumeProfile; /**< applicable strategy for this stream. */
+ } __attribute__((packed));
+
public:
Stream(const std::string &mappingValue,
CInstanceConfigurableElement *instanceConfigurableElement,
const CMappingContext &context);
protected:
- virtual bool receiveFromHW(std::string &error);
virtual bool sendToHW(std::string &error);
private:
@@ -42,8 +48,5 @@
* Interface to communicate with Audio Policy Engine.
*/
android::AudioPolicyPluginInterface *mPolicyPluginInterface;
-
audio_stream_type_t mId; /**< stream type identifier to link with audio.h. */
- uint32_t mApplicableStrategy; /**< applicable strategy for this stream. */
- static const uint32_t mDefaultApplicableStrategy = 0; /**< default strategy. */
};
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.cpp
deleted file mode 100755
index 1469c3f..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source 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.
- */
-
-#include "VolumeProfile.h"
-#include "PolicyMappingKeys.h"
-#include "PolicySubsystem.h"
-#include "ParameterBlockType.h"
-#include <Volume.h>
-#include <math.h>
-
-using std::string;
-
-VolumeProfile::VolumeProfile(const string &mappingValue,
- CInstanceConfigurableElement *instanceConfigurableElement,
- const CMappingContext &context)
- : CFormattedSubsystemObject(instanceConfigurableElement,
- mappingValue,
- MappingKeyAmend1,
- (MappingKeyAmendEnd - MappingKeyAmend1 + 1),
- context),
- mPolicySubsystem(static_cast<const PolicySubsystem *>(
- instanceConfigurableElement->getBelongingSubsystem())),
- mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
-{
- uint32_t categoryKey = context.getItemAsInteger(MappingKeyCategory);
- if (categoryKey >= DEVICE_CATEGORY_CNT) {
- mCategory = DEVICE_CATEGORY_SPEAKER;
- } else {
- mCategory = static_cast<device_category>(categoryKey);
- }
- mId = static_cast<audio_stream_type_t>(context.getItemAsInteger(MappingKeyIdentifier));
-
- // (no exception support, defer the error)
- if (instanceConfigurableElement->getType() != CInstanceConfigurableElement::EParameterBlock) {
- return;
- }
- // Get actual element type
- const CParameterBlockType *parameterType = static_cast<const CParameterBlockType *>(
- instanceConfigurableElement->getTypeElement());
- mPoints = parameterType->getArrayLength();
-}
-
-bool VolumeProfile::receiveFromHW(string & /*error*/)
-{
- return true;
-}
-
-bool VolumeProfile::sendToHW(string & /*error*/)
-{
- Point points[mPoints];
- blackboardRead(&points, sizeof(Point) * mPoints);
-
- VolumeCurvePoints pointsVector;
- for (size_t i = 0; i < mPoints; i++) {
- VolumeCurvePoint curvePoint;
- curvePoint.mIndex = points[i].index;
- curvePoint.mDBAttenuation = static_cast<float>(points[i].dbAttenuation) /
- (1UL << gFractional);
- pointsVector.push_back(curvePoint);
- }
- return mPolicyPluginInterface->setVolumeProfileForStream(mId, mCategory, pointsVector);
-}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.h b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.h
deleted file mode 100755
index 3c2d9bc..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/VolumeProfile.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source 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.
- */
-
-#pragma once
-
-#include "FormattedSubsystemObject.h"
-#include "InstanceConfigurableElement.h"
-#include "MappingContext.h"
-#include <Volume.h>
-#include <AudioPolicyPluginInterface.h>
-#include <string>
-
-class PolicySubsystem;
-
-class VolumeProfile : public CFormattedSubsystemObject
-{
-private:
- struct Point
- {
- int index;
- /** Volume is using FixedPointParameter until float parameters are available. */
- int16_t dbAttenuation;
- } __attribute__((packed));
-
-public:
- VolumeProfile(const std::string &mappingValue,
- CInstanceConfigurableElement *instanceConfigurableElement,
- const CMappingContext &context);
-
-protected:
- virtual bool receiveFromHW(std::string &error);
- virtual bool sendToHW(std::string &error);
-
-private:
- const PolicySubsystem *mPolicySubsystem; /**< Route subsytem plugin. */
-
- /**
- * Interface to communicate with Audio Policy Engine.
- */
- android::AudioPolicyPluginInterface *mPolicyPluginInterface;
-
- /**
- * volume profile identifier, which is in fact a stream type to link with audio.h.
- */
- audio_stream_type_t mId;
-
- size_t mPoints;
- device_category mCategory;
-
- static const uint32_t gFractional = 8; /**< Beware to align with the structure. */
-};
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 074af50..7d585c0 100755
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -115,18 +115,6 @@
return (mApmObserver != NULL)? NO_ERROR : NO_INIT;
}
-bool Engine::setVolumeProfileForStream(const audio_stream_type_t &streamType,
- device_category deviceCategory,
- const VolumeCurvePoints &points)
-{
- Stream *stream = getFromCollection<audio_stream_type_t>(streamType);
- if (stream == NULL) {
- ALOGE("%s: stream %d not found", __FUNCTION__, streamType);
- return false;
- }
- return stream->setVolumeProfile(deviceCategory, points) == NO_ERROR;
-}
-
template <typename Key>
Element<Key> *Engine::getFromCollection(const Key &key) const
{
@@ -188,6 +176,18 @@
return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(strategy);
}
+bool Engine::PluginInterfaceImpl::setVolumeProfileForStream(const audio_stream_type_t &stream,
+ const audio_stream_type_t &profile)
+{
+ if (mPolicyEngine->setPropertyForKey<audio_stream_type_t, audio_stream_type_t>(stream,
+ profile)) {
+ mPolicyEngine->mApmObserver->getVolumeCurves().switchVolumeCurve(profile, stream);
+ return true;
+ }
+ return false;
+}
+
+
template <typename Property, typename Key>
bool Engine::setPropertyForKey(const Property &property, const Key &key)
{
@@ -199,32 +199,6 @@
return element->template set<Property>(property) == NO_ERROR;
}
-float Engine::volIndexToDb(device_category category,
- audio_stream_type_t streamType,
- int indexInUi)
-{
- Stream *stream = getFromCollection<audio_stream_type_t>(streamType);
- if (stream == NULL) {
- ALOGE("%s: Element indexed by key=%d not found", __FUNCTION__, streamType);
- return 1.0f;
- }
- return stream->volIndexToDb(category, indexInUi);
-}
-
-status_t Engine::initStreamVolume(audio_stream_type_t streamType,
- int indexMin, int indexMax)
-{
- Stream *stream = getFromCollection<audio_stream_type_t>(streamType);
- if (stream == NULL) {
- ALOGE("%s: Stream Type %d not found", __FUNCTION__, streamType);
- return BAD_TYPE;
- }
- mApmObserver->getStreamDescriptors().setVolumeIndexMin(streamType, indexMin);
- mApmObserver->getStreamDescriptors().setVolumeIndexMax(streamType, indexMax);
-
- return stream->initVolume(indexMin, indexMax);
-}
-
status_t Engine::setPhoneState(audio_mode_t mode)
{
return mPolicyParameterMgr->setPhoneState(mode);
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 8a15e5e..bc5e035 100755
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -88,20 +88,6 @@
{
return mPolicyEngine->setDeviceConnectionState(devDesc, state);
}
- virtual status_t initStreamVolume(audio_stream_type_t stream,
- int indexMin, int indexMax)
- {
- return mPolicyEngine->initStreamVolume(stream, indexMin, indexMax);
- }
-
- virtual void initializeVolumeCurves(bool /*isSpeakerDrcEnabled*/) {}
-
- virtual float volIndexToDb(device_category deviceCategory,
- audio_stream_type_t stream,
- int indexInUi)
- {
- return mPolicyEngine->volIndexToDb(deviceCategory, stream, indexInUi);
- }
private:
Engine *mPolicyEngine;
@@ -141,11 +127,7 @@
stream);
}
virtual bool setVolumeProfileForStream(const audio_stream_type_t &stream,
- device_category deviceCategory,
- const VolumeCurvePoints &points)
- {
- return mPolicyEngine->setVolumeProfileForStream(stream, deviceCategory, points);
- }
+ const audio_stream_type_t &volumeProfile);
virtual bool setStrategyForUsage(const audio_usage_t &usage, routing_strategy strategy)
{
@@ -181,9 +163,6 @@
audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const;
status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
audio_policy_dev_state_t state);
- float volIndexToDb(device_category category, audio_stream_type_t stream, int indexInUi);
- status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax);
-
StrategyCollection mStrategyCollection; /**< Strategies indexed by their enum id. */
StreamCollection mStreamCollection; /**< Streams indexed by their enum id. */
UsageCollection mUsageCollection; /**< Usages indexed by their enum id. */
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.cpp b/services/audiopolicy/engineconfigurable/src/Stream.cpp
index 3bd5220..0ed364f 100755
--- a/services/audiopolicy/engineconfigurable/src/Stream.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Stream.cpp
@@ -62,91 +62,22 @@
return mApplicableStrategy;
}
-status_t Element<audio_stream_type_t>::setVolumeProfile(device_category category,
- const VolumeCurvePoints &points)
+template <>
+status_t Element<audio_stream_type_t>::set<audio_stream_type_t>(audio_stream_type_t volumeProfile)
{
- ALOGD("%s: adding volume profile for %s for device category %d, points nb =%zu", __FUNCTION__,
- getName().c_str(), category, points.size());
- mVolumeProfiles[category] = points;
-
- for (size_t i = 0; i < points.size(); i++) {
- ALOGV("%s: %s cat=%d curve index =%zu Index=%d dBAttenuation=%f",
- __FUNCTION__, getName().c_str(), category, i, points[i].mIndex,
- points[i].mDBAttenuation);
- }
- return NO_ERROR;
-}
-
-status_t Element<audio_stream_type_t>::initVolume(int indexMin, int indexMax)
-{
- ALOGV("initStreamVolume() stream %s, min %d, max %d", getName().c_str(), indexMin, indexMax);
- if (indexMin < 0 || indexMin >= indexMax) {
- ALOGW("initStreamVolume() invalid index limits for stream %s, min %d, max %d",
- getName().c_str(), indexMin, indexMax);
+ if (volumeProfile >= AUDIO_STREAM_CNT) {
return BAD_VALUE;
}
- mIndexMin = indexMin;
- mIndexMax = indexMax;
-
+ mVolumeProfile = volumeProfile;
+ ALOGD("%s: 0x%X for Stream %s", __FUNCTION__, mVolumeProfile, getName().c_str());
return NO_ERROR;
}
-float Element<audio_stream_type_t>::volIndexToDb(device_category deviceCategory, int indexInUi)
+template <>
+audio_stream_type_t Element<audio_stream_type_t>::get<audio_stream_type_t>() const
{
- VolumeProfileConstIterator it = mVolumeProfiles.find(deviceCategory);
- if (it == mVolumeProfiles.end()) {
- ALOGE("%s: device category %d not found for stream %s", __FUNCTION__, deviceCategory,
- getName().c_str());
- return 0.0f;
- }
- const VolumeCurvePoints curve = mVolumeProfiles[deviceCategory];
- if (curve.size() != Volume::VOLCNT) {
- ALOGE("%s: invalid profile for category %d and for stream %s", __FUNCTION__, deviceCategory,
- getName().c_str());
- return 0.0f;
- }
-
- // the volume index in the UI is relative to the min and max volume indices for this stream type
- int nbSteps = 1 + curve[Volume::VOLMAX].mIndex -
- curve[Volume::VOLMIN].mIndex;
-
- if (mIndexMax - mIndexMin == 0) {
- ALOGE("%s: Invalid volume indexes Min=Max=%d", __FUNCTION__, mIndexMin);
- return 0.0f;
- }
- int volIdx = (nbSteps * (indexInUi - mIndexMin)) /
- (mIndexMax - mIndexMin);
-
- // find what part of the curve this index volume belongs to, or if it's out of bounds
- int segment = 0;
- if (volIdx < curve[Volume::VOLMIN].mIndex) { // out of bounds
- return VOLUME_MIN_DB;
- } else if (volIdx < curve[Volume::VOLKNEE1].mIndex) {
- segment = 0;
- } else if (volIdx < curve[Volume::VOLKNEE2].mIndex) {
- segment = 1;
- } else if (volIdx <= curve[Volume::VOLMAX].mIndex) {
- segment = 2;
- } else { // out of bounds
- return 0.0f;
- }
-
- // linear interpolation in the attenuation table in dB
- float decibels = curve[segment].mDBAttenuation +
- ((float)(volIdx - curve[segment].mIndex)) *
- ( (curve[segment+1].mDBAttenuation -
- curve[segment].mDBAttenuation) /
- ((float)(curve[segment+1].mIndex -
- curve[segment].mIndex)) );
-
- ALOGV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f]",
- curve[segment].mIndex, volIdx,
- curve[segment+1].mIndex,
- curve[segment].mDBAttenuation,
- decibels,
- curve[segment+1].mDBAttenuation);
-
- return decibels;
+ ALOGV("%s: 0x%X for Stream %s", __FUNCTION__, mVolumeProfile, getName().c_str());
+ return mVolumeProfile;
}
} // namespace audio_policy
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.h b/services/audiopolicy/engineconfigurable/src/Stream.h
index b103f89..6902003 100755
--- a/services/audiopolicy/engineconfigurable/src/Stream.h
+++ b/services/audiopolicy/engineconfigurable/src/Stream.h
@@ -18,7 +18,6 @@
#include "Element.h"
#include "EngineDefinition.h"
-#include <Volume.h>
#include <RoutingStrategy.h>
#include <map>
@@ -32,17 +31,10 @@
template <>
class Element<audio_stream_type_t>
{
-private:
- typedef std::map<device_category, VolumeCurvePoints> VolumeProfiles;
- typedef VolumeProfiles::iterator VolumeProfileIterator;
- typedef VolumeProfiles::const_iterator VolumeProfileConstIterator;
-
public:
Element(const std::string &name)
: mName(name),
- mApplicableStrategy(STRATEGY_MEDIA),
- mIndexMin(0),
- mIndexMax(1)
+ mApplicableStrategy(STRATEGY_MEDIA)
{}
~Element() {}
@@ -79,12 +71,6 @@
template <typename Property>
status_t set(Property property);
- status_t setVolumeProfile(device_category category, const VolumeCurvePoints &points);
-
- float volIndexToDb(device_category deviceCategory, int indexInUi);
-
- status_t initVolume(int indexMin, int indexMax);
-
private:
/* Copy facilities are put private to disable copy. */
Element(const Element &object);
@@ -95,16 +81,7 @@
routing_strategy mApplicableStrategy; /**< Applicable strategy for this stream. */
- /**
- * Collection of volume profiles indexed by the stream type.
- * Volume is the only reason why the stream profile was not removed from policy when introducing
- * attributes.
- */
- VolumeProfiles mVolumeProfiles;
-
- int mIndexMin;
-
- int mIndexMax;
+ audio_stream_type_t mVolumeProfile; /**< Volume Profile followed by this stream. */
};
typedef Element<audio_stream_type_t> Stream;
diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk
index b3b3dde..bb12714 100755
--- a/services/audiopolicy/enginedefault/Android.mk
+++ b/services/audiopolicy/enginedefault/Android.mk
@@ -8,8 +8,6 @@
LOCAL_SRC_FILES := \
src/Engine.cpp \
src/EngineInstance.cpp \
- src/Gains.cpp \
-
audio_policy_engine_includes_common := \
$(LOCAL_PATH)/include \
@@ -38,11 +36,7 @@
LOCAL_STATIC_LIBRARIES := \
libmedia_helper \
libaudiopolicycomponents \
-
-ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
-LOCAL_STATIC_LIBRARIES += libxml2
-endif #ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
-
+ libxml2
LOCAL_SHARED_LIBRARIES += \
libcutils \
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index b0df018..37f79fe 100755
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -25,7 +25,6 @@
#endif
#include "Engine.h"
-#include "Gains.h"
#include <AudioPolicyManagerObserver.h>
#include <AudioPort.h>
#include <IOProfile.h>
@@ -63,56 +62,6 @@
return (mApmObserver != NULL) ? NO_ERROR : NO_INIT;
}
-float Engine::volIndexToDb(device_category category, audio_stream_type_t streamType, int indexInUi)
-{
- const StreamDescriptor &streamDesc = mApmObserver->getStreamDescriptors().valueAt(streamType);
- return Gains::volIndexToDb(category, streamDesc, indexInUi);
-}
-
-
-status_t Engine::initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax)
-{
- ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
- if (indexMin < 0 || indexMin >= indexMax) {
- ALOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d",
- stream , indexMin, indexMax);
- return BAD_VALUE;
- }
- mApmObserver->getStreamDescriptors().setVolumeIndexMin(stream, indexMin);
- mApmObserver->getStreamDescriptors().setVolumeIndexMax(stream, indexMax);
- return NO_ERROR;
-}
-
-void Engine::initializeVolumeCurves(bool isSpeakerDrcEnabled)
-{
- StreamDescriptorCollection &streams = mApmObserver->getStreamDescriptors();
-
- for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
- for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
- streams.setVolumeCurvePoint(static_cast<audio_stream_type_t>(i),
- static_cast<device_category>(j),
- Gains::sVolumeProfiles[i][j]);
- }
- }
-
- // Check availability of DRC on speaker path: if available, override some of the speaker curves
- if (isSpeakerDrcEnabled) {
- streams.setVolumeCurvePoint(AUDIO_STREAM_SYSTEM, DEVICE_CATEGORY_SPEAKER,
- Gains::sDefaultSystemVolumeCurveDrc);
- streams.setVolumeCurvePoint(AUDIO_STREAM_RING, DEVICE_CATEGORY_SPEAKER,
- Gains::sSpeakerSonificationVolumeCurveDrc);
- streams.setVolumeCurvePoint(AUDIO_STREAM_ALARM, DEVICE_CATEGORY_SPEAKER,
- Gains::sSpeakerSonificationVolumeCurveDrc);
- streams.setVolumeCurvePoint(AUDIO_STREAM_NOTIFICATION, DEVICE_CATEGORY_SPEAKER,
- Gains::sSpeakerSonificationVolumeCurveDrc);
- streams.setVolumeCurvePoint(AUDIO_STREAM_MUSIC, DEVICE_CATEGORY_SPEAKER,
- Gains::sSpeakerMediaVolumeCurveDrc);
- streams.setVolumeCurvePoint(AUDIO_STREAM_ACCESSIBILITY, DEVICE_CATEGORY_SPEAKER,
- Gains::sSpeakerMediaVolumeCurveDrc);
- }
-}
-
-
status_t Engine::setPhoneState(audio_mode_t state)
{
ALOGV("setPhoneState() state %d", state);
@@ -130,20 +79,14 @@
// store previous phone state for management of sonification strategy below
int oldState = mPhoneState;
mPhoneState = state;
- StreamDescriptorCollection &streams = mApmObserver->getStreamDescriptors();
- // are we entering or starting a call
+
if (!is_state_in_call(oldState) && is_state_in_call(state)) {
ALOGV(" Entering call in setPhoneState()");
- for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
- streams.setVolumeCurvePoint(AUDIO_STREAM_DTMF, static_cast<device_category>(j),
- Gains::sVolumeProfiles[AUDIO_STREAM_VOICE_CALL][j]);
- }
+ mApmObserver->getVolumeCurves().switchVolumeCurve(AUDIO_STREAM_VOICE_CALL,
+ AUDIO_STREAM_DTMF);
} else if (is_state_in_call(oldState) && !is_state_in_call(state)) {
ALOGV(" Exiting call in setPhoneState()");
- for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
- streams.setVolumeCurvePoint(AUDIO_STREAM_DTMF, static_cast<device_category>(j),
- Gains::sVolumeProfiles[AUDIO_STREAM_DTMF][j]);
- }
+ mApmObserver->getVolumeCurves().restoreOriginVolumeCurve(AUDIO_STREAM_DTMF);
}
return NO_ERROR;
}
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 697f19b..8b6eaf6 100755
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -18,7 +18,6 @@
#include "AudioPolicyManagerInterface.h"
-#include "Gains.h"
#include <AudioGain.h>
#include <policy.h>
@@ -93,19 +92,6 @@
{
return NO_ERROR;
}
- virtual status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax)
- {
- return mPolicyEngine->initStreamVolume(stream, indexMin, indexMax);
- }
- virtual void initializeVolumeCurves(bool isSpeakerDrcEnabled)
- {
- return mPolicyEngine->initializeVolumeCurves(isSpeakerDrcEnabled);
- }
- virtual float volIndexToDb(device_category deviceCategory,
- audio_stream_type_t stream, int indexInUi)
- {
- return mPolicyEngine->volIndexToDb(deviceCategory, stream, indexInUi);
- }
private:
Engine *mPolicyEngine;
} mManagerInterface;
@@ -140,11 +126,6 @@
routing_strategy getStrategyForUsage(audio_usage_t usage);
audio_devices_t getDeviceForStrategy(routing_strategy strategy) const;
audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const;
-
- float volIndexToDb(device_category category, audio_stream_type_t stream, int indexInUi);
- status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax);
- void initializeVolumeCurves(bool isSpeakerDrcEnabled);
-
audio_mode_t mPhoneState; /**< current phone state. */
/** current forced use configuration. */
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index f853274..3c70ce8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -39,11 +39,11 @@
#include <media/AudioPolicyHelper.h>
#include <soundtrigger/SoundTrigger.h>
#include "AudioPolicyManager.h"
-#ifdef USE_XML_AUDIO_POLICY_CONF
-#include <Serializer.h>
-#else
+#ifndef USE_XML_AUDIO_POLICY_CONF
#include <ConfigParsingUtils.h>
+#include <StreamDescriptor.h>
#endif
+#include <Serializer.h>
#include "TypeConverter.h"
#include <policy.h>
@@ -1159,7 +1159,7 @@
// apply volume rules for current stream and device if necessary
checkAndSetVolume(stream,
- mStreams.valueFor(stream).getVolumeIndex(device),
+ mVolumeCurves->getVolumeIndex(stream, device),
outputDesc,
device);
@@ -1766,10 +1766,9 @@
int indexMax)
{
ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
- mEngine->initStreamVolume(stream, indexMin, indexMax);
- //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now
+ mVolumeCurves->initStreamVolume(stream, indexMin, indexMax);
if (stream == AUDIO_STREAM_MUSIC) {
- mEngine->initStreamVolume(AUDIO_STREAM_ACCESSIBILITY, indexMin, indexMax);
+ mVolumeCurves->initStreamVolume(AUDIO_STREAM_ACCESSIBILITY, indexMin, indexMax);
}
}
@@ -1778,8 +1777,8 @@
audio_devices_t device)
{
- if ((index < mStreams.valueFor(stream).getVolumeIndexMin()) ||
- (index > mStreams.valueFor(stream).getVolumeIndexMax())) {
+ if ((index < mVolumeCurves->getVolumeIndexMin(stream)) ||
+ (index > mVolumeCurves->getVolumeIndexMax(stream))) {
return BAD_VALUE;
}
if (!audio_is_output_device(device)) {
@@ -1787,7 +1786,7 @@
}
// Force max volume if stream cannot be muted
- if (!mStreams.canBeMuted(stream)) index = mStreams.valueFor(stream).getVolumeIndexMax();
+ if (!mVolumeCurves->canBeMuted(stream)) index = mVolumeCurves->getVolumeIndexMax(stream);
ALOGV("setStreamVolumeIndex() stream %d, device %04x, index %d",
stream, device, index);
@@ -1795,9 +1794,9 @@
// if device is AUDIO_DEVICE_OUT_DEFAULT set default value and
// clear all device specific values
if (device == AUDIO_DEVICE_OUT_DEFAULT) {
- mStreams.clearCurrentVolumeIndex(stream);
+ mVolumeCurves->clearCurrentVolumeIndex(stream);
}
- mStreams.addCurrentVolumeIndex(stream, device, index);
+ mVolumeCurves->addCurrentVolumeIndex(stream, device, index);
// update volume on all outputs whose current device is also selected by the same
// strategy as the device specified by the caller
@@ -1807,7 +1806,7 @@
//FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now
audio_devices_t accessibilityDevice = AUDIO_DEVICE_NONE;
if (stream == AUDIO_STREAM_MUSIC) {
- mStreams.addCurrentVolumeIndex(AUDIO_STREAM_ACCESSIBILITY, device, index);
+ mVolumeCurves->addCurrentVolumeIndex(AUDIO_STREAM_ACCESSIBILITY, device, index);
accessibilityDevice = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, true /*fromCache*/);
}
if ((device != AUDIO_DEVICE_OUT_DEFAULT) &&
@@ -1851,7 +1850,7 @@
}
device = Volume::getDeviceForVolume(device);
- *index = mStreams.valueFor(stream).getVolumeIndex(device);
+ *index = mVolumeCurves->getVolumeIndex(stream, device);
ALOGV("getStreamVolumeIndex() stream %d device %08x index %d", stream, device, *index);
return NO_ERROR;
}
@@ -2106,7 +2105,7 @@
mHwModules.dump(fd);
mOutputs.dump(fd);
mInputs.dump(fd);
- mStreams.dump(fd);
+ mVolumeCurves->dump(fd);
mEffects.dump(fd);
mAudioPatches.dump(fd);
@@ -2991,7 +2990,6 @@
#endif //AUDIO_POLICY_TEST
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mA2dpSuspended(false),
- mSpeakerDrcEnabled(false),
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
@@ -2999,6 +2997,35 @@
mTtsOutputAvailable(false),
mMasterMono(false)
{
+ mUidCached = getuid();
+ mpClientInterface = clientInterface;
+
+ // TODO: remove when legacy conf file is removed. true on devices that use DRC on the
+ // DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.
+ // Note: remove also speaker_drc_enabled from global configuration of XML config file.
+ bool speakerDrcEnabled = false;
+
+#ifdef USE_XML_AUDIO_POLICY_CONF
+ mVolumeCurves = new VolumeCurvesCollection();
+ AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
+ mDefaultOutputDevice, speakerDrcEnabled,
+ static_cast<VolumeCurvesCollection *>(mVolumeCurves));
+ PolicySerializer serializer;
+ if (serializer.deserialize(AUDIO_POLICY_XML_CONFIG_FILE, config) != NO_ERROR) {
+#else
+ mVolumeCurves = new StreamDescriptorCollection();
+ AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
+ mDefaultOutputDevice, speakerDrcEnabled);
+ if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
+ (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
+#endif
+ ALOGE("could not load audio policy configuration file, setting defaults");
+ config.setDefault();
+ }
+ // must be done after reading the policy (since conditionned by Speaker Drc Enabling)
+ mVolumeCurves->initializeVolumeCurves(speakerDrcEnabled);
+
+ // Once policy config has been parsed, retrieve an instance of the engine and initialize it.
audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
if (!engineInstance) {
ALOGE("%s: Could not get an instance of policy engine", __FUNCTION__);
@@ -3014,27 +3041,7 @@
status_t status = mEngine->initCheck();
ALOG_ASSERT(status == NO_ERROR, "Policy engine not initialized(err=%d)", status);
- mUidCached = getuid();
- mpClientInterface = clientInterface;
-
- AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
- mDefaultOutputDevice, mSpeakerDrcEnabled);
-
-#ifdef USE_XML_AUDIO_POLICY_CONF
- PolicySerializer serializer;
- if (serializer.deserialize(AUDIO_POLICY_XML_CONFIG_FILE, config) != NO_ERROR) {
-#else
- if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
- (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
-#endif
- ALOGE("could not load audio policy configuration file, setting defaults");
- config.setDefault();
- }
// mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
-
- // must be done after reading the policy (since conditionned by Speaker Drc Enabling)
- mEngine->initializeVolumeCurves(mSpeakerDrcEnabled);
-
// open all output streams needed to access attached devices
audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types();
audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
@@ -4731,11 +4738,10 @@
}
float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
- int index,
- audio_devices_t device)
+ int index,
+ audio_devices_t device)
{
- float volumeDb = mEngine->volIndexToDb(Volume::getDeviceCategory(device), stream, index);
-
+ float volumeDb = mVolumeCurves->volIndexToDb(stream, Volume::getDeviceCategory(device), index);
// if a headset is connected, apply the following rules to ring tones and notifications
// to avoid sound level bursts in user's ears:
// - always attenuate ring tones and notifications volume by 6dB
@@ -4751,7 +4757,7 @@
|| (stream == AUDIO_STREAM_SYSTEM)
|| ((stream_strategy == STRATEGY_ENFORCED_AUDIBLE) &&
(mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_NONE))) &&
- mStreams.canBeMuted(stream)) {
+ mVolumeCurves->canBeMuted(stream)) {
volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
// when the phone is ringing we must consider that music could have been paused just before
// by the music application and behave as if music was active if the last music track was
@@ -4760,8 +4766,9 @@
mLimitRingtoneVolume) {
audio_devices_t musicDevice = getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/);
float musicVolDB = computeVolume(AUDIO_STREAM_MUSIC,
- mStreams.valueFor(AUDIO_STREAM_MUSIC).getVolumeIndex(musicDevice),
- musicDevice);
+ mVolumeCurves->getVolumeIndex(AUDIO_STREAM_MUSIC,
+ musicDevice),
+ musicDevice);
float minVolDB = (musicVolDB > SONIFICATION_HEADSET_VOLUME_MIN_DB) ?
musicVolDB : SONIFICATION_HEADSET_VOLUME_MIN_DB;
if (volumeDb > minVolDB) {
@@ -4813,7 +4820,7 @@
float voiceVolume;
// Force voice volume to max for bluetooth SCO as volume is managed by the headset
if (stream == AUDIO_STREAM_VOICE_CALL) {
- voiceVolume = (float)index/(float)mStreams.valueFor(stream).getVolumeIndexMax();
+ voiceVolume = (float)index/(float)mVolumeCurves->getVolumeIndexMax(stream);
} else {
voiceVolume = 1.0;
}
@@ -4839,7 +4846,7 @@
continue;
}
checkAndSetVolume((audio_stream_type_t)stream,
- mStreams.valueFor((audio_stream_type_t)stream).getVolumeIndex(device),
+ mVolumeCurves->getVolumeIndex((audio_stream_type_t)stream, device),
outputDesc,
device,
delayMs,
@@ -4871,7 +4878,6 @@
int delayMs,
audio_devices_t device)
{
- const StreamDescriptor& streamDesc = mStreams.valueFor(stream);
if (device == AUDIO_DEVICE_NONE) {
device = outputDesc->device();
}
@@ -4881,7 +4887,7 @@
if (on) {
if (outputDesc->mMuteCount[stream] == 0) {
- if (streamDesc.canBeMuted() &&
+ if (mVolumeCurves->canBeMuted(stream) &&
((stream != AUDIO_STREAM_ENFORCED_AUDIBLE) ||
(mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_NONE))) {
checkAndSetVolume(stream, 0, outputDesc, device, delayMs);
@@ -4896,7 +4902,7 @@
}
if (--outputDesc->mMuteCount[stream] == 0) {
checkAndSetVolume(stream,
- streamDesc.getVolumeIndex(device),
+ mVolumeCurves->getVolumeIndex(stream, device),
outputDesc,
device,
delayMs);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 37faac2..18d03b0 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -33,7 +33,6 @@
#include <AudioGain.h>
#include <AudioPort.h>
#include <AudioPatch.h>
-#include <ConfigParsingUtils.h>
#include <DeviceDescriptor.h>
#include <IOProfile.h>
#include <HwModule.h>
@@ -42,8 +41,8 @@
#include <AudioPolicyMix.h>
#include <EffectDescriptor.h>
#include <SoundTriggerSession.h>
-#include <StreamDescriptor.h>
#include <SessionRoute.h>
+#include <VolumeCurve.h>
namespace android {
@@ -272,10 +271,7 @@
{
return mAvailableInputDevices;
}
- virtual StreamDescriptorCollection &getStreamDescriptors()
- {
- return mStreams;
- }
+ virtual IVolumeCurvesCollection &getVolumeCurves() { return *mVolumeCurves; }
virtual const sp<DeviceDescriptor> &getDefaultOutputDevice() const
{
return mDefaultOutputDevice;
@@ -531,7 +527,8 @@
SessionRouteMap mOutputRoutes = SessionRouteMap(SessionRouteMap::MAPTYPE_OUTPUT);
SessionRouteMap mInputRoutes = SessionRouteMap(SessionRouteMap::MAPTYPE_INPUT);
- StreamDescriptorCollection mStreams; // stream descriptors for volume control
+ IVolumeCurvesCollection *mVolumeCurves; // Volume Curves per use case and device category
+
bool mLimitRingtoneVolume; // limit ringtone volume to music volume if headset connected
audio_devices_t mDeviceForStrategy[NUM_STRATEGIES];
float mLastVoiceVolume; // last voice volume value sent to audio HAL
@@ -539,9 +536,6 @@
EffectDescriptorCollection mEffects; // list of registered audio effects
bool mA2dpSuspended; // true if A2DP output is suspended
sp<DeviceDescriptor> mDefaultOutputDevice; // output device selected by default at boot time
- bool mSpeakerDrcEnabled;// true on devices that use DRC on the DEVICE_CATEGORY_SPEAKER path
- // to boost soft sounds, used to adjust volume curves accordingly
-
HwModuleCollection mHwModules;
volatile int32_t mAudioPortGeneration;
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 9ba8f3f..d416353 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -46,6 +46,7 @@
device3/Camera3ZslStream.cpp \
device3/Camera3DummyStream.cpp \
device3/StatusTracker.cpp \
+ device3/Camera3BufferManager.cpp \
gui/RingBufferConsumer.cpp \
utils/CameraTraces.cpp \
utils/AutoConditionLock.cpp
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 4be2c92..fcdcdb5 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -56,6 +56,10 @@
#include "api2/CameraDeviceClient.h"
#include "utils/CameraTraces.h"
+namespace {
+ const char* kPermissionServiceName = "permission";
+}; // namespace anonymous
+
namespace android {
// ----------------------------------------------------------------------------
@@ -1920,6 +1924,37 @@
mServicePid = servicePid;
mOpsActive = false;
mDestructionStarted = false;
+
+ // In some cases the calling code has no access to the package it runs under.
+ // For example, NDK camera API.
+ // In this case we will get the packages for the calling UID and pick the first one
+ // for attributing the app op. This will work correctly for runtime permissions
+ // as for legacy apps we will toggle the app op for all packages in the UID.
+ // The caveat is that the operation may be attributed to the wrong package and
+ // stats based on app ops may be slightly off.
+ if (mClientPackageName.size() <= 0) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16(kPermissionServiceName));
+ if (binder == 0) {
+ ALOGE("Cannot get permission service");
+ // Leave mClientPackageName unchanged (empty) and the further interaction
+ // with camera will fail in BasicClient::startCameraOps
+ return;
+ }
+
+ sp<IPermissionController> permCtrl = interface_cast<IPermissionController>(binder);
+ Vector<String16> packages;
+
+ permCtrl->getPackagesForUid(mClientUid, packages);
+
+ if (packages.isEmpty()) {
+ ALOGE("No packages for calling UID");
+ // Leave mClientPackageName unchanged (empty) and the further interaction
+ // with camera will fail in BasicClient::startCameraOps
+ return;
+ }
+ mClientPackageName = packages[0];
+ }
}
CameraService::BasicClient::~BasicClient() {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 5877c65..c1c2aef 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -244,13 +244,13 @@
bool mDestructionStarted;
// these are initialized in the constructor.
- sp<CameraService> mCameraService; // immutable after constructor
- int mCameraId; // immutable after constructor
- int mCameraFacing; // immutable after constructor
- const String16 mClientPackageName;
+ sp<CameraService> mCameraService; // immutable after constructor
+ int mCameraId; // immutable after constructor
+ int mCameraFacing; // immutable after constructor
+ String16 mClientPackageName; // immutable after constructor
pid_t mClientPid;
- uid_t mClientUid; // immutable after constructor
- pid_t mServicePid; // immutable after constructor
+ uid_t mClientUid; // immutable after constructor
+ pid_t mServicePid; // immutable after constructor
bool mDisconnected;
// - The app-side Binder interface to receive callbacks from us
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index bd9fea3..6b60307 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -456,11 +456,12 @@
return BAD_VALUE;
}
- int streamId = -1;
+ // TODO: Hookup the stream set id with upper layer.
+ int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
res = mDevice->createStream(surface, width, height, format, dataSpace,
static_cast<camera3_stream_rotation_t>
(outputConfiguration.getRotation()),
- &streamId);
+ &streamId, outputConfiguration.getSurfaceSetID());
if (res == OK) {
mStreamMap.add(binder, streamId);
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 7b083a3..6fd2b39 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -31,6 +31,7 @@
#include "camera/CaptureResult.h"
#include "common/CameraModule.h"
#include "gui/IGraphicBufferProducer.h"
+#include "device3/Camera3StreamInterface.h"
namespace android {
@@ -108,7 +109,8 @@
*/
virtual status_t createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id) = 0;
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID) = 0;
/**
* Create an input stream of width, height, and format.
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
new file mode 100644
index 0000000..b2a3076
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
@@ -0,0 +1,403 @@
+/*
+ * Copyright 2016 The Android Open Source 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Camera3-BufferManager"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+
+#include <gui/ISurfaceComposer.h>
+#include <private/gui/ComposerService.h>
+#include <utils/Log.h>
+#include <utils/Trace.h>
+#include "utils/CameraTraces.h"
+#include "Camera3BufferManager.h"
+
+namespace android {
+
+namespace camera3 {
+
+Camera3BufferManager::Camera3BufferManager(const sp<IGraphicBufferAlloc>& allocator) :
+ mAllocator(allocator) {
+ if (allocator == NULL) {
+ sp<ISurfaceComposer> composer(ComposerService::getComposerService());
+ mAllocator = composer->createGraphicBufferAlloc();
+ if (mAllocator == NULL) {
+ ALOGE("createGraphicBufferAlloc failed");
+ }
+ }
+}
+
+Camera3BufferManager::~Camera3BufferManager() {
+}
+
+status_t Camera3BufferManager::registerStream(const StreamInfo& streamInfo) {
+ ATRACE_CALL();
+
+ int streamId = streamInfo.streamId;
+ int streamSetId = streamInfo.streamSetId;
+
+ if (streamId == CAMERA3_STREAM_ID_INVALID || streamSetId == CAMERA3_STREAM_SET_ID_INVALID) {
+ ALOGE("%s: Stream id (%d) or stream set id (%d) is invalid",
+ __FUNCTION__, streamId, streamSetId);
+ return BAD_VALUE;
+ }
+ if (streamInfo.totalBufferCount > kMaxBufferCount || streamInfo.totalBufferCount == 0) {
+ ALOGE("%s: Stream id (%d) with stream set id (%d) total buffer count %zu is invalid",
+ __FUNCTION__, streamId, streamSetId, streamInfo.totalBufferCount);
+ return BAD_VALUE;
+ }
+ if (!streamInfo.isConfigured) {
+ ALOGE("%s: Stream (%d) is not configured", __FUNCTION__, streamId);
+ return BAD_VALUE;
+ }
+
+ // For Gralloc v1, try to allocate a buffer and see if it is successful, otherwise, stream
+ // buffer sharing for this newly added stream is not supported. For Gralloc v0, we don't
+ // need check this, as the buffers are not really shared between streams, the buffers are
+ // allocated for each stream individually, the allocation failure will be checked in
+ // getBufferForStream() call.
+ if (mGrallocVersion > HARDWARE_DEVICE_API_VERSION(0,1)) {
+ // TODO: To be implemented.
+
+ // In case allocation fails, return invalid operation
+ return INVALID_OPERATION;
+ }
+
+ Mutex::Autolock l(mLock);
+ if (mAllocator == NULL) {
+ ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ // Check if this stream was registered with different stream set ID, if so, error out.
+ for (size_t i = 0; i < mStreamSetMap.size(); i++) {
+ ssize_t streamIdx = mStreamSetMap[i].streamInfoMap.indexOfKey(streamId);
+ if (streamIdx != NAME_NOT_FOUND &&
+ mStreamSetMap[i].streamInfoMap[streamIdx].streamSetId != streamInfo.streamSetId) {
+ ALOGE("%s: It is illegal to register the same stream id with different stream set",
+ __FUNCTION__);
+ return BAD_VALUE;
+ }
+ }
+ // Check if there is an existing stream set registered; if not, create one; otherwise, add this
+ // stream info to the existing stream set entry.
+ ssize_t setIdx = mStreamSetMap.indexOfKey(streamSetId);
+ if (setIdx == NAME_NOT_FOUND) {
+ ALOGV("%s: stream set %d is not registered to stream set map yet, create it.",
+ __FUNCTION__, streamSetId);
+ // Create stream info map, then add to mStreamsetMap.
+ StreamSet newStreamSet;
+ setIdx = mStreamSetMap.add(streamSetId, newStreamSet);
+ }
+ // Update stream set map and water mark.
+ StreamSet& currentStreamSet = mStreamSetMap.editValueAt(setIdx);
+ ssize_t streamIdx = currentStreamSet.streamInfoMap.indexOfKey(streamId);
+ if (streamIdx != NAME_NOT_FOUND) {
+ ALOGW("%s: stream %d was already registered with stream set %d",
+ __FUNCTION__, streamId, streamSetId);
+ return OK;
+ }
+ currentStreamSet.streamInfoMap.add(streamId, streamInfo);
+ currentStreamSet.handoutBufferCountMap.add(streamId, 0);
+
+ // The watermark should be the max of buffer count of each stream inside a stream set.
+ if (streamInfo.totalBufferCount > currentStreamSet.allocatedBufferWaterMark) {
+ currentStreamSet.allocatedBufferWaterMark = streamInfo.totalBufferCount;
+ }
+
+ return OK;
+}
+
+status_t Camera3BufferManager::unregisterStream(int streamId, int streamSetId) {
+ ATRACE_CALL();
+ Mutex::Autolock l(mLock);
+ ALOGV("%s: unregister stream %d with stream set %d", __FUNCTION__,
+ streamId, streamSetId);
+ if (mAllocator == NULL) {
+ ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ if (!checkIfStreamRegisteredLocked(streamId, streamSetId)){
+ ALOGE("%s: stream %d with set id %d wasn't properly registered to this buffer manager!",
+ __FUNCTION__, streamId, streamSetId);
+ return BAD_VALUE;
+ }
+
+ // De-list all the buffers associated with this stream first.
+ StreamSet& currentSet = mStreamSetMap.editValueFor(streamSetId);
+ BufferList& freeBufs = currentSet.freeBuffers;
+ BufferCountMap& handOutBufferCounts = currentSet.handoutBufferCountMap;
+ InfoMap& infoMap = currentSet.streamInfoMap;
+ removeBuffersFromBufferListLocked(freeBufs, streamId);
+ handOutBufferCounts.removeItem(streamId);
+
+ // Remove the stream info from info map and recalculate the buffer count water mark.
+ infoMap.removeItem(streamId);
+ currentSet.allocatedBufferWaterMark = 0;
+ for (size_t i = 0; i < infoMap.size(); i++) {
+ if (infoMap[i].totalBufferCount > currentSet.allocatedBufferWaterMark) {
+ currentSet.allocatedBufferWaterMark = infoMap[i].totalBufferCount;
+ }
+ }
+
+ // Remove this stream set if all its streams have been removed.
+ if (freeBufs.size() == 0 && handOutBufferCounts.size() == 0 && infoMap.size() == 0) {
+ mStreamSetMap.removeItem(streamSetId);
+ }
+
+ return OK;
+}
+
+status_t Camera3BufferManager::getBufferForStream(int streamId, int streamSetId,
+ sp<GraphicBuffer>* gb, int* fenceFd) {
+ ATRACE_CALL();
+
+ Mutex::Autolock l(mLock);
+ ALOGV("%s: get buffer for stream %d with stream set %d", __FUNCTION__,
+ streamId, streamSetId);
+ if (mAllocator == NULL) {
+ ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ if (!checkIfStreamRegisteredLocked(streamId, streamSetId)) {
+ ALOGE("%s: stream %d is not registered with stream set %d yet!!!",
+ __FUNCTION__, streamId, streamSetId);
+ return BAD_VALUE;
+ }
+
+ StreamSet &streamSet = mStreamSetMap.editValueFor(streamSetId);
+ GraphicBufferEntry buffer =
+ getFirstBufferFromBufferListLocked(streamSet.freeBuffers, streamId);
+
+ if (mGrallocVersion < HARDWARE_DEVICE_API_VERSION(1,0)) {
+ // Allocate one if there is no free buffer available.
+ if (buffer.graphicBuffer == nullptr) {
+ const StreamInfo& info = streamSet.streamInfoMap.valueFor(streamId);
+ status_t res = OK;
+ buffer.fenceFd = -1;
+ buffer.graphicBuffer = mAllocator->createGraphicBuffer(
+ info.width, info.height, info.format, info.combinedUsage, &res);
+ ALOGV("%s: allocate a new graphic buffer %p with handle %p",
+ __FUNCTION__, buffer.graphicBuffer.get(), buffer.graphicBuffer->handle);
+ if (res != OK) {
+ ALOGE("%s: graphic buffer allocation failed: (error %d %s) ",
+ __FUNCTION__, res, strerror(-res));
+ return res;
+ }
+ }
+
+ // Increase the hand-out buffer count for tracking purpose.
+ BufferCountMap& handOutBufferCounts = streamSet.handoutBufferCountMap;
+ size_t& bufferCount = handOutBufferCounts.editValueFor(streamId);
+ bufferCount++;
+
+ *gb = buffer.graphicBuffer;
+ *fenceFd = buffer.fenceFd;
+ ALOGV("%s: get buffer (%p) with handle (%p).",
+ __FUNCTION__, buffer.graphicBuffer.get(), buffer.graphicBuffer->handle);
+
+ // Proactively free buffers for other streams if the current number of allocated buffers
+ // exceeds the water mark. This only for Gralloc V1, for V2, this logic can also be handled
+ // in returnBufferForStream() if we want to free buffer more quickly.
+ // TODO: probably should find out all the inactive stream IDs, and free the firstly found
+ // buffers for them.
+ StreamId firstOtherStreamId = CAMERA3_STREAM_ID_INVALID;
+ if (streamSet.streamInfoMap.size() > 1) {
+ for (size_t i = 0; i < streamSet.streamInfoMap.size(); i++) {
+ firstOtherStreamId = streamSet.streamInfoMap[i].streamId;
+ if (firstOtherStreamId != streamId) {
+ break;
+ }
+ }
+ if (firstOtherStreamId == CAMERA3_STREAM_ID_INVALID) {
+ return OK;
+ }
+
+ // This will drop the reference to one free buffer, which will effectively free one
+ // buffer (from the free buffer list) for the inactive streams.
+ size_t totalAllocatedBufferCount = streamSet.freeBuffers.size();
+ for (size_t i = 0; i < streamSet.handoutBufferCountMap.size(); i++) {
+ totalAllocatedBufferCount += streamSet.handoutBufferCountMap[i];
+ }
+ if (totalAllocatedBufferCount > streamSet.allocatedBufferWaterMark) {
+ getFirstBufferFromBufferListLocked(streamSet.freeBuffers, firstOtherStreamId);
+ }
+ }
+ } else {
+ // TODO: implement this.
+ return BAD_VALUE;
+ }
+
+ return OK;
+}
+
+status_t Camera3BufferManager::returnBufferForStream(int streamId,
+ int streamSetId, const sp<GraphicBuffer>& buffer, int fenceFd) {
+ ATRACE_CALL();
+ Mutex::Autolock l(mLock);
+ ALOGV_IF(buffer != 0, "%s: return buffer (%p) with handle (%p) for stream %d and stream set %d",
+ __FUNCTION__, buffer.get(), buffer->handle, streamId, streamSetId);
+ if (mAllocator == NULL) {
+ ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ if (!checkIfStreamRegisteredLocked(streamId, streamSetId)){
+ ALOGV("%s: returning buffer for an already unregistered stream (stream %d with set id %d),"
+ "buffer will be dropped right away!", __FUNCTION__, streamId, streamSetId);
+ return OK;
+ }
+
+ if (mGrallocVersion < HARDWARE_DEVICE_API_VERSION(1,0)) {
+ // Add to the freeBuffer list.
+ StreamSet& streamSet = mStreamSetMap.editValueFor(streamSetId);
+ if (buffer != 0) {
+ BufferEntry entry;
+ entry.add(streamId, GraphicBufferEntry(buffer, fenceFd));
+ status_t res = addBufferToBufferListLocked(streamSet.freeBuffers, entry);
+ if (res != OK) {
+ ALOGE("%s: add buffer to free buffer list failed", __FUNCTION__);
+ return res;
+ }
+ }
+
+ // Update the hand-out buffer count for this buffer.
+ BufferCountMap& handOutBufferCounts = streamSet.handoutBufferCountMap;
+ size_t& bufferCount = handOutBufferCounts.editValueFor(streamId);
+ bufferCount--;
+ } else {
+ // TODO: implement this.
+ return BAD_VALUE;
+ }
+
+ return OK;
+}
+
+void Camera3BufferManager::dump(int fd, const Vector<String16>& args) const {
+ Mutex::Autolock l(mLock);
+
+ (void) args;
+ String8 lines;
+ lines.appendFormat(" Total stream sets: %zu\n", mStreamSetMap.size());
+ for (size_t i = 0; i < mStreamSetMap.size(); i++) {
+ lines.appendFormat(" Stream set %d has below streams:\n", mStreamSetMap.keyAt(i));
+ for (size_t j = 0; j < mStreamSetMap[i].streamInfoMap.size(); j++) {
+ lines.appendFormat(" Stream %d\n", mStreamSetMap[i].streamInfoMap[j].streamId);
+ }
+ lines.appendFormat(" Stream set buffer count water mark: %zu\n",
+ mStreamSetMap[i].allocatedBufferWaterMark);
+ lines.appendFormat(" Handout buffer counts:\n");
+ for (size_t m = 0; m < mStreamSetMap[i].handoutBufferCountMap.size(); m++) {
+ int streamId = mStreamSetMap[i].handoutBufferCountMap.keyAt(m);
+ size_t bufferCount = mStreamSetMap[i].handoutBufferCountMap.valueAt(m);
+ lines.appendFormat(" stream id: %d, buffer count: %zu.\n",
+ streamId, bufferCount);
+ }
+
+ lines.appendFormat(" Free buffer count: %zu\n",
+ mStreamSetMap[i].freeBuffers.size());
+ for (auto& bufEntry : mStreamSetMap[i].freeBuffers) {
+ for (size_t m = 0; m < bufEntry.size(); m++) {
+ const sp<GraphicBuffer>& buffer = bufEntry.valueAt(m).graphicBuffer;
+ int streamId = bufEntry.keyAt(m);
+ lines.appendFormat(" stream id: %d, buffer: %p, handle: %p.\n",
+ streamId, buffer.get(), buffer->handle);
+ }
+ }
+ }
+ write(fd, lines.string(), lines.size());
+}
+
+bool Camera3BufferManager::checkIfStreamRegisteredLocked(int streamId, int streamSetId) const {
+ ssize_t setIdx = mStreamSetMap.indexOfKey(streamSetId);
+ if (setIdx == NAME_NOT_FOUND) {
+ ALOGV("%s: stream set %d is not registered to stream set map yet!",
+ __FUNCTION__, streamSetId);
+ return false;
+ }
+
+ ssize_t streamIdx = mStreamSetMap.valueAt(setIdx).streamInfoMap.indexOfKey(streamId);
+ if (streamIdx == NAME_NOT_FOUND) {
+ ALOGV("%s: stream %d is not registered to stream info map yet!", __FUNCTION__, streamId);
+ return false;
+ }
+
+ size_t bufferWaterMark = mStreamSetMap[setIdx].allocatedBufferWaterMark;
+ if (bufferWaterMark == 0 || bufferWaterMark > kMaxBufferCount) {
+ ALOGW("%s: stream %d with stream set %d is not registered correctly to stream set map,"
+ " as the water mark (%zu) is wrong!",
+ __FUNCTION__, streamId, streamSetId, bufferWaterMark);
+ return false;
+ }
+
+ return true;
+}
+
+status_t Camera3BufferManager::addBufferToBufferListLocked(BufferList& bufList,
+ const BufferEntry& buffer) {
+ // TODO: need add some sanity check here.
+ bufList.push_back(buffer);
+
+ return OK;
+}
+
+status_t Camera3BufferManager::removeBuffersFromBufferListLocked(BufferList& bufferList,
+ int streamId) {
+ BufferList::iterator i = bufferList.begin();
+ while (i != bufferList.end()) {
+ ssize_t idx = i->indexOfKey(streamId);
+ if (idx != NAME_NOT_FOUND) {
+ i->removeItem(streamId);
+ if (i->isEmpty()) {
+ i = bufferList.erase(i);
+ }
+ break;
+ } else {
+ i++;
+ }
+ }
+
+ ALOGW_IF(i == bufferList.end(), "%s: Unable to find buffers for stream %d",
+ __FUNCTION__, streamId);
+
+ return OK;
+}
+
+Camera3BufferManager::GraphicBufferEntry Camera3BufferManager::getFirstBufferFromBufferListLocked(
+ BufferList& buffers, int streamId) {
+ // Try to get the first buffer from the free buffer list if there is one.
+ GraphicBufferEntry entry;
+ BufferList::iterator i = buffers.begin();
+ while (i != buffers.end()) {
+ ssize_t idx = i->indexOfKey(streamId);
+ if (idx != NAME_NOT_FOUND) {
+ entry = GraphicBufferEntry(i->valueAt(idx));
+ i = buffers.erase(i);
+ break;
+ } else {
+ i++;
+ }
+ }
+
+ ALOGV_IF(entry.graphicBuffer == 0, "%s: Unable to find free buffer for stream %d",
+ __FUNCTION__, streamId);
+ return entry;
+}
+
+} // namespace camera3
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.h b/services/camera/libcameraservice/device3/Camera3BufferManager.h
new file mode 100644
index 0000000..0b4f55c
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.h
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2016 The Android Open Source 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_SERVERS_CAMERA3_BUFFER_MANAGER_H
+#define ANDROID_SERVERS_CAMERA3_BUFFER_MANAGER_H
+
+#include <list>
+#include <algorithm>
+#include <ui/GraphicBuffer.h>
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include "Camera3OutputStream.h"
+
+namespace android {
+
+namespace camera3 {
+
+struct StreamInfo;
+
+/**
+ * A class managing the graphic buffers that is used by camera output streams. It allocates and
+ * hands out Gralloc buffers to the clients (e.g., Camera3OutputStream) based on the requests.
+ * When clients request a buffer, buffer manager will pick a buffer if there are some already
+ * allocated buffer available, will allocate a buffer otherwise. When there are too many allocated
+ * buffer maintained by the buffer manager, it will dynamically deallocate some buffers that are
+ * solely owned by this buffer manager.
+ * In doing so, it reduces the memory footprint unless it is already minimal without impacting
+ * performance.
+ *
+ */
+class Camera3BufferManager: public virtual RefBase {
+public:
+ Camera3BufferManager(const sp<IGraphicBufferAlloc>& allocator = NULL);
+
+ virtual ~Camera3BufferManager();
+
+ /**
+ * This method registers an output stream to this buffer manager by using the provided stream
+ * information.
+ *
+ * The stream info includes the necessary information such as stream size, format, buffer count,
+ * usage flags, etc. for the buffer manager to allocate and hand out buffers for this stream.
+ *
+ * It's illegal to call this method if the stream is not CONFIGURED yet, as some critical
+ * stream properties (e.g., combined usage flags) are only available in this state. It is also
+ * illegal to call this method with an invalid stream set ID (CAMERA3_STREAM_SET_ID_INVALID),
+ * as the invalid stream set ID indicates that this stream doesn't intend to use buffer manager.
+ *
+ *
+ * Once a stream is successfully registered to this buffer manager, the buffer manager takes
+ * over the buffer allocation role and provides buffers to this stream via getBufferForStream().
+ * The returned buffer can be sent to the camera HAL for image output, and then queued to the
+ * ANativeWindow (Surface) for downstream consumer to acquire. Once the image buffer is released
+ * by the consumer end point, the BufferQueueProducer callback onBufferReleased will call
+ * returnBufferForStream() to return the free buffer to this buffer manager. If the stream
+ * uses buffer manager to manage the stream buffers, it should disable the BufferQueue
+ * allocation via IGraphicBufferProducer::allowAllocation(false).
+ *
+ * Registering an already registered stream has no effect.
+ *
+ * Return values:
+ *
+ * OK: Registration of the new stream was successful.
+ * BAD_VALUE: This stream is not at CONFIGURED state, or the stream ID or stream set
+ * ID are invalid, or attempting to register the same stream to multiple
+ * stream sets, or other stream properties are invalid.
+ * INVALID_OPERATION: This buffer manager doesn't support buffer sharing across this stream
+ * and other streams that were already registered with the same stream set
+ * ID.
+ */
+ status_t registerStream(const StreamInfo &streamInfo);
+
+ /**
+ * This method unregisters a stream from this buffer manager.
+ *
+ * After a stream is unregistered, further getBufferForStream() calls will fail for this stream.
+ * After all streams for a given stream set are unregistered, all the buffers solely owned (for
+ * this stream set) by this buffer manager will be freed; all buffers subsequently returned to
+ * this buffer manager for this stream set will be freed immediately.
+ *
+ * Return values:
+ *
+ * OK: Removal of the a stream from this buffer manager was successful.
+ * BAD_VALUE: stream ID or stream set ID are invalid, or stream ID and stream set ID
+ * combination doesn't match what was registered, or this stream wasn't registered
+ * to this buffer manager before.
+ */
+ status_t unregisterStream(int streamId, int streamSetId);
+
+ /**
+ * This method obtains a buffer for a stream from this buffer manager.
+ *
+ * This method returns the first free buffer from the free buffer list (associated with this
+ * stream set) if there is any. Otherwise, it will allocate a buffer for this stream, return
+ * it and increment its count of handed-out buffers. When the total number of allocated buffers
+ * is too high, it may deallocate the unused buffers to save memory footprint of this stream
+ * set.
+ *
+ * After this call, the client takes over the ownership of this buffer if it is not freed.
+ *
+ * Return values:
+ *
+ * OK: Getting buffer for this stream was successful.
+ * BAD_VALUE: stream ID or streamSetId are invalid, or stream ID and stream set ID
+ * combination doesn't match what was registered, or this stream wasn't registered
+ * to this buffer manager before.
+ * NO_MEMORY: Unable to allocate a buffer for this stream at this time.
+ */
+ status_t getBufferForStream(int streamId, int streamSetId, sp<GraphicBuffer>* gb, int* fenceFd);
+
+ /**
+ * This method returns a buffer for a stream to this buffer manager.
+ *
+ * When a buffer is returned, it is treated as a free buffer and may either be reused for future
+ * getBufferForStream() calls, or freed if there total number of outstanding allocated buffers
+ * is too large. The latter only applies to the case where the buffer are physically shared
+ * between streams in the same stream set. A physically shared buffer is the buffer that has one
+ * physical back store but multiple handles. Multiple stream can access the same physical memory
+ * with their own handles. Physically shared buffer can only be supported by Gralloc HAL V1.
+ * See hardware/libhardware/include/hardware/gralloc1.h for more details.
+ *
+ *
+ * This call takes the ownership of the returned buffer if it was allocated by this buffer
+ * manager; clients should not use this buffer after this call. Attempting to access this buffer
+ * after this call will have undefined behavior. Holding a reference to this buffer after this
+ * call may cause memory leakage. If a BufferQueue is used to track the buffers handed out by
+ * this buffer queue, it is recommended to call detachNextBuffer() from the buffer queue after
+ * BufferQueueProducer onBufferReleased callback is fired, and return it to this buffer manager.
+ *
+ * OK: Buffer return for this stream was successful.
+ * BAD_VALUE: stream ID or streamSetId are invalid, or stream ID and stream set ID combination
+ * doesn't match what was registered, or this stream wasn't registered to this
+ * buffer manager before.
+ */
+ status_t returnBufferForStream(int streamId, int streamSetId, const sp<GraphicBuffer>& buffer,
+ int fenceFd);
+
+ /**
+ * Dump the buffer manager statistics.
+ */
+ void dump(int fd, const Vector<String16> &args) const;
+
+private:
+ /**
+ * Lock to synchronize the access to the methods of this class.
+ */
+ mutable Mutex mLock;
+
+ static const size_t kMaxBufferCount = BufferQueueDefs::NUM_BUFFER_SLOTS;
+
+ /**
+ * mAllocator is the connection to SurfaceFlinger that is used to allocate new GraphicBuffer
+ * objects.
+ */
+ sp<IGraphicBufferAlloc> mAllocator;
+
+ struct GraphicBufferEntry {
+ sp<GraphicBuffer> graphicBuffer;
+ int fenceFd;
+ GraphicBufferEntry(const sp<GraphicBuffer>& gb = 0, int fd = -1) :
+ graphicBuffer(gb),
+ fenceFd(fd) {}
+ };
+
+ /**
+ * A buffer entry (indexed by stream ID) represents a single physically allocated buffer. For
+ * Gralloc V0, since each physical buffer is associated with one stream, this is
+ * a single entry map. For Gralloc V1, one physical buffer can be shared between different
+ * streams in one stream set, so this entry may include multiple entries, where the different
+ * graphic buffers have the same common Gralloc backing store.
+ */
+ typedef int StreamId;
+ typedef KeyedVector<StreamId, GraphicBufferEntry> BufferEntry;
+
+ typedef std::list<BufferEntry> BufferList;
+
+ /**
+ * Stream info map (indexed by stream ID) tracks all the streams registered to a particular
+ * stream set.
+ */
+ typedef KeyedVector<StreamId, StreamInfo> InfoMap;
+
+ /**
+ * Stream set buffer count map (indexed by stream ID) tracks all buffer counts of the streams
+ * registered to a particular stream set.
+ */
+ typedef KeyedVector<StreamId, size_t> BufferCountMap;
+
+ /**
+ * StreamSet keeps track of the stream info, free buffer list and hand-out buffer counts for
+ * each stream set.
+ */
+ struct StreamSet {
+ /**
+ * Stream set buffer count water mark representing the max number of allocated buffers
+ * (hand-out buffers + free buffers) count for each stream set. For a given stream set, when
+ * getBufferForStream() is called on this buffer manager, if the total allocated buffer
+ * count exceeds this water mark, the buffer manager will attempt to reduce it as follows:
+ *
+ * In getBufferForStream(), find a buffer associated with other streams (inside the same
+ * stream set) on the free buffer list and free it. For Gralloc V1, can just free the top
+ * of the free buffer list if the physical buffer sharing in this stream is supported.
+ *
+ * For a particular stream set, a larger allocatedBufferWaterMark increases the memory
+ * footprint of the stream set, but reduces the chance that getBufferForStream() will have
+ * to allocate a new buffer. We assume that the streams in one stream set are not streaming
+ * simultaneously, the max allocated buffer count water mark for a stream set will the max
+ * of all streams' total buffer counts. This will avoid new buffer allocation in steady
+ * streaming state.
+ */
+ size_t allocatedBufferWaterMark;
+ /**
+ * The stream info for all streams in this set
+ */
+ InfoMap streamInfoMap;
+ /**
+ * The free buffer list for all the buffers belong to this set. The free buffers are
+ * returned by the returnBufferForStream() call, and available for reuse.
+ */
+ BufferList freeBuffers;
+ /**
+ * The count of the buffers that were handed out to the streams of this set.
+ */
+ BufferCountMap handoutBufferCountMap;
+ StreamSet() {
+ allocatedBufferWaterMark = 0;
+ }
+ };
+
+ /**
+ * Stream set map managed by this buffer manager.
+ */
+ typedef int StreamSetId;
+ KeyedVector<StreamSetId, StreamSet> mStreamSetMap;
+
+ // TODO: There is no easy way to query the Gralloc version in this code yet, we have different
+ // code paths for different Gralloc versions, hardcode something here for now.
+ const uint32_t mGrallocVersion = GRALLOC_DEVICE_API_VERSION_0_1;
+
+ /**
+ * Check if this stream was successfully registered already. This method needs to be called with
+ * mLock held.
+ */
+ bool checkIfStreamRegisteredLocked(int streamId, int streamSetId) const;
+
+ /**
+ * Add a buffer entry to the BufferList. This method needs to be called with mLock held.
+ */
+ status_t addBufferToBufferListLocked(BufferList &bufList, const BufferEntry &buffer);
+
+ /**
+ * Remove all buffers from the BufferList.
+ *
+ * Note that this doesn't mean that the buffers are freed after this call. A buffer is freed
+ * only if all other references to it are dropped.
+ *
+ * This method needs to be called with mLock held.
+ */
+ status_t removeBuffersFromBufferListLocked(BufferList &bufList, int streamId);
+
+ /**
+ * Get the first available buffer from the buffer list for this stream. The graphicBuffer inside
+ * this entry will be NULL if there is no any GraphicBufferEntry found. After this call, the
+ * GraphicBufferEntry will be removed from the BufferList if a GraphicBufferEntry is found.
+ *
+ * This method needs to be called with mLock held.
+ *
+ */
+ GraphicBufferEntry getFirstBufferFromBufferListLocked(BufferList& buffers, int streamId);
+};
+
+} // namespace camera3
+} // namespace android
+
+#endif // ANDROID_SERVERS_CAMERA3_BUFFER_MANAGER_H
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 6c07aef..ea1e5f6 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -167,6 +167,9 @@
return res;
}
+ /** Create buffer manager */
+ mBufferManager = new Camera3BufferManager();
+
bool aeLockAvailable = false;
camera_metadata_ro_entry aeLockAvailableEntry;
res = find_camera_metadata_ro_entry(info.static_camera_characteristics,
@@ -293,6 +296,7 @@
mRequestThread.clear();
mStatusTracker.clear();
+ mBufferManager.clear();
hal3Device = mHal3Device;
}
@@ -502,6 +506,10 @@
mOutputStreams[i]->dump(fd,args);
}
+ lines = String8(" Camera3 Buffer Manager:\n");
+ write(fd, lines.string(), lines.size());
+ mBufferManager->dump(fd, args);
+
lines = String8(" In-flight requests:\n");
if (mInFlightMap.size() == 0) {
lines.append(" None\n");
@@ -926,7 +934,7 @@
status_t Camera3Device::createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format, android_dataspace dataSpace,
- camera3_stream_rotation_t rotation, int *id) {
+ camera3_stream_rotation_t rotation, int *id, int streamSetId) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
@@ -963,6 +971,11 @@
assert(mStatus != STATUS_ACTIVE);
sp<Camera3OutputStream> newStream;
+ // Overwrite stream set id to invalid for HAL3.1 or lower, as buffer manager does support
+ // such devices.
+ if (mDeviceVersion < CAMERA_DEVICE_API_VERSION_3_2) {
+ streamSetId = CAMERA3_STREAM_SET_ID_INVALID;
+ }
if (format == HAL_PIXEL_FORMAT_BLOB) {
ssize_t blobBufferSize;
if (dataSpace != HAL_DATASPACE_DEPTH) {
@@ -979,7 +992,7 @@
}
}
newStream = new Camera3OutputStream(mNextStreamId, consumer,
- width, height, blobBufferSize, format, dataSpace, rotation);
+ width, height, blobBufferSize, format, dataSpace, rotation, streamSetId);
} else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height);
if (rawOpaqueBufferSize <= 0) {
@@ -987,13 +1000,22 @@
return BAD_VALUE;
}
newStream = new Camera3OutputStream(mNextStreamId, consumer,
- width, height, rawOpaqueBufferSize, format, dataSpace, rotation);
+ width, height, rawOpaqueBufferSize, format, dataSpace, rotation, streamSetId);
} else {
newStream = new Camera3OutputStream(mNextStreamId, consumer,
- width, height, format, dataSpace, rotation);
+ width, height, format, dataSpace, rotation, streamSetId);
}
newStream->setStatusTracker(mStatusTracker);
+ /**
+ * Camera3 Buffer manager is only supported by HAL3.2 onwards, as the older HALs requires
+ * buffers to be statically allocated for internal static buffer registration, while the
+ * buffers provided by buffer manager are really dynamically allocated.
+ */
+ if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) {
+ newStream->setBufferManager(mBufferManager);
+ }
+
res = mOutputStreams.add(mNextStreamId, newStream);
if (res < 0) {
SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 7e20b0d..f70a153 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -29,6 +29,7 @@
#include "common/CameraDeviceBase.h"
#include "device3/StatusTracker.h"
+#include "device3/Camera3BufferManager.h"
/**
* Function pointer types with C calling convention to
@@ -97,7 +98,8 @@
// stream, reconfiguring device, and unpausing.
virtual status_t createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id);
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID);
virtual status_t createInputStream(
uint32_t width, uint32_t height, int format,
int *id);
@@ -721,6 +723,13 @@
sp<camera3::StatusTracker> mStatusTracker;
/**
+ * Graphic buffer manager for output streams. Each device has a buffer manager, which is used
+ * by the output streams to get and return buffers if these streams are registered to this
+ * buffer manager.
+ */
+ sp<camera3::Camera3BufferManager> mBufferManager;
+
+ /**
* Thread for preparing streams
*/
class PreparerThread : private Thread, public virtual RefBase {
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
index 1d9d04f..fe04eb1 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
@@ -38,7 +38,7 @@
status_t Camera3DummyStream::getBufferLocked(camera3_stream_buffer *buffer) {
ATRACE_CALL();
- ALOGE("%s: Stream %d: Dummy stream cannot produce buffers!", mId);
+ ALOGE("%s: Stream %d: Dummy stream cannot produce buffers!", __FUNCTION__, mId);
return INVALID_OPERATION;
}
@@ -46,7 +46,7 @@
const camera3_stream_buffer &buffer,
nsecs_t timestamp) {
ATRACE_CALL();
- ALOGE("%s: Stream %d: Dummy stream cannot return buffers!", mId);
+ ALOGE("%s: Stream %d: Dummy stream cannot return buffers!", __FUNCTION__, mId);
return INVALID_OPERATION;
}
@@ -57,7 +57,7 @@
/*out*/
sp<Fence> *releaseFenceOut) {
ATRACE_CALL();
- ALOGE("%s: Stream %d: Dummy stream cannot return buffers!", mId);
+ ALOGE("%s: Stream %d: Dummy stream cannot return buffers!", __FUNCTION__, mId);
return INVALID_OPERATION;
}
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index 7b298e6..4824974 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -31,9 +31,9 @@
Camera3IOStreamBase::Camera3IOStreamBase(int id, camera3_stream_type_t type,
uint32_t width, uint32_t height, size_t maxSize, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation, int setId) :
Camera3Stream(id, type,
- width, height, maxSize, format, dataSpace, rotation),
+ width, height, maxSize, format, dataSpace, rotation, setId),
mTotalBufferCount(0),
mHandoutTotalBufferCount(0),
mHandoutOutputBufferCount(0),
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index f5727e8..35dda39 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -34,7 +34,8 @@
protected:
Camera3IOStreamBase(int id, camera3_stream_type_t type,
uint32_t width, uint32_t height, size_t maxSize, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation);
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ int setId = CAMERA3_STREAM_SET_ID_INVALID);
public:
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index 2504bfd..7dab2e3 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -169,7 +169,7 @@
if (producer == NULL) {
return BAD_VALUE;
} else if (mProducer == NULL) {
- ALOGE("%s: No input stream is configured");
+ ALOGE("%s: No input stream is configured", __FUNCTION__);
return INVALID_OPERATION;
}
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index a5aa1fa..c721144 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -34,28 +34,34 @@
Camera3OutputStream::Camera3OutputStream(int id,
sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation, int setId) :
Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
- /*maxSize*/0, format, dataSpace, rotation),
+ /*maxSize*/0, format, dataSpace, rotation, setId),
mConsumer(consumer),
mTransform(0),
- mTraceFirstBuffer(true) {
+ mTraceFirstBuffer(true),
+ mUseBufferManager(false) {
if (mConsumer == NULL) {
ALOGE("%s: Consumer is NULL!", __FUNCTION__);
mState = STATE_ERROR;
}
+
+ if (setId > CAMERA3_STREAM_SET_ID_INVALID) {
+ mBufferReleasedListener = new BufferReleasedListener(this);
+ }
}
Camera3OutputStream::Camera3OutputStream(int id,
sp<Surface> consumer,
uint32_t width, uint32_t height, size_t maxSize, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation, int setId) :
Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, maxSize,
- format, dataSpace, rotation),
+ format, dataSpace, rotation, setId),
mConsumer(consumer),
mTransform(0),
- mTraceFirstBuffer(true) {
+ mTraceFirstBuffer(true),
+ mUseBufferManager(false) {
if (format != HAL_PIXEL_FORMAT_BLOB && format != HAL_PIXEL_FORMAT_RAW_OPAQUE) {
ALOGE("%s: Bad format for size-only stream: %d", __FUNCTION__,
@@ -67,17 +73,28 @@
ALOGE("%s: Consumer is NULL!", __FUNCTION__);
mState = STATE_ERROR;
}
+
+ if (setId > CAMERA3_STREAM_SET_ID_INVALID) {
+ mBufferReleasedListener = new BufferReleasedListener(this);
+ }
}
Camera3OutputStream::Camera3OutputStream(int id, camera3_stream_type_t type,
uint32_t width, uint32_t height,
int format,
android_dataspace dataSpace,
- camera3_stream_rotation_t rotation) :
+ camera3_stream_rotation_t rotation,
+ int setId) :
Camera3IOStreamBase(id, type, width, height,
/*maxSize*/0,
- format, dataSpace, rotation),
- mTransform(0) {
+ format, dataSpace, rotation, setId),
+ mTransform(0),
+ mTraceFirstBuffer(true),
+ mUseBufferManager(false) {
+
+ if (setId > CAMERA3_STREAM_SET_ID_INVALID) {
+ mBufferReleasedListener = new BufferReleasedListener(this);
+ }
// Subclasses expected to initialize mConsumer themselves
}
@@ -96,28 +113,46 @@
}
ANativeWindowBuffer* anb;
- int fenceFd;
+ int fenceFd = -1;
+ if (mUseBufferManager) {
+ sp<GraphicBuffer> gb;
+ res = mBufferManager->getBufferForStream(getId(), getStreamSetId(), &gb, &fenceFd);
+ if (res != OK) {
+ ALOGE("%s: Stream %d: Can't get next output buffer from buffer manager: %s (%d)",
+ __FUNCTION__, mId, strerror(-res), res);
+ return res;
+ }
+ // Attach this buffer to the bufferQueue: the buffer will be in dequeue state after a
+ // successful return.
+ anb = gb.get();
+ res = mConsumer->attachBuffer(anb);
+ if (res != OK) {
+ ALOGE("%s: Stream %d: Can't attach the output buffer to this surface: %s (%d)",
+ __FUNCTION__, mId, strerror(-res), res);
+ return res;
+ }
+ } else {
+ /**
+ * Release the lock briefly to avoid deadlock for below scenario:
+ * Thread 1: StreamingProcessor::startStream -> Camera3Stream::isConfiguring().
+ * This thread acquired StreamingProcessor lock and try to lock Camera3Stream lock.
+ * Thread 2: Camera3Stream::returnBuffer->StreamingProcessor::onFrameAvailable().
+ * This thread acquired Camera3Stream lock and bufferQueue lock, and try to lock
+ * StreamingProcessor lock.
+ * Thread 3: Camera3Stream::getBuffer(). This thread acquired Camera3Stream lock
+ * and try to lock bufferQueue lock.
+ * Then there is circular locking dependency.
+ */
+ sp<ANativeWindow> currentConsumer = mConsumer;
+ mLock.unlock();
- /**
- * Release the lock briefly to avoid deadlock for below scenario:
- * Thread 1: StreamingProcessor::startStream -> Camera3Stream::isConfiguring().
- * This thread acquired StreamingProcessor lock and try to lock Camera3Stream lock.
- * Thread 2: Camera3Stream::returnBuffer->StreamingProcessor::onFrameAvailable().
- * This thread acquired Camera3Stream lock and bufferQueue lock, and try to lock
- * StreamingProcessor lock.
- * Thread 3: Camera3Stream::getBuffer(). This thread acquired Camera3Stream lock
- * and try to lock bufferQueue lock.
- * Then there is circular locking dependency.
- */
- sp<ANativeWindow> currentConsumer = mConsumer;
- mLock.unlock();
-
- res = currentConsumer->dequeueBuffer(currentConsumer.get(), &anb, &fenceFd);
- mLock.lock();
- if (res != OK) {
- ALOGE("%s: Stream %d: Can't dequeue next output buffer: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
- return res;
+ res = currentConsumer->dequeueBuffer(currentConsumer.get(), &anb, &fenceFd);
+ mLock.lock();
+ if (res != OK) {
+ ALOGE("%s: Stream %d: Can't dequeue next output buffer: %s (%d)",
+ __FUNCTION__, mId, strerror(-res), res);
+ return res;
+ }
}
/**
@@ -270,9 +305,9 @@
ALOG_ASSERT(mConsumer != 0, "mConsumer should never be NULL");
- // Configure consumer-side ANativeWindow interface
- res = native_window_api_connect(mConsumer.get(),
- NATIVE_WINDOW_API_CAMERA);
+ // Configure consumer-side ANativeWindow interface. The listener may be used
+ // to notify buffer manager (if it is used) of the returned buffers.
+ res = mConsumer->connect(NATIVE_WINDOW_API_CAMERA, /*listener*/mBufferReleasedListener);
if (res != OK) {
ALOGE("%s: Unable to connect to native window for stream %d",
__FUNCTION__, mId);
@@ -366,6 +401,30 @@
__FUNCTION__, mTransform, strerror(-res), res);
}
+ /**
+ * Camera3 Buffer manager is only supported by HAL3.2 onwards, as the older HALs requires
+ * buffers to be statically allocated for internal static buffer registration, while the
+ * buffers provided by buffer manager are really dynamically allocated. Camera3Device only
+ * sets the mBufferManager if device version is >= HAL3.2, which guarantees that the buffer
+ * manager setup is skipped in below code.
+ */
+ if (mBufferManager != 0 && mSetId > CAMERA3_STREAM_SET_ID_INVALID) {
+ StreamInfo streamInfo(
+ getId(), getStreamSetId(), getWidth(), getHeight(), getFormat(), getDataSpace(),
+ camera3_stream::usage, mTotalBufferCount, /*isConfigured*/true);
+ res = mBufferManager->registerStream(streamInfo);
+ if (res == OK) {
+ // Disable buffer allocation for this BufferQueue, buffer manager will take over
+ // the buffer allocation responsibility.
+ mConsumer->getIGraphicBufferProducer()->allowAllocation(false);
+ mUseBufferManager = true;
+ } else {
+ ALOGE("%s: Unable to register stream %d to camera3 buffer manager, "
+ "(error %d %s), fall back to BufferQueue for buffer management!",
+ __FUNCTION__, mId, res, strerror(-res));
+ }
+ }
+
return OK;
}
@@ -376,6 +435,8 @@
return res;
}
+ ALOGV("%s: disconnecting stream %d from native window", __FUNCTION__, getId());
+
res = native_window_api_disconnect(mConsumer.get(),
NATIVE_WINDOW_API_CAMERA);
@@ -396,6 +457,21 @@
return res;
}
+ // Since device is already idle, there is no getBuffer call to buffer manager, unregister the
+ // stream at this point should be safe.
+ if (mUseBufferManager) {
+ res = mBufferManager->unregisterStream(getId(), getStreamSetId());
+ if (res != OK) {
+ ALOGE("%s: Unable to unregister stream %d from buffer manager "
+ "(error %d %s)", __FUNCTION__, mId, res, strerror(-res));
+ mState = STATE_ERROR;
+ return res;
+ }
+ // Note that, to make prepare/teardown case work, we must not mBufferManager.clear(), as
+ // the stream is still in usable state after this call.
+ mUseBufferManager = false;
+ }
+
mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG
: STATE_CONSTRUCTED;
return OK;
@@ -437,6 +513,59 @@
return (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) != 0;
}
+status_t Camera3OutputStream::setBufferManager(sp<Camera3BufferManager> bufferManager) {
+ Mutex::Autolock l(mLock);
+ if (mState != STATE_CONSTRUCTED) {
+ ALOGE("%s: this method can only be called when stream in in CONSTRUCTED state.",
+ __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ mBufferManager = bufferManager;
+
+ return OK;
+}
+
+void Camera3OutputStream::BufferReleasedListener::onBufferReleased() {
+ sp<Camera3OutputStream> stream = mParent.promote();
+ if (stream == nullptr) {
+ ALOGV("%s: Parent camera3 output stream was destroyed", __FUNCTION__);
+ return;
+ }
+
+ Mutex::Autolock l(stream->mLock);
+ if (!(stream->mUseBufferManager)) {
+ return;
+ }
+
+ sp<Fence> fence;
+ sp<GraphicBuffer> buffer;
+ int fenceFd = -1;
+ status_t res = stream->mConsumer->detachNextBuffer(&buffer, &fence);
+ if (res == NO_MEMORY) {
+ // This may rarely happen, which indicates that the released buffer was freed by other
+ // call (e.g., attachBuffer, dequeueBuffer etc.) before reaching here. We should notify the
+ // buffer manager that this buffer has been freed. It's not fatal, but should be avoided,
+ // therefore log a warning.
+ buffer = 0;
+ ALOGW("%s: the released buffer has already been freed by the buffer queue!", __FUNCTION__);
+ } else if (res != OK) {
+ // Other errors are fatal.
+ ALOGE("%s: detach next buffer failed: %s (%d).", __FUNCTION__, strerror(-res), res);
+ stream->mState = STATE_ERROR;
+ return;
+ }
+
+ if (fence!= 0 && fence->isValid()) {
+ fenceFd = fence->dup();
+ }
+ res = stream->mBufferManager->returnBufferForStream(stream->getId(), stream->getStreamSetId(),
+ buffer, fenceFd);
+ if (res != OK) {
+ ALOGE("%s: return buffer to buffer manager failed: %s (%d).", __FUNCTION__,
+ strerror(-res), res);
+ stream->mState = STATE_ERROR;
+ }
+}
}; // namespace camera3
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 3c083ec..e222e2c 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -18,16 +18,54 @@
#define ANDROID_SERVERS_CAMERA3_OUTPUT_STREAM_H
#include <utils/RefBase.h>
+#include <gui/IProducerListener.h>
#include <gui/Surface.h>
#include "Camera3Stream.h"
#include "Camera3IOStreamBase.h"
#include "Camera3OutputStreamInterface.h"
+#include "Camera3BufferManager.h"
namespace android {
namespace camera3 {
+class Camera3BufferManager;
+
+/**
+ * Stream info structure that holds the necessary stream info for buffer manager to use for
+ * buffer allocation and management.
+ */
+struct StreamInfo {
+ int streamId;
+ int streamSetId;
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+ android_dataspace dataSpace;
+ uint32_t combinedUsage;
+ size_t totalBufferCount;
+ bool isConfigured;
+ StreamInfo(int id = CAMERA3_STREAM_ID_INVALID,
+ int setId = CAMERA3_STREAM_SET_ID_INVALID,
+ uint32_t w = 0,
+ uint32_t h = 0,
+ uint32_t fmt = 0,
+ android_dataspace ds = HAL_DATASPACE_UNKNOWN,
+ uint32_t usage = 0,
+ size_t bufferCount = 0,
+ bool configured = false) :
+ streamId(id),
+ streamSetId(setId),
+ width(w),
+ height(h),
+ format(fmt),
+ dataSpace(ds),
+ combinedUsage(usage),
+ totalBufferCount(bufferCount),
+ isConfigured(configured){}
+};
+
/**
* A class for managing a single stream of output data from the camera device.
*/
@@ -37,18 +75,24 @@
public:
/**
* Set up a stream for formats that have 2 dimensions, such as RAW and YUV.
+ * A valid stream set id needs to be set to support buffer sharing between multiple
+ * streams.
*/
Camera3OutputStream(int id, sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation);
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ int setId = CAMERA3_STREAM_SET_ID_INVALID);
/**
* Set up a stream for formats that have a variable buffer size for the same
* dimensions, such as compressed JPEG.
+ * A valid stream set id needs to be set to support buffer sharing between multiple
+ * streams.
*/
Camera3OutputStream(int id, sp<Surface> consumer,
uint32_t width, uint32_t height, size_t maxSize, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation);
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ int setId = CAMERA3_STREAM_SET_ID_INVALID);
virtual ~Camera3OutputStream();
@@ -69,10 +113,32 @@
*/
bool isVideoStream() const;
+ class BufferReleasedListener : public BnProducerListener {
+ public:
+ BufferReleasedListener(wp<Camera3OutputStream> parent) : mParent(parent) {}
+
+ /**
+ * Implementation of IProducerListener, used to notify this stream that the consumer
+ * has returned a buffer and it is ready to return to Camera3BufferManager for reuse.
+ */
+ virtual void onBufferReleased();
+
+ private:
+ wp<Camera3OutputStream> mParent;
+ };
+
+ /**
+ * 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.
+ */
+ status_t setBufferManager(sp<Camera3BufferManager> bufferManager);
+
protected:
Camera3OutputStream(int id, camera3_stream_type_t type,
uint32_t width, uint32_t height, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation);
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ int setId = CAMERA3_STREAM_SET_ID_INVALID);
/**
* Note that we release the lock briefly in this function
@@ -98,6 +164,22 @@
String8 mConsumerName;
/**
+ * GraphicBuffer manager this stream is registered to. Used to replace the buffer
+ * allocation/deallocation role of BufferQueue.
+ */
+ sp<Camera3BufferManager> mBufferManager;
+
+ /**
+ * Buffer released listener, used to notify the buffer manager that a buffer is released
+ * from consumer side.
+ */
+ sp<BufferReleasedListener> mBufferReleasedListener;
+
+ /**
+ * Flag indicating if the buffer manager is used to allocate the stream buffers
+ */
+ bool mUseBufferManager;
+ /**
* Internal Camera3Stream interface
*/
virtual status_t getBufferLocked(camera3_stream_buffer *buffer);
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 141f6c3..ed3ab97 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -47,13 +47,19 @@
Camera3Stream::Camera3Stream(int id,
camera3_stream_type type,
uint32_t width, uint32_t height, size_t maxSize, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation, int setId) :
camera3_stream(),
mId(id),
+ mSetId(setId),
mName(String8::format("Camera3Stream[%d]", id)),
mMaxSize(maxSize),
mState(STATE_CONSTRUCTED),
mStatusId(StatusTracker::NO_STATUS_ID),
+ oldUsage(0),
+ oldMaxBuffers(0),
+ mStreamUnpreparable(false),
+ mPrepared(false),
+ mPreparedBufferIdx(0),
mLastMaxCount(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX) {
camera3_stream::stream_type = type;
@@ -77,6 +83,10 @@
return mId;
}
+int Camera3Stream::getStreamSetId() const {
+ return mSetId;
+}
+
uint32_t Camera3Stream::getWidth() const {
return camera3_stream::width;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 753280b..fe51ab5 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -130,6 +130,11 @@
int getId() const;
/**
+ * Get the output stream set id.
+ */
+ int getStreamSetId() const;
+
+ /**
* Get the stream's dimensions and format
*/
uint32_t getWidth() const;
@@ -350,6 +355,21 @@
protected:
const int mId;
+ /**
+ * Stream set id, used to indicate which group of this stream belongs to for buffer sharing
+ * across multiple streams.
+ *
+ * The default value is set to CAMERA3_STREAM_SET_ID_INVALID, which indicates that this stream
+ * doesn't intend to share buffers with any other streams, and this stream will fall back to
+ * the existing BufferQueue mechanism to manage the buffer allocations and buffer circulation.
+ * When a valid stream set id is set, this stream intends to use the Camera3BufferManager to
+ * manage the buffer allocations; the BufferQueue will only handle the buffer transaction
+ * between the producer and consumer. For this case, upon successfully registration, the streams
+ * with the same stream set id will potentially share the buffers allocated by
+ * Camera3BufferManager.
+ */
+ const int mSetId;
+
const String8 mName;
// Zero for formats with fixed buffer size for given dimensions.
const size_t mMaxSize;
@@ -367,7 +387,8 @@
Camera3Stream(int id, camera3_stream_type type,
uint32_t width, uint32_t height, size_t maxSize, int format,
- android_dataspace dataSpace, camera3_stream_rotation_t rotation);
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ int setId);
/**
* Interface to be implemented by derived classes
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index 54009ae..3f7e7a7 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -26,6 +26,20 @@
namespace camera3 {
+enum {
+ /**
+ * This stream set ID indicates that the set ID is invalid, and this stream doesn't intend to
+ * share buffers with any other stream. It is illegal to register this kind of stream to
+ * Camera3BufferManager.
+ */
+ CAMERA3_STREAM_SET_ID_INVALID = -1,
+
+ /**
+ * Invalid output stream ID.
+ */
+ CAMERA3_STREAM_ID_INVALID = -1,
+};
+
class StatusTracker;
/**
@@ -45,6 +59,11 @@
virtual int getId() const = 0;
/**
+ * Get the output stream set id.
+ */
+ virtual int getStreamSetId() const = 0;
+
+ /**
* Get the stream's dimensions and format
*/
virtual uint32_t getWidth() const = 0;
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.h b/services/camera/libcameraservice/gui/RingBufferConsumer.h
index 243ea31..28dc5d5 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.h
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.h
@@ -189,4 +189,4 @@
} // namespace android
-#endif // ANDROID_GUI_CPUCONSUMER_H
+#endif // ANDROID_GUI_RINGBUFFERCONSUMER_H