Merge "MediaExtractor: Fix use-after-free"
diff --git a/camera/camera2/CaptureRequest.cpp b/camera/camera2/CaptureRequest.cpp
index 983d29b..1843ec4 100644
--- a/camera/camera2/CaptureRequest.cpp
+++ b/camera/camera2/CaptureRequest.cpp
@@ -18,6 +18,7 @@
// #define LOG_NDEBUG 0
#define LOG_TAG "CameraRequest"
#include <utils/Log.h>
+#include <utils/String16.h>
#include <camera/camera2/CaptureRequest.h>
@@ -42,18 +43,39 @@
return BAD_VALUE;
}
- mMetadata.clear();
mSurfaceList.clear();
mStreamIdxList.clear();
mSurfaceIdxList.clear();
+ mPhysicalCameraSettings.clear();
status_t err = OK;
- if ((err = mMetadata.readFromParcel(parcel)) != OK) {
- ALOGE("%s: Failed to read metadata from parcel", __FUNCTION__);
+ int32_t settingsCount;
+ if ((err = parcel->readInt32(&settingsCount)) != OK) {
+ ALOGE("%s: Failed to read the settings count from parcel: %d", __FUNCTION__, err);
return err;
}
- ALOGV("%s: Read metadata from parcel", __FUNCTION__);
+
+ if (settingsCount <= 0) {
+ ALOGE("%s: Settings count %d should always be positive!", __FUNCTION__, settingsCount);
+ return BAD_VALUE;
+ }
+
+ for (int32_t i = 0; i < settingsCount; i++) {
+ String16 id;
+ if ((err = parcel->readString16(&id)) != OK) {
+ ALOGE("%s: Failed to read camera id!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ CameraMetadata settings;
+ if ((err = settings.readFromParcel(parcel)) != OK) {
+ ALOGE("%s: Failed to read metadata from parcel", __FUNCTION__);
+ return err;
+ }
+ ALOGV("%s: Read metadata from parcel", __FUNCTION__);
+ mPhysicalCameraSettings.push_back({std::string(String8(id).string()), settings});
+ }
int isReprocess = 0;
if ((err = parcel->readInt32(&isReprocess)) != OK) {
@@ -135,10 +157,25 @@
status_t err = OK;
- if ((err = mMetadata.writeToParcel(parcel)) != OK) {
+ int32_t settingsCount = static_cast<int32_t>(mPhysicalCameraSettings.size());
+
+ if ((err = parcel->writeInt32(settingsCount)) != OK) {
+ ALOGE("%s: Failed to write settings count!", __FUNCTION__);
return err;
}
+ for (const auto &it : mPhysicalCameraSettings) {
+ if ((err = parcel->writeString16(String16(it.id.c_str()))) != OK) {
+ ALOGE("%s: Failed to camera id!", __FUNCTION__);
+ return err;
+ }
+
+ if ((err = it.settings.writeToParcel(parcel)) != OK) {
+ ALOGE("%s: Failed to write settings!", __FUNCTION__);
+ return err;
+ }
+ }
+
parcel->writeInt32(mIsReprocess ? 1 : 0);
if (mSurfaceConverted) {
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 813d6c9..feb04c2 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -1,6 +1,6 @@
/*
**
-** Copyright 2015, The Android Open Source Project
+** Copyright 2015-2018, 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.
@@ -64,6 +64,10 @@
return mIsShared;
}
+String16 OutputConfiguration::getPhysicalCameraId() const {
+ return mPhysicalCameraId;
+}
+
OutputConfiguration::OutputConfiguration() :
mRotation(INVALID_ROTATION),
mSurfaceSetID(INVALID_SET_ID),
@@ -139,6 +143,8 @@
return err;
}
+ parcel->readString16(&mPhysicalCameraId);
+
mRotation = rotation;
mSurfaceSetID = setID;
mSurfaceType = surfaceType;
@@ -153,8 +159,9 @@
mGbps.push_back(surface.graphicBufferProducer);
}
- ALOGV("%s: OutputConfiguration: rotation = %d, setId = %d, surfaceType = %d",
- __FUNCTION__, mRotation, mSurfaceSetID, mSurfaceType);
+ ALOGV("%s: OutputConfiguration: rotation = %d, setId = %d, surfaceType = %d,"
+ " physicalCameraId = %s", __FUNCTION__, mRotation, mSurfaceSetID,
+ mSurfaceType, String8(mPhysicalCameraId).string());
return err;
}
@@ -204,6 +211,9 @@
err = parcel->writeParcelableVector(surfaceShims);
if (err != OK) return err;
+ err = parcel->writeString16(mPhysicalCameraId);
+ if (err != OK) return err;
+
return OK;
}
diff --git a/camera/include/camera/camera2/CaptureRequest.h b/camera/include/camera/camera2/CaptureRequest.h
index c53799f..506abab 100644
--- a/camera/include/camera/camera2/CaptureRequest.h
+++ b/camera/include/camera/camera2/CaptureRequest.h
@@ -40,7 +40,11 @@
CaptureRequest(CaptureRequest&& rhs) noexcept;
virtual ~CaptureRequest();
- CameraMetadata mMetadata;
+ struct PhysicalCameraSettings {
+ std::string id;
+ CameraMetadata settings;
+ };
+ std::vector<PhysicalCameraSettings> mPhysicalCameraSettings;
// Used by NDK client to pass surfaces by stream/surface index.
bool mSurfaceConverted = false;
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index 3599604..a80f44b 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2015-2018 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.
@@ -46,6 +46,7 @@
int getHeight() const;
bool isDeferred() const;
bool isShared() const;
+ String16 getPhysicalCameraId() const;
/**
* Keep impl up-to-date with OutputConfiguration.java in frameworks/base
*/
@@ -74,7 +75,8 @@
mHeight == other.mHeight &&
mIsDeferred == other.mIsDeferred &&
mIsShared == other.mIsShared &&
- gbpsEqual(other));
+ gbpsEqual(other) &&
+ mPhysicalCameraId == other.mPhysicalCameraId );
}
bool operator != (const OutputConfiguration& other) const {
return !(*this == other);
@@ -102,6 +104,9 @@
if (mIsShared != other.mIsShared) {
return mIsShared < other.mIsShared;
}
+ if (mPhysicalCameraId != other.mPhysicalCameraId) {
+ return mPhysicalCameraId < other.mPhysicalCameraId;
+ }
return gbpsLessThan(other);
}
bool operator > (const OutputConfiguration& other) const {
@@ -120,8 +125,7 @@
int mHeight;
bool mIsDeferred;
bool mIsShared;
- // helper function
- static String16 readMaybeEmptyString16(const android::Parcel* parcel);
+ String16 mPhysicalCameraId;
};
} // namespace params
} // namespace camera2
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index f7cea4f..ef1c61f 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -372,7 +372,8 @@
const ACaptureRequest* request, /*out*/sp<CaptureRequest>& outReq) {
camera_status_t ret;
sp<CaptureRequest> req(new CaptureRequest());
- req->mMetadata = request->settings->getInternalData();
+ req->mPhysicalCameraSettings.push_back({std::string(mCameraId.string()),
+ request->settings->getInternalData()});
req->mIsReprocess = false; // NDK does not support reprocessing yet
req->mContext = request->context;
req->mSurfaceConverted = true; // set to true, and fill in stream/surface idx to speed up IPC
@@ -418,7 +419,7 @@
ACaptureRequest*
CameraDevice::allocateACaptureRequest(sp<CaptureRequest>& req) {
ACaptureRequest* pRequest = new ACaptureRequest();
- CameraMetadata clone = req->mMetadata;
+ CameraMetadata clone = req->mPhysicalCameraSettings.begin()->settings;
pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST);
pRequest->targets = new ACameraOutputTargets();
for (size_t i = 0; i < req->mSurfaceList.size(); i++) {
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index 29ad09b..62b0ec9 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -305,6 +305,7 @@
case ACAMERA_STATISTICS_FACE_DETECT_MODE:
case ACAMERA_STATISTICS_HOT_PIXEL_MAP_MODE:
case ACAMERA_STATISTICS_LENS_SHADING_MAP_MODE:
+ case ACAMERA_STATISTICS_OIS_DATA_MODE:
case ACAMERA_TONEMAP_CURVE_BLUE:
case ACAMERA_TONEMAP_CURVE_GREEN:
case ACAMERA_TONEMAP_CURVE_RED:
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 6e861a6..ffb2900 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -69,6 +69,7 @@
ACAMERA_SYNC,
ACAMERA_REPROCESS,
ACAMERA_DEPTH,
+ ACAMERA_LOGICAL_MULTI_CAMERA,
ACAMERA_SECTION_COUNT,
ACAMERA_VENDOR = 0x8000
@@ -104,6 +105,9 @@
ACAMERA_SYNC_START = ACAMERA_SYNC << 16,
ACAMERA_REPROCESS_START = ACAMERA_REPROCESS << 16,
ACAMERA_DEPTH_START = ACAMERA_DEPTH << 16,
+ ACAMERA_LOGICAL_MULTI_CAMERA_START
+ = ACAMERA_LOGICAL_MULTI_CAMERA
+ << 16,
ACAMERA_VENDOR_START = ACAMERA_VENDOR << 16
} acamera_metadata_section_start_t;
@@ -4562,6 +4566,85 @@
*/
ACAMERA_STATISTICS_LENS_SHADING_MAP_MODE = // byte (acamera_metadata_enum_android_statistics_lens_shading_map_mode_t)
ACAMERA_STATISTICS_START + 16,
+ /**
+ * <p>Whether the camera device outputs the OIS data in output
+ * result metadata.</p>
+ *
+ * <p>Type: byte (acamera_metadata_enum_android_statistics_ois_data_mode_t)</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+ * <li>ACaptureRequest</li>
+ * </ul></p>
+ *
+ * <p>When set to ON,
+ * ACAMERA_STATISTICS_OIS_TIMESTAMPS, android.statistics.oisShiftPixelX,
+ * android.statistics.oisShiftPixelY will provide OIS data in the output result metadata.</p>
+ *
+ * @see ACAMERA_STATISTICS_OIS_TIMESTAMPS
+ */
+ ACAMERA_STATISTICS_OIS_DATA_MODE = // byte (acamera_metadata_enum_android_statistics_ois_data_mode_t)
+ ACAMERA_STATISTICS_START + 17,
+ /**
+ * <p>An array of timestamps of OIS samples, in nanoseconds.</p>
+ *
+ * <p>Type: int64[n]</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+ * </ul></p>
+ *
+ * <p>The array contains the timestamps of OIS samples. The timestamps are in the same
+ * timebase as and comparable to ACAMERA_SENSOR_TIMESTAMP.</p>
+ *
+ * @see ACAMERA_SENSOR_TIMESTAMP
+ */
+ ACAMERA_STATISTICS_OIS_TIMESTAMPS = // int64[n]
+ ACAMERA_STATISTICS_START + 18,
+ /**
+ * <p>An array of shifts of OIS samples, in x direction.</p>
+ *
+ * <p>Type: float[n]</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+ * </ul></p>
+ *
+ * <p>The array contains the amount of shifts in x direction, in pixels, based on OIS samples.
+ * A positive value is a shift from left to right in active array coordinate system. For
+ * example, if the optical center is (1000, 500) in active array coordinates, an shift of
+ * (3, 0) puts the new optical center at (1003, 500).</p>
+ * <p>The number of shifts must match the number of timestamps in
+ * ACAMERA_STATISTICS_OIS_TIMESTAMPS.</p>
+ *
+ * @see ACAMERA_STATISTICS_OIS_TIMESTAMPS
+ */
+ ACAMERA_STATISTICS_OIS_X_SHIFTS = // float[n]
+ ACAMERA_STATISTICS_START + 19,
+ /**
+ * <p>An array of shifts of OIS samples, in y direction.</p>
+ *
+ * <p>Type: float[n]</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+ * </ul></p>
+ *
+ * <p>The array contains the amount of shifts in y direction, in pixels, based on OIS samples.
+ * A positive value is a shift from top to bottom in active array coordinate system. For
+ * example, if the optical center is (1000, 500) in active array coordinates, an shift of
+ * (0, 5) puts the new optical center at (1000, 505).</p>
+ * <p>The number of shifts must match the number of timestamps in
+ * ACAMERA_STATISTICS_OIS_TIMESTAMPS.</p>
+ *
+ * @see ACAMERA_STATISTICS_OIS_TIMESTAMPS
+ */
+ ACAMERA_STATISTICS_OIS_Y_SHIFTS = // float[n]
+ ACAMERA_STATISTICS_START + 20,
ACAMERA_STATISTICS_END,
/**
@@ -4634,6 +4717,24 @@
*/
ACAMERA_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES = // byte[n]
ACAMERA_STATISTICS_INFO_START + 7,
+ /**
+ * <p>List of OIS data output modes for ACAMERA_STATISTICS_OIS_DATA_MODE that
+ * are supported by this camera device.</p>
+ *
+ * @see ACAMERA_STATISTICS_OIS_DATA_MODE
+ *
+ * <p>Type: byte[n]</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+ * </ul></p>
+ *
+ * <p>If no OIS data output is available for this camera device, this key will
+ * contain only OFF.</p>
+ */
+ ACAMERA_STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES = // byte[n]
+ ACAMERA_STATISTICS_INFO_START + 8,
ACAMERA_STATISTICS_INFO_END,
/**
@@ -5165,6 +5266,29 @@
ACAMERA_DEPTH_START + 4,
ACAMERA_DEPTH_END,
+ /**
+ * <p>The accuracy of frame timestamp synchronization between physical cameras</p>
+ *
+ * <p>Type: byte (acamera_metadata_enum_android_logical_multi_camera_sensor_sync_type_t)</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+ * </ul></p>
+ *
+ * <p>The accuracy of the frame timestamp synchronization determines the physical cameras'
+ * ability to start exposure at the same time. If the sensorSyncType is CALIBRATED,
+ * the physical camera sensors usually run in master-slave mode so that their shutter
+ * time is synchronized. For APPROXIMATE sensorSyncType, the camera sensors usually run in
+ * master-master mode, and there could be offset between their start of exposure.</p>
+ * <p>In both cases, all images generated for a particular capture request still carry the same
+ * timestamps, so that they can be used to look up the matching frame number and
+ * onCaptureStarted callback.</p>
+ */
+ ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE = // byte (acamera_metadata_enum_android_logical_multi_camera_sensor_sync_type_t)
+ ACAMERA_LOGICAL_MULTI_CAMERA_START + 1,
+ ACAMERA_LOGICAL_MULTI_CAMERA_END,
+
} acamera_metadata_tag_t;
/**
@@ -6895,6 +7019,52 @@
*/
ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING = 10,
+ /**
+ * <p>The camera device is a logical camera backed by two or more physical cameras that are
+ * also exposed to the application.</p>
+ * <p>This capability requires the camera device to support the following:</p>
+ * <ul>
+ * <li>This camera device must list the following static metadata entries in <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html">CameraCharacteristics</a>:<ul>
+ * <li>android.logicalMultiCamera.physicalIds</li>
+ * <li>ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE</li>
+ * </ul>
+ * </li>
+ * <li>The underlying physical cameras' static metadata must list the following entries,
+ * so that the application can correlate pixels from the physical streams:<ul>
+ * <li>ACAMERA_LENS_POSE_REFERENCE</li>
+ * <li>ACAMERA_LENS_POSE_ROTATION</li>
+ * <li>ACAMERA_LENS_POSE_TRANSLATION</li>
+ * <li>ACAMERA_LENS_INTRINSIC_CALIBRATION</li>
+ * <li>ACAMERA_LENS_RADIAL_DISTORTION</li>
+ * </ul>
+ * </li>
+ * <li>The logical camera device must be LIMITED or higher device.</li>
+ * </ul>
+ * <p>Both the logical camera device and its underlying physical devices support the
+ * mandatory stream combinations required for their device levels.</p>
+ * <p>Additionally, for each guaranteed stream combination, the logical camera supports:</p>
+ * <ul>
+ * <li>Replacing one logical {@link AIMAGE_FORMAT_YUV_420_888 YUV_420_888}
+ * or raw stream with two physical streams of the same size and format, each from a
+ * separate physical camera, given that the size and format are supported by both
+ * physical cameras.</li>
+ * <li>Adding two raw streams, each from one physical camera, if the logical camera doesn't
+ * advertise RAW capability, but the underlying physical cameras do. This is usually
+ * the case when the physical cameras have different sensor sizes.</li>
+ * </ul>
+ * <p>Using physical streams in place of a logical stream of the same size and format will
+ * not slow down the frame rate of the capture, as long as the minimum frame duration
+ * of the physical and logical streams are the same.</p>
+ *
+ * @see ACAMERA_LENS_INTRINSIC_CALIBRATION
+ * @see ACAMERA_LENS_POSE_REFERENCE
+ * @see ACAMERA_LENS_POSE_ROTATION
+ * @see ACAMERA_LENS_POSE_TRANSLATION
+ * @see ACAMERA_LENS_RADIAL_DISTORTION
+ * @see ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
+ */
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA = 11,
+
} acamera_metadata_enum_android_request_available_capabilities_t;
@@ -7226,6 +7396,20 @@
} acamera_metadata_enum_android_statistics_lens_shading_map_mode_t;
+// ACAMERA_STATISTICS_OIS_DATA_MODE
+typedef enum acamera_metadata_enum_acamera_statistics_ois_data_mode {
+ /**
+ * <p>Do not include OIS data in the capture result.</p>
+ */
+ ACAMERA_STATISTICS_OIS_DATA_MODE_OFF = 0,
+
+ /**
+ * <p>Include OIS data in the capture result.</p>
+ */
+ ACAMERA_STATISTICS_OIS_DATA_MODE_ON = 1,
+
+} acamera_metadata_enum_android_statistics_ois_data_mode_t;
+
// ACAMERA_TONEMAP_MODE
@@ -7387,6 +7571,37 @@
*/
ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_3 = 3,
+ /**
+ * <p>This camera device is backed by an external camera connected to this Android device.</p>
+ * <p>The device has capability identical to a LIMITED level device, with the following
+ * exceptions:</p>
+ * <ul>
+ * <li>The device may not report lens/sensor related information such as<ul>
+ * <li>ACAMERA_LENS_FOCAL_LENGTH</li>
+ * <li>ACAMERA_LENS_INFO_HYPERFOCAL_DISTANCE</li>
+ * <li>ACAMERA_SENSOR_INFO_PHYSICAL_SIZE</li>
+ * <li>ACAMERA_SENSOR_INFO_WHITE_LEVEL</li>
+ * <li>ACAMERA_SENSOR_BLACK_LEVEL_PATTERN</li>
+ * <li>ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT</li>
+ * <li>ACAMERA_SENSOR_ROLLING_SHUTTER_SKEW</li>
+ * </ul>
+ * </li>
+ * <li>The device will report 0 for ACAMERA_SENSOR_ORIENTATION</li>
+ * <li>The device has less guarantee on stable framerate, as the framerate partly depends
+ * on the external camera being used.</li>
+ * </ul>
+ *
+ * @see ACAMERA_LENS_FOCAL_LENGTH
+ * @see ACAMERA_LENS_INFO_HYPERFOCAL_DISTANCE
+ * @see ACAMERA_SENSOR_BLACK_LEVEL_PATTERN
+ * @see ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+ * @see ACAMERA_SENSOR_INFO_PHYSICAL_SIZE
+ * @see ACAMERA_SENSOR_INFO_WHITE_LEVEL
+ * @see ACAMERA_SENSOR_ORIENTATION
+ * @see ACAMERA_SENSOR_ROLLING_SHUTTER_SKEW
+ */
+ ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL = 4,
+
} acamera_metadata_enum_android_info_supported_hardware_level_t;
@@ -7474,6 +7689,25 @@
} acamera_metadata_enum_android_depth_depth_is_exclusive_t;
+// ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
+typedef enum acamera_metadata_enum_acamera_logical_multi_camera_sensor_sync_type {
+ /**
+ * <p>A software mechanism is used to synchronize between the physical cameras. As a result,
+ * the timestamp of an image from a physical stream is only an approximation of the
+ * image sensor start-of-exposure time.</p>
+ */
+ ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE = 0,
+
+ /**
+ * <p>The camera device supports frame timestamp synchronization at the hardware level,
+ * and the timestamp of a physical stream image accurately reflects its
+ * start-of-exposure time.</p>
+ */
+ ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED = 1,
+
+} acamera_metadata_enum_android_logical_multi_camera_sensor_sync_type_t;
+
+
#endif /* __ANDROID_API__ >= 24 */
__END_DECLS
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 8fe9a86..24c0c51 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -317,6 +317,9 @@
EXPECT_TRUE(res.isOk()) << res;
EXPECT_EQ(numCameras, static_cast<const int>(statuses.size()));
+ for (const auto &it : statuses) {
+ listener->onStatusChanged(it.status, String16(it.cameraId));
+ }
for (int32_t i = 0; i < numCameras; i++) {
String16 cameraId = String16(String8::format("%d", i));
@@ -421,6 +424,9 @@
serviceListener = new TestCameraServiceListener();
std::vector<hardware::CameraStatus> statuses;
service->addListener(serviceListener, &statuses);
+ for (const auto &it : statuses) {
+ serviceListener->onStatusChanged(it.status, String16(it.cameraId));
+ }
service->getNumberOfCameras(hardware::ICameraService::CAMERA_TYPE_BACKWARD_COMPATIBLE,
&numCameras);
}
@@ -439,8 +445,9 @@
ASSERT_NOT_NULL(service);
EXPECT_TRUE(serviceListener->waitForNumCameras(numCameras));
for (int32_t i = 0; i < numCameras; i++) {
+ String8 cameraId8 = String8::format("%d", i);
// Make sure we're available, or skip device tests otherwise
- String16 cameraId(String8::format("%d",i));
+ String16 cameraId(cameraId8);
int32_t s = serviceListener->getStatus(cameraId);
EXPECT_EQ(hardware::ICameraServiceListener::STATUS_PRESENT, s);
if (s != hardware::ICameraServiceListener::STATUS_PRESENT) {
@@ -488,7 +495,7 @@
EXPECT_TRUE(res.isOk()) << res;
hardware::camera2::CaptureRequest request;
- request.mMetadata = requestTemplate;
+ request.mPhysicalCameraSettings.push_back({cameraId8.string(), requestTemplate});
request.mSurfaceList.add(surface);
request.mIsReprocess = false;
int64_t lastFrameNumber = 0;
@@ -515,7 +522,7 @@
/*out*/&requestTemplate);
EXPECT_TRUE(res.isOk()) << res;
hardware::camera2::CaptureRequest request2;
- request2.mMetadata = requestTemplate;
+ request2.mPhysicalCameraSettings.push_back({cameraId8.string(), requestTemplate});
request2.mSurfaceList.add(surface);
request2.mIsReprocess = false;
callbacks->clearStatus();
@@ -548,10 +555,10 @@
EXPECT_TRUE(res.isOk()) << res;
android::hardware::camera2::CaptureRequest request3;
android::hardware::camera2::CaptureRequest request4;
- request3.mMetadata = requestTemplate;
+ request3.mPhysicalCameraSettings.push_back({cameraId8.string(), requestTemplate});
request3.mSurfaceList.add(surface);
request3.mIsReprocess = false;
- request4.mMetadata = requestTemplate2;
+ request4.mPhysicalCameraSettings.push_back({cameraId8.string(), requestTemplate2});
request4.mSurfaceList.add(surface);
request4.mIsReprocess = false;
std::vector<hardware::camera2::CaptureRequest> requestList;
@@ -585,3 +592,62 @@
}
};
+
+TEST_F(CameraClientBinderTest, CheckBinderCaptureRequest) {
+ sp<CaptureRequest> requestOriginal, requestParceled;
+ sp<IGraphicBufferProducer> gbProducer;
+ sp<IGraphicBufferConsumer> gbConsumer;
+ BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
+ sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false));
+ Vector<sp<Surface>> surfaceList;
+ surfaceList.push_back(surface);
+ std::string physicalDeviceId1 = "0";
+ std::string physicalDeviceId2 = "1";
+ CameraMetadata physicalDeviceSettings1, physicalDeviceSettings2;
+ uint8_t intent1 = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
+ uint8_t intent2 = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
+ EXPECT_EQ(OK, physicalDeviceSettings1.update(ANDROID_CONTROL_CAPTURE_INTENT, &intent1, 1));
+ EXPECT_EQ(OK, physicalDeviceSettings2.update(ANDROID_CONTROL_CAPTURE_INTENT, &intent2, 1));
+
+ requestParceled = new CaptureRequest();
+ Parcel p;
+ EXPECT_TRUE(requestParceled->readFromParcel(&p) != OK);
+ p.writeInt32(0);
+ p.setDataPosition(0);
+ EXPECT_TRUE(requestParceled->readFromParcel(&p) != OK);
+ p.freeData();
+ p.writeInt32(-1);
+ p.setDataPosition(0);
+ EXPECT_TRUE(requestParceled->readFromParcel(&p) != OK);
+ p.freeData();
+ p.writeInt32(1);
+ p.setDataPosition(0);
+ EXPECT_TRUE(requestParceled->readFromParcel(&p) != OK);
+
+ requestOriginal = new CaptureRequest();
+ requestOriginal->mPhysicalCameraSettings.push_back({physicalDeviceId1,
+ physicalDeviceSettings1});
+ requestOriginal->mPhysicalCameraSettings.push_back({physicalDeviceId2,
+ physicalDeviceSettings2});
+ requestOriginal->mSurfaceList.push_back(surface);
+ requestOriginal->mIsReprocess = false;
+ requestOriginal->mSurfaceConverted = false;
+
+ p.freeData();
+ EXPECT_TRUE(requestOriginal->writeToParcel(&p) == OK);
+ p.setDataPosition(0);
+ EXPECT_TRUE(requestParceled->readFromParcel(&p) == OK);
+ EXPECT_EQ(requestParceled->mIsReprocess, false);
+ EXPECT_FALSE(requestParceled->mSurfaceList.empty());
+ EXPECT_EQ(2u, requestParceled->mPhysicalCameraSettings.size());
+ auto it = requestParceled->mPhysicalCameraSettings.begin();
+ EXPECT_EQ(physicalDeviceId1, it->id);
+ EXPECT_TRUE(it->settings.exists(ANDROID_CONTROL_CAPTURE_INTENT));
+ auto entry = it->settings.find(ANDROID_CONTROL_CAPTURE_INTENT);
+ EXPECT_EQ(entry.data.u8[0], intent1);
+ it++;
+ EXPECT_EQ(physicalDeviceId2, it->id);
+ EXPECT_TRUE(it->settings.exists(ANDROID_CONTROL_CAPTURE_INTENT));
+ entry = it->settings.find(ANDROID_CONTROL_CAPTURE_INTENT);
+ EXPECT_EQ(entry.data.u8[0], intent2);
+};
diff --git a/camera/tests/VendorTagDescriptorTests.cpp b/camera/tests/VendorTagDescriptorTests.cpp
index 75cfb73..0ee358d 100644
--- a/camera/tests/VendorTagDescriptorTests.cpp
+++ b/camera/tests/VendorTagDescriptorTests.cpp
@@ -142,6 +142,7 @@
EXPECT_EQ(OK, vDescOriginal->writeToParcel(&p));
p.setDataPosition(0);
+ vDescParceled = new VendorTagDescriptor();
ASSERT_EQ(OK, vDescParceled->readFromParcel(&p));
// Ensure consistent tag count
diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp
index 67017eb..5500d24 100644
--- a/cmds/stagefright/audioloop.cpp
+++ b/cmds/stagefright/audioloop.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+#define LOG_NDEBUG 0
+#define LOG_TAG "audioloop"
+#include <utils/Log.h>
+
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -37,11 +41,13 @@
static void usage(const char* name)
{
- fprintf(stderr, "Usage: %s [-d du.ration] [-m] [-w] [<output-file>]\n", name);
+ fprintf(stderr, "Usage: %s [-d du.ration] [-m] [-w] [-N name] [<output-file>]\n", name);
fprintf(stderr, "Encodes either a sine wave or microphone input to AMR format\n");
fprintf(stderr, " -d duration in seconds, default 5 seconds\n");
fprintf(stderr, " -m use microphone for input, default sine source\n");
fprintf(stderr, " -w use AMR wideband (default narrowband)\n");
+ fprintf(stderr, " -N name of the encoder; must be set with -M\n");
+ fprintf(stderr, " -M media type of the encoder; must be set with -N\n");
fprintf(stderr, " <output-file> output file for AMR encoding,"
" if unspecified, decode to speaker.\n");
}
@@ -54,8 +60,10 @@
bool outputWBAMR = false;
bool playToSpeaker = true;
const char* fileOut = NULL;
+ AString name;
+ AString mediaType;
int ch;
- while ((ch = getopt(argc, argv, "d:mw")) != -1) {
+ while ((ch = getopt(argc, argv, "d:mwN:M:")) != -1) {
switch (ch) {
case 'd':
duration = atoi(optarg);
@@ -66,6 +74,12 @@
case 'w':
outputWBAMR = true;
break;
+ case 'N':
+ name.setTo(optarg);
+ break;
+ case 'M':
+ mediaType.setTo(optarg);
+ break;
default:
usage(argv[0]);
return -1;
@@ -76,8 +90,18 @@
if (argc == 1) {
fileOut = argv[0];
}
- const int32_t kSampleRate = outputWBAMR ? 16000 : 8000;
- const int32_t kBitRate = outputWBAMR ? 16000 : 8000;
+ if ((name.empty() && !mediaType.empty()) || (!name.empty() && mediaType.empty())) {
+ fprintf(stderr, "-N and -M must be set together\n");
+ usage(argv[0]);
+ return -1;
+ }
+ if (!name.empty() && fileOut != NULL) {
+ fprintf(stderr, "-N and -M cannot be used with <output file>\n");
+ usage(argv[0]);
+ return -1;
+ }
+ int32_t sampleRate = !name.empty() ? 44100 : outputWBAMR ? 16000 : 8000;
+ int32_t bitRate = sampleRate;
android::ProcessState::self()->startThreadPool();
sp<MediaSource> source;
@@ -87,22 +111,27 @@
source = new AudioSource(
AUDIO_SOURCE_MIC,
String16(),
- kSampleRate,
+ sampleRate,
channels);
} else {
// use a sine source at 500 hz.
- source = new SineSource(kSampleRate, channels);
+ source = new SineSource(sampleRate, channels);
}
sp<AMessage> meta = new AMessage;
- meta->setString(
- "mime",
- outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB
- : MEDIA_MIMETYPE_AUDIO_AMR_NB);
+ if (name.empty()) {
+ meta->setString(
+ "mime",
+ outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB
+ : MEDIA_MIMETYPE_AUDIO_AMR_NB);
+ } else {
+ meta->setString("mime", mediaType);
+ meta->setString("testing-name", name);
+ }
meta->setInt32("channel-count", channels);
- meta->setInt32("sample-rate", kSampleRate);
- meta->setInt32("bitrate", kBitRate);
+ meta->setInt32("sample-rate", sampleRate);
+ meta->setInt32("bitrate", bitRate);
int32_t maxInputSize;
if (source->getFormat()->findInt32(kKeyMaxInputSize, &maxInputSize)) {
meta->setInt32("max-input-size", maxInputSize);
@@ -131,13 +160,14 @@
sp<MediaSource> decoder = SimpleDecodingSource::Create(encoder);
if (playToSpeaker) {
- AudioPlayer *player = new AudioPlayer(NULL);
- player->setSource(decoder);
- player->start();
+ AudioPlayer player(NULL);
+ player.setSource(decoder);
+ player.start();
sleep(duration);
+ALOGI("Line: %d", __LINE__);
decoder.clear(); // must clear |decoder| otherwise delete player will hang.
- delete player; // there is no player->stop()...
+ALOGI("Line: %d", __LINE__);
} else {
CHECK_EQ(decoder->start(), (status_t)OK);
MediaBuffer* buffer;
@@ -151,6 +181,7 @@
}
CHECK_EQ(decoder->stop(), (status_t)OK);
}
+ALOGI("Line: %d", __LINE__);
}
return 0;
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 5da8114..e40a6cd 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -510,7 +510,9 @@
* This could, for example, affect which microphones are used and how the
* recorded data is processed.
*
- * The default, if you do not call this function, is AAUDIO_INPUT_PRESET_GENERIC.
+ * The default, if you do not call this function, is AAUDIO_INPUT_PRESET_VOICE_RECOGNITION.
+ * That is because VOICE_RECOGNITION is the preset with the lowest latency
+ * on many platforms.
*
* @param builder reference provided by AAudio_createStreamBuilder()
* @param inputPreset the desired configuration for recording
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 82c0667..9a2405a 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -93,7 +93,7 @@
}
mInputPreset = builder.getInputPreset();
if (mInputPreset == AAUDIO_UNSPECIFIED) {
- mInputPreset = AAUDIO_INPUT_PRESET_GENERIC;
+ mInputPreset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
}
// callbacks
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 42b585f..c59ee6c 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -515,9 +515,9 @@
aaudio_stream_state_t mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
- aaudio_usage_t mUsage = AAUDIO_USAGE_MEDIA;
- aaudio_content_type_t mContentType = AAUDIO_CONTENT_TYPE_MUSIC;
- aaudio_input_preset_t mInputPreset = AAUDIO_INPUT_PRESET_GENERIC;
+ aaudio_usage_t mUsage = AAUDIO_UNSPECIFIED;
+ aaudio_content_type_t mContentType = AAUDIO_UNSPECIFIED;
+ aaudio_input_preset_t mInputPreset = AAUDIO_UNSPECIFIED;
int32_t mSessionId = AAUDIO_UNSPECIFIED;
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index c5dfb7c..3352b33 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -86,10 +86,15 @@
// AudioRecord::Buffer
// TODO define our own AudioBuffer and pass it from the subclasses.
AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
- if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED || !mCallbackEnabled.load()) {
+ if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) {
+ ALOGW("processCallbackCommon() data, stream disconnected");
+ audioBuffer->size = SIZE_STOP_CALLBACKS;
+ } else if (!mCallbackEnabled.load()) {
+ ALOGW("processCallbackCommon() stopping because callback disabled");
audioBuffer->size = SIZE_STOP_CALLBACKS;
} else {
if (audioBuffer->frameCount == 0) {
+ ALOGW("processCallbackCommon() data, frameCount is zero");
return;
}
@@ -106,7 +111,7 @@
if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
audioBuffer->size = audioBuffer->frameCount * getBytesPerFrame();
} else { // STOP or invalid result
- ALOGW("%s() stop stream by faking an error", __func__);
+ ALOGW("%s() callback requested stop, fake an error", __func__);
audioBuffer->size = SIZE_STOP_CALLBACKS;
// Disable the callback just in case AudioFlinger keeps trying to call us.
mCallbackEnabled.store(false);
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.h b/media/libaaudio/src/legacy/AudioStreamLegacy.h
index 6a506b3..494edbc 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.h
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.h
@@ -121,9 +121,6 @@
void forceDisconnect(bool errorCallbackEnabled = true);
- void onStart() { mCallbackEnabled.store(true); }
- void onStop() { mCallbackEnabled.store(false); }
-
int64_t incrementFramesWritten(int32_t frames) {
return mFramesWritten.increment(frames);
}
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 61a0f8a..f7ae7d7 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -244,11 +244,13 @@
return AAudioConvert_androidToAAudioResult(err);
}
+ // Enable callback before starting AudioTrack to avoid shutting
+ // down because of a race condition.
+ mCallbackEnabled.store(true);
err = mAudioRecord->start();
if (err != OK) {
return AAudioConvert_androidToAAudioResult(err);
} else {
- onStart();
setState(AAUDIO_STREAM_STATE_STARTING);
}
return AAUDIO_OK;
@@ -258,11 +260,11 @@
if (mAudioRecord.get() == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
}
- onStop();
setState(AAUDIO_STREAM_STATE_STOPPING);
incrementFramesWritten(getFramesRead() - getFramesWritten()); // TODO review
mTimestampPosition.set(getFramesRead());
mAudioRecord->stop();
+ mCallbackEnabled.store(false);
mFramesRead.reset32();
mTimestampPosition.reset32();
// Pass false to prevent errorCallback from being called after disconnect
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 52c7822..4d1b187 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -271,11 +271,13 @@
return AAudioConvert_androidToAAudioResult(err);
}
+ // Enable callback before starting AudioTrack to avoid shutting
+ // down because of a race condition.
+ mCallbackEnabled.store(true);
err = mAudioTrack->start();
if (err != OK) {
return AAudioConvert_androidToAAudioResult(err);
} else {
- onStart();
setState(AAUDIO_STREAM_STATE_STARTING);
}
return AAUDIO_OK;
@@ -292,9 +294,9 @@
AAudio_convertStreamStateToText(getState()));
return AAUDIO_ERROR_INVALID_STATE;
}
- onStop();
setState(AAUDIO_STREAM_STATE_PAUSING);
mAudioTrack->pause();
+ mCallbackEnabled.store(false);
status_t err = mAudioTrack->getPosition(&mPositionWhenPausing);
if (err != OK) {
return AAudioConvert_androidToAAudioResult(err);
@@ -323,13 +325,13 @@
ALOGE("requestStop() no AudioTrack");
return AAUDIO_ERROR_INVALID_STATE;
}
- onStop();
setState(AAUDIO_STREAM_STATE_STOPPING);
incrementFramesRead(getFramesWritten() - getFramesRead()); // TODO review
mTimestampPosition.set(getFramesWritten());
mFramesWritten.reset32();
mTimestampPosition.reset32();
mAudioTrack->stop();
+ mCallbackEnabled.store(false);
return checkForDisconnectRequest(false);;
}
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 2bee6e3..2a34016 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -341,7 +341,7 @@
STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION == AUDIO_SOURCE_VOICE_COMMUNICATION);
STATIC_ASSERT(AAUDIO_INPUT_PRESET_UNPROCESSED == AUDIO_SOURCE_UNPROCESSED);
if (preset == AAUDIO_UNSPECIFIED) {
- preset = AAUDIO_INPUT_PRESET_GENERIC;
+ preset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
}
return (audio_source_t) preset; // same value
}
diff --git a/media/libaaudio/tests/test_attributes.cpp b/media/libaaudio/tests/test_attributes.cpp
index 9cbf113..b01af25 100644
--- a/media/libaaudio/tests/test_attributes.cpp
+++ b/media/libaaudio/tests/test_attributes.cpp
@@ -76,7 +76,7 @@
aaudio_input_preset_t expectedPreset =
(preset == DONT_SET || preset == AAUDIO_UNSPECIFIED)
- ? AAUDIO_INPUT_PRESET_GENERIC // default
+ ? AAUDIO_INPUT_PRESET_VOICE_RECOGNITION // default
: preset;
EXPECT_EQ(expectedPreset, AAudioStream_getInputPreset(aaudioStream));
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 16150f6..7969ed0 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -858,6 +858,7 @@
audio_io_handle_t *output,
audio_session_t session,
audio_stream_type_t *stream,
+ pid_t pid,
uid_t uid,
const audio_config_t *config,
audio_output_flags_t flags,
@@ -866,7 +867,7 @@
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return NO_INIT;
- return aps->getOutputForAttr(attr, output, session, stream, uid,
+ return aps->getOutputForAttr(attr, output, session, stream, pid, uid,
config,
flags, selectedDeviceId, portId);
}
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index c0e53b3..6478975 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -174,6 +174,7 @@
audio_io_handle_t *output,
audio_session_t session,
audio_stream_type_t *stream,
+ pid_t pid,
uid_t uid,
const audio_config_t *config,
audio_output_flags_t flags,
@@ -217,6 +218,7 @@
data.writeInt32(1);
data.writeInt32(*stream);
}
+ data.writeInt32(pid);
data.writeInt32(uid);
data.write(config, sizeof(audio_config_t));
data.writeInt32(static_cast <uint32_t>(flags));
@@ -968,6 +970,7 @@
if (hasStream) {
stream = (audio_stream_type_t)data.readInt32();
}
+ pid_t pid = (pid_t)data.readInt32();
uid_t uid = (uid_t)data.readInt32();
audio_config_t config;
memset(&config, 0, sizeof(audio_config_t));
@@ -978,7 +981,7 @@
audio_port_handle_t portId = (audio_port_handle_t)data.readInt32();
audio_io_handle_t output = 0;
status_t status = getOutputForAttr(hasAttributes ? &attr : NULL,
- &output, session, &stream, uid,
+ &output, session, &stream, pid, uid,
&config,
flags, &selectedDeviceId, &portId);
reply->writeInt32(status);
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index d6cc37a..e452837 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -216,6 +216,7 @@
audio_io_handle_t *output,
audio_session_t session,
audio_stream_type_t *stream,
+ pid_t pid,
uid_t uid,
const audio_config_t *config,
audio_output_flags_t flags,
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 7e9413d..5338927 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -60,6 +60,7 @@
audio_io_handle_t *output,
audio_session_t session,
audio_stream_type_t *stream,
+ pid_t pid,
uid_t uid,
const audio_config_t *config,
audio_output_flags_t flags,
diff --git a/media/libaudiohal/2.0/Android.bp b/media/libaudiohal/2.0/Android.bp
new file mode 100644
index 0000000..574b435
--- /dev/null
+++ b/media/libaudiohal/2.0/Android.bp
@@ -0,0 +1,54 @@
+cc_library_shared {
+ name: "libaudiohal@2.0",
+
+ srcs: [
+ "DeviceHalLocal.cpp",
+ "DevicesFactoryHalHybrid.cpp",
+ "DevicesFactoryHalLocal.cpp",
+ "StreamHalLocal.cpp",
+
+ "ConversionHelperHidl.cpp",
+ "DeviceHalHidl.cpp",
+ "DevicesFactoryHalHidl.cpp",
+ "EffectBufferHalHidl.cpp",
+ "EffectHalHidl.cpp",
+ "EffectsFactoryHalHidl.cpp",
+ "StreamHalHidl.cpp",
+ ],
+
+ export_include_dirs: ["."],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libaudiohal_deathhandler",
+ "libaudioutils",
+ "libcutils",
+ "liblog",
+ "libutils",
+ "libhardware",
+ "libbase",
+ "libfmq",
+ "libhwbinder",
+ "libhidlbase",
+ "libhidlmemory",
+ "libhidltransport",
+ "android.hardware.audio@2.0",
+ "android.hardware.audio.common@2.0",
+ "android.hardware.audio.common@2.0-util",
+ "android.hardware.audio.effect@2.0",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory@1.0",
+ "libmedia_helper",
+ "libmediautils",
+ ],
+ header_libs: [
+ "libaudiohal_headers"
+ ],
+
+ export_shared_lib_headers: [
+ "libfmq",
+ ],
+}
diff --git a/media/libaudiohal/ConversionHelperHidl.cpp b/media/libaudiohal/2.0/ConversionHelperHidl.cpp
similarity index 100%
rename from media/libaudiohal/ConversionHelperHidl.cpp
rename to media/libaudiohal/2.0/ConversionHelperHidl.cpp
diff --git a/media/libaudiohal/ConversionHelperHidl.h b/media/libaudiohal/2.0/ConversionHelperHidl.h
similarity index 100%
rename from media/libaudiohal/ConversionHelperHidl.h
rename to media/libaudiohal/2.0/ConversionHelperHidl.h
diff --git a/media/libaudiohal/DeviceHalHidl.cpp b/media/libaudiohal/2.0/DeviceHalHidl.cpp
similarity index 99%
rename from media/libaudiohal/DeviceHalHidl.cpp
rename to media/libaudiohal/2.0/DeviceHalHidl.cpp
index 49ef991..0d9c6c4 100644
--- a/media/libaudiohal/DeviceHalHidl.cpp
+++ b/media/libaudiohal/2.0/DeviceHalHidl.cpp
@@ -37,6 +37,7 @@
using ::android::hardware::audio::common::V2_0::AudioPortConfig;
using ::android::hardware::audio::common::V2_0::AudioMode;
using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::common::V2_0::HidlUtils;
using ::android::hardware::audio::V2_0::DeviceAddress;
using ::android::hardware::audio::V2_0::IPrimaryDevice;
using ::android::hardware::audio::V2_0::ParameterValue;
diff --git a/media/libaudiohal/DeviceHalHidl.h b/media/libaudiohal/2.0/DeviceHalHidl.h
similarity index 100%
rename from media/libaudiohal/DeviceHalHidl.h
rename to media/libaudiohal/2.0/DeviceHalHidl.h
diff --git a/media/libaudiohal/DeviceHalLocal.cpp b/media/libaudiohal/2.0/DeviceHalLocal.cpp
similarity index 100%
rename from media/libaudiohal/DeviceHalLocal.cpp
rename to media/libaudiohal/2.0/DeviceHalLocal.cpp
diff --git a/media/libaudiohal/DeviceHalLocal.h b/media/libaudiohal/2.0/DeviceHalLocal.h
similarity index 100%
rename from media/libaudiohal/DeviceHalLocal.h
rename to media/libaudiohal/2.0/DeviceHalLocal.h
diff --git a/media/libaudiohal/DevicesFactoryHalHidl.cpp b/media/libaudiohal/2.0/DevicesFactoryHalHidl.cpp
similarity index 100%
rename from media/libaudiohal/DevicesFactoryHalHidl.cpp
rename to media/libaudiohal/2.0/DevicesFactoryHalHidl.cpp
diff --git a/media/libaudiohal/DevicesFactoryHalHidl.h b/media/libaudiohal/2.0/DevicesFactoryHalHidl.h
similarity index 100%
rename from media/libaudiohal/DevicesFactoryHalHidl.h
rename to media/libaudiohal/2.0/DevicesFactoryHalHidl.h
diff --git a/media/libaudiohal/DevicesFactoryHalHybrid.cpp b/media/libaudiohal/2.0/DevicesFactoryHalHybrid.cpp
similarity index 91%
rename from media/libaudiohal/DevicesFactoryHalHybrid.cpp
rename to media/libaudiohal/2.0/DevicesFactoryHalHybrid.cpp
index 8dc1434..77df6b5 100644
--- a/media/libaudiohal/DevicesFactoryHalHybrid.cpp
+++ b/media/libaudiohal/2.0/DevicesFactoryHalHybrid.cpp
@@ -23,11 +23,6 @@
namespace android {
-// static
-sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
- return new DevicesFactoryHalHybrid();
-}
-
DevicesFactoryHalHybrid::DevicesFactoryHalHybrid()
: mLocalFactory(new DevicesFactoryHalLocal()),
mHidlFactory(new DevicesFactoryHalHidl()) {
diff --git a/media/libaudiohal/DevicesFactoryHalHybrid.h b/media/libaudiohal/2.0/DevicesFactoryHalHybrid.h
similarity index 100%
rename from media/libaudiohal/DevicesFactoryHalHybrid.h
rename to media/libaudiohal/2.0/DevicesFactoryHalHybrid.h
diff --git a/media/libaudiohal/DevicesFactoryHalLocal.cpp b/media/libaudiohal/2.0/DevicesFactoryHalLocal.cpp
similarity index 100%
rename from media/libaudiohal/DevicesFactoryHalLocal.cpp
rename to media/libaudiohal/2.0/DevicesFactoryHalLocal.cpp
diff --git a/media/libaudiohal/DevicesFactoryHalLocal.h b/media/libaudiohal/2.0/DevicesFactoryHalLocal.h
similarity index 100%
rename from media/libaudiohal/DevicesFactoryHalLocal.h
rename to media/libaudiohal/2.0/DevicesFactoryHalLocal.h
diff --git a/media/libaudiohal/EffectBufferHalHidl.cpp b/media/libaudiohal/2.0/EffectBufferHalHidl.cpp
similarity index 97%
rename from media/libaudiohal/EffectBufferHalHidl.cpp
rename to media/libaudiohal/2.0/EffectBufferHalHidl.cpp
index 8b5201b..226a500 100644
--- a/media/libaudiohal/EffectBufferHalHidl.cpp
+++ b/media/libaudiohal/2.0/EffectBufferHalHidl.cpp
@@ -37,14 +37,12 @@
return counter++;
}
-// static
-status_t EffectBufferHalInterface::allocate(
+status_t EffectBufferHalHidl::allocate(
size_t size, sp<EffectBufferHalInterface>* buffer) {
return mirror(nullptr, size, buffer);
}
-// static
-status_t EffectBufferHalInterface::mirror(
+status_t EffectBufferHalHidl::mirror(
void* external, size_t size, sp<EffectBufferHalInterface>* buffer) {
sp<EffectBufferHalInterface> tempBuffer = new EffectBufferHalHidl(size);
status_t result = static_cast<EffectBufferHalHidl*>(tempBuffer.get())->init();
diff --git a/media/libaudiohal/EffectBufferHalHidl.h b/media/libaudiohal/2.0/EffectBufferHalHidl.h
similarity index 92%
rename from media/libaudiohal/EffectBufferHalHidl.h
rename to media/libaudiohal/2.0/EffectBufferHalHidl.h
index d7a43ae..31e0087 100644
--- a/media/libaudiohal/EffectBufferHalHidl.h
+++ b/media/libaudiohal/2.0/EffectBufferHalHidl.h
@@ -32,6 +32,9 @@
class EffectBufferHalHidl : public EffectBufferHalInterface
{
public:
+ static status_t allocate(size_t size, sp<EffectBufferHalInterface>* buffer);
+ static status_t mirror(void* external, size_t size, sp<EffectBufferHalInterface>* buffer);
+
virtual audio_buffer_t* audioBuffer();
virtual void* externalData() const;
diff --git a/media/libaudiohal/EffectHalHidl.cpp b/media/libaudiohal/2.0/EffectHalHidl.cpp
similarity index 99%
rename from media/libaudiohal/EffectHalHidl.cpp
rename to media/libaudiohal/2.0/EffectHalHidl.cpp
index f4d1958..4fb032c 100644
--- a/media/libaudiohal/EffectHalHidl.cpp
+++ b/media/libaudiohal/2.0/EffectHalHidl.cpp
@@ -31,6 +31,7 @@
using ::android::hardware::audio::effect::V2_0::EffectConfigParameters;
using ::android::hardware::audio::effect::V2_0::MessageQueueFlagBits;
using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::audio::common::V2_0::HidlUtils;
using ::android::hardware::audio::common::V2_0::AudioChannelMask;
using ::android::hardware::audio::common::V2_0::AudioFormat;
using ::android::hardware::hidl_vec;
diff --git a/media/libaudiohal/EffectHalHidl.h b/media/libaudiohal/2.0/EffectHalHidl.h
similarity index 100%
rename from media/libaudiohal/EffectHalHidl.h
rename to media/libaudiohal/2.0/EffectHalHidl.h
diff --git a/media/libaudiohal/EffectsFactoryHalHidl.cpp b/media/libaudiohal/2.0/EffectsFactoryHalHidl.cpp
similarity index 91%
rename from media/libaudiohal/EffectsFactoryHalHidl.cpp
rename to media/libaudiohal/2.0/EffectsFactoryHalHidl.cpp
index a8081b7..0d40e6d 100644
--- a/media/libaudiohal/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/2.0/EffectsFactoryHalHidl.cpp
@@ -20,10 +20,12 @@
#include <cutils/native_handle.h>
#include "ConversionHelperHidl.h"
+#include "EffectBufferHalHidl.h"
#include "EffectHalHidl.h"
#include "EffectsFactoryHalHidl.h"
#include "HidlUtils.h"
+using ::android::hardware::audio::common::V2_0::HidlUtils;
using ::android::hardware::audio::common::V2_0::Uuid;
using ::android::hardware::audio::effect::V2_0::IEffect;
using ::android::hardware::audio::effect::V2_0::Result;
@@ -31,16 +33,6 @@
namespace android {
-// static
-sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
- return new EffectsFactoryHalHidl();
-}
-
-// static
-bool EffectsFactoryHalInterface::isNullUuid(const effect_uuid_t *pEffectUuid) {
- return memcmp(pEffectUuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t)) == 0;
-}
-
EffectsFactoryHalHidl::EffectsFactoryHalHidl() : ConversionHelperHidl("EffectsFactory") {
mEffectsFactory = IEffectsFactory::getService();
if (mEffectsFactory == 0) {
@@ -145,4 +137,14 @@
return processReturn(__FUNCTION__, ret);
}
+status_t EffectsFactoryHalHidl::allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) {
+ return EffectBufferHalHidl::allocate(size, buffer);
+}
+
+status_t EffectsFactoryHalHidl::mirrorBuffer(void* external, size_t size,
+ sp<EffectBufferHalInterface>* buffer) {
+ return EffectBufferHalHidl::mirror(external, size, buffer);
+}
+
+
} // namespace android
diff --git a/media/libaudiohal/EffectsFactoryHalHidl.h b/media/libaudiohal/2.0/EffectsFactoryHalHidl.h
similarity index 90%
rename from media/libaudiohal/EffectsFactoryHalHidl.h
rename to media/libaudiohal/2.0/EffectsFactoryHalHidl.h
index e89f042..82b5481 100644
--- a/media/libaudiohal/EffectsFactoryHalHidl.h
+++ b/media/libaudiohal/2.0/EffectsFactoryHalHidl.h
@@ -21,6 +21,8 @@
#include <android/hardware/audio/effect/2.0/types.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include "ConversionHelperHidl.h"
+
namespace android {
using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
@@ -49,6 +51,10 @@
virtual status_t dumpEffects(int fd);
+ status_t allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override;
+ status_t mirrorBuffer(void* external, size_t size,
+ sp<EffectBufferHalInterface>* buffer) override;
+
private:
friend class EffectsFactoryHalInterface;
diff --git a/media/libaudiohal/StreamHalHidl.cpp b/media/libaudiohal/2.0/StreamHalHidl.cpp
similarity index 100%
rename from media/libaudiohal/StreamHalHidl.cpp
rename to media/libaudiohal/2.0/StreamHalHidl.cpp
diff --git a/media/libaudiohal/StreamHalHidl.h b/media/libaudiohal/2.0/StreamHalHidl.h
similarity index 100%
rename from media/libaudiohal/StreamHalHidl.h
rename to media/libaudiohal/2.0/StreamHalHidl.h
diff --git a/media/libaudiohal/StreamHalLocal.cpp b/media/libaudiohal/2.0/StreamHalLocal.cpp
similarity index 100%
rename from media/libaudiohal/StreamHalLocal.cpp
rename to media/libaudiohal/2.0/StreamHalLocal.cpp
diff --git a/media/libaudiohal/StreamHalLocal.h b/media/libaudiohal/2.0/StreamHalLocal.h
similarity index 100%
rename from media/libaudiohal/StreamHalLocal.h
rename to media/libaudiohal/2.0/StreamHalLocal.h
diff --git a/media/libaudiohal/StreamPowerLog.h b/media/libaudiohal/2.0/StreamPowerLog.h
similarity index 100%
rename from media/libaudiohal/StreamPowerLog.h
rename to media/libaudiohal/2.0/StreamPowerLog.h
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 700de8e..7ecb9d8 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -2,46 +2,52 @@
name: "libaudiohal",
srcs: [
- "DeviceHalLocal.cpp",
- "DevicesFactoryHalHybrid.cpp",
- "DevicesFactoryHalLocal.cpp",
- "StreamHalLocal.cpp",
-
- "ConversionHelperHidl.cpp",
- "HalDeathHandlerHidl.cpp",
- "DeviceHalHidl.cpp",
- "DevicesFactoryHalHidl.cpp",
- "EffectBufferHalHidl.cpp",
- "EffectHalHidl.cpp",
- "EffectsFactoryHalHidl.cpp",
- "StreamHalHidl.cpp",
+ "DevicesFactoryHalInterface.cpp",
+ "EffectsFactoryHalInterface.cpp",
],
cflags: [
"-Wall",
"-Werror",
],
- export_include_dirs: ["include"],
shared_libs: [
- "libaudioutils",
- "libcutils",
- "liblog",
- "libutils",
- "libhardware",
- "libbase",
- "libfmq",
- "libhwbinder",
- "libhidlbase",
- "libhidlmemory",
- "libhidltransport",
"android.hardware.audio@2.0",
- "android.hardware.audio.common@2.0",
- "android.hardware.audio.common@2.0-util",
"android.hardware.audio.effect@2.0",
- "android.hidl.allocator@1.0",
- "android.hidl.memory@1.0",
- "libmedia_helper",
- "libmediautils",
+ "libaudiohal@2.0",
+ "libutils",
],
+
+ header_libs: [
+ "libaudiohal_headers"
+ ]
+}
+
+cc_library_shared {
+ name: "libaudiohal_deathhandler",
+
+ srcs: [
+ "HalDeathHandlerHidl.cpp",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ shared_libs: [
+ "libhidlbase",
+ "libutils",
+ "liblog",
+ ],
+
+ header_libs: [
+ "libaudiohal_headers"
+ ]
+}
+
+cc_library_headers {
+ name: "libaudiohal_headers",
+
+ export_include_dirs: ["include"],
}
diff --git a/media/libaudiohal/DevicesFactoryHalInterface.cpp b/media/libaudiohal/DevicesFactoryHalInterface.cpp
new file mode 100644
index 0000000..cfec3d6
--- /dev/null
+++ b/media/libaudiohal/DevicesFactoryHalInterface.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 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 "DevicesFactoryHalHybrid.h"
+#include <android/hardware/audio/2.0/IDevicesFactory.h>
+
+using namespace ::android::hardware::audio;
+
+namespace android {
+
+// static
+sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
+ if (V2_0::IDevicesFactory::getService() != nullptr) {
+ return new DevicesFactoryHalHybrid();
+ }
+ return nullptr;
+}
+
+} // namespace android
diff --git a/media/libaudiohal/EffectsFactoryHalInterface.cpp b/media/libaudiohal/EffectsFactoryHalInterface.cpp
new file mode 100644
index 0000000..01a171e
--- /dev/null
+++ b/media/libaudiohal/EffectsFactoryHalInterface.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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_TAG "EffectsFactoryHalHidl"
+//#define LOG_NDEBUG 0
+
+#include "EffectHalHidl.h"
+#include "EffectsFactoryHalHidl.h"
+
+using ::android::hardware::Return;
+
+using namespace ::android::hardware::audio::effect;
+
+namespace android {
+
+// static
+sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
+ if (V2_0::IEffectsFactory::getService() != nullptr) {
+ return new EffectsFactoryHalHidl();
+ }
+ return nullptr;
+}
+
+// static
+bool EffectsFactoryHalInterface::isNullUuid(const effect_uuid_t *pEffectUuid) {
+ return memcmp(pEffectUuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t)) == 0;
+}
+
+} // namespace android
diff --git a/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h
index 1cae662..d0603cd 100644
--- a/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h
@@ -26,6 +26,7 @@
// Abstraction for an audio buffer. It may be a "mirror" for
// a buffer that the effect chain doesn't own, or a buffer owned by
// the effect chain.
+// Buffers are created from EffectsFactoryHalInterface
class EffectBufferHalInterface : public RefBase
{
public:
@@ -49,9 +50,6 @@
virtual void update(size_t size) = 0; // copies partial data from external buffer
virtual void commit(size_t size) = 0; // copies partial data to external buffer
- static status_t allocate(size_t size, sp<EffectBufferHalInterface>* buffer);
- static status_t mirror(void* external, size_t size, sp<EffectBufferHalInterface>* buffer);
-
protected:
// Subclasses can not be constructed directly by clients.
EffectBufferHalInterface() {}
diff --git a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
index a616e86..316a46c 100644
--- a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
@@ -48,6 +48,10 @@
static sp<EffectsFactoryHalInterface> create();
+ virtual status_t allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) = 0;
+ virtual status_t mirrorBuffer(void* external, size_t size,
+ sp<EffectBufferHalInterface>* buffer) = 0;
+
// Helper function to compare effect uuid to EFFECT_UUID_NULL.
static bool isNullUuid(const effect_uuid_t *pEffectUuid);
diff --git a/media/libaudioprocessing/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
index 862fef6..e19af4a 100644
--- a/media/libaudioprocessing/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -183,7 +183,7 @@
mOutFrameSize =
audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(outputChannelMask);
status_t status;
- status = EffectBufferHalInterface::mirror(
+ status = mEffectsFactory->mirrorBuffer(
nullptr, mInFrameSize * bufferFrameCount, &mInBuffer);
if (status != 0) {
ALOGE("DownmixerBufferProvider() error %d while creating input buffer", status);
@@ -191,7 +191,7 @@
mEffectsFactory.clear();
return;
}
- status = EffectBufferHalInterface::mirror(
+ status = mEffectsFactory->mirrorBuffer(
nullptr, mOutFrameSize * bufferFrameCount, &mOutBuffer);
if (status != 0) {
ALOGE("DownmixerBufferProvider() error %d while creating output buffer", status);
diff --git a/media/libmedia/TypeConverter.cpp b/media/libmedia/TypeConverter.cpp
index 9b06047..ae232b5 100644
--- a/media/libmedia/TypeConverter.cpp
+++ b/media/libmedia/TypeConverter.cpp
@@ -115,6 +115,9 @@
MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DIRECT_PCM),
MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ),
MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
+ // FIXME: this cast will be removed when the flag will be
+ // declared in types.hal for audio HAL V4.0 and auto imported to audio-base.h
+ MAKE_STRING_FROM_ENUM((audio_output_flags_t)AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
TERMINATOR
};
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index cf800b2..8bd0a51 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -457,13 +457,6 @@
mGeneration(0) {
CHECK(mLooper != NULL);
- AString mime;
- CHECK(mOutputFormat->findString("mime", &mime));
-
- if (!strncasecmp("video/", mime.c_str(), 6)) {
- mIsVideo = true;
- }
-
if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
mPuller = new Puller(source);
}
@@ -487,6 +480,7 @@
}
status_t MediaCodecSource::initEncoder() {
+
mReflector = new AHandlerReflector<MediaCodecSource>(this);
mLooper->registerHandler(mReflector);
@@ -500,23 +494,12 @@
AString outputMIME;
CHECK(mOutputFormat->findString("mime", &outputMIME));
+ mIsVideo = outputMIME.startsWithIgnoreCase("video/");
- Vector<AString> matchingCodecs;
- MediaCodecList::findMatchingCodecs(
- outputMIME.c_str(), true /* encoder */,
- ((mFlags & FLAG_PREFER_SOFTWARE_CODEC) ? MediaCodecList::kPreferSoftwareCodecs : 0),
- &matchingCodecs);
-
+ AString name;
status_t err = NO_INIT;
- for (size_t ix = 0; ix < matchingCodecs.size(); ++ix) {
- mEncoder = MediaCodec::CreateByComponentName(
- mCodecLooper, matchingCodecs[ix]);
-
- if (mEncoder == NULL) {
- continue;
- }
-
- ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
+ if (mOutputFormat->findString("testing-name", &name)) {
+ mEncoder = MediaCodec::CreateByComponentName(mCodecLooper, name);
mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector);
mEncoder->setCallback(mEncoderActivityNotify);
@@ -526,12 +509,38 @@
NULL /* nativeWindow */,
NULL /* crypto */,
MediaCodec::CONFIGURE_FLAG_ENCODE);
+ } else {
+ Vector<AString> matchingCodecs;
+ MediaCodecList::findMatchingCodecs(
+ outputMIME.c_str(), true /* encoder */,
+ ((mFlags & FLAG_PREFER_SOFTWARE_CODEC) ? MediaCodecList::kPreferSoftwareCodecs : 0),
+ &matchingCodecs);
- if (err == OK) {
- break;
+ for (size_t ix = 0; ix < matchingCodecs.size(); ++ix) {
+ mEncoder = MediaCodec::CreateByComponentName(
+ mCodecLooper, matchingCodecs[ix]);
+
+ if (mEncoder == NULL) {
+ continue;
+ }
+
+ ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
+
+ mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector);
+ mEncoder->setCallback(mEncoderActivityNotify);
+
+ err = mEncoder->configure(
+ mOutputFormat,
+ NULL /* nativeWindow */,
+ NULL /* crypto */,
+ MediaCodec::CONFIGURE_FLAG_ENCODE);
+
+ if (err == OK) {
+ break;
+ }
+ mEncoder->release();
+ mEncoder = NULL;
}
- mEncoder->release();
- mEncoder = NULL;
}
if (err != OK) {
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 353a5e4..078c646 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -38,8 +38,6 @@
namespace android {
-static const char *kSystemApkPath = "/system/app/MediaComponents/MediaComponents.apk";
-
// static
sp<IMediaExtractor> MediaExtractorFactory::Create(
const sp<DataSource> &source, const char *mime) {
@@ -246,7 +244,7 @@
}
//static
-void MediaExtractorFactory::RegisterExtractors(
+void MediaExtractorFactory::RegisterExtractorsInApk(
const char *apkPath, List<sp<ExtractorPlugin>> &pluginList) {
ALOGV("search for plugins at %s", apkPath);
ZipArchiveHandle zipHandle;
@@ -265,6 +263,8 @@
while (Next(cookie, &entry, &name) == 0) {
String8 libPath = String8(apkPath) + "!/" +
String8(reinterpret_cast<const char*>(name.name), name.name_length);
+ // TODO: Open with a linker namespace so that it can be linked with sub-libraries
+ // within the apk instead of system libraries already loaded.
void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL);
if (libHandle) {
MediaExtractor::GetExtractorDef getDef =
@@ -291,6 +291,38 @@
}
}
+//static
+void MediaExtractorFactory::RegisterExtractorsInSystem(
+ const char *libDirPath, List<sp<ExtractorPlugin>> &pluginList) {
+ ALOGV("search for plugins at %s", libDirPath);
+ DIR *libDir = opendir(libDirPath);
+ if (libDir) {
+ struct dirent* libEntry;
+ while ((libEntry = readdir(libDir))) {
+ String8 libPath = String8(libDirPath) + "/" + libEntry->d_name;
+ void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL);
+ if (libHandle) {
+ MediaExtractor::GetExtractorDef getDef =
+ (MediaExtractor::GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
+ if (getDef) {
+ ALOGV("registering sniffer for %s", libPath.string());
+ RegisterExtractor(
+ new ExtractorPlugin(getDef(), libHandle, libPath), pluginList);
+ } else {
+ ALOGW("%s does not contain sniffer", libPath.string());
+ dlclose(libHandle);
+ }
+ } else {
+ ALOGW("couldn't dlopen(%s) %s", libPath.string(), strerror(errno));
+ }
+ }
+
+ closedir(libDir);
+ } else {
+ ALOGE("couldn't opendir(%s)", libDirPath);
+ }
+}
+
// static
void MediaExtractorFactory::UpdateExtractors(const char *newUpdateApkPath) {
Mutex::Autolock autoLock(gPluginMutex);
@@ -303,10 +335,20 @@
std::shared_ptr<List<sp<ExtractorPlugin>>> newList(new List<sp<ExtractorPlugin>>());
- RegisterExtractors(kSystemApkPath, *newList);
+ RegisterExtractorsInSystem("/system/lib"
+#ifdef __LP64__
+ "64"
+#endif
+ "/extractors", *newList);
+
+ RegisterExtractorsInSystem("/vendor/lib"
+#ifdef __LP64__
+ "64"
+#endif
+ "/extractors", *newList);
if (newUpdateApkPath != nullptr) {
- RegisterExtractors(newUpdateApkPath, *newList);
+ RegisterExtractorsInApk(newUpdateApkPath, *newList);
}
gPlugins = newList;
diff --git a/media/libstagefright/codec2/vndk/C2Store.cpp b/media/libstagefright/codec2/vndk/C2Store.cpp
index daa9d3f..555e77b 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -405,6 +405,7 @@
// TODO: move this also into a .so so it can be updated
mComponents.emplace("c2.google.avc.decoder", "libstagefright_soft_c2avcdec.so");
mComponents.emplace("c2.google.aac.decoder", "libstagefright_soft_c2aacdec.so");
+ mComponents.emplace("c2.google.aac.encoder", "libstagefright_soft_c2aacenc.so");
}
c2_status_t C2PlatformComponentStore::copyBuffer(
diff --git a/media/libstagefright/codecs/aacenc/Android.bp b/media/libstagefright/codecs/aacenc/Android.bp
index 9342351..4caef92 100644
--- a/media/libstagefright/codecs/aacenc/Android.bp
+++ b/media/libstagefright/codecs/aacenc/Android.bp
@@ -1,4 +1,42 @@
cc_library_shared {
+ name: "libstagefright_soft_c2aacenc",
+// vendor_available: true,
+// vndk: {
+// enabled: true,
+// },
+
+ srcs: ["C2SoftAacEnc.cpp"],
+
+ cflags: ["-Werror"],
+
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ "unsigned-integer-overflow",
+ ],
+ cfi: true,
+ diag: {
+ cfi: true,
+ },
+ },
+
+ static_libs: [
+ "libFraunhoferAAC",
+ "libstagefright_codec2_vndk"
+ ],
+
+ shared_libs: [
+ "libcutils",
+ "libion",
+ "liblog",
+ "libstagefright_codec2",
+ "libstagefright_foundation",
+ "libstagefright_simple_c2component",
+ "libutils",
+ ],
+}
+
+cc_library_shared {
name: "libstagefright_soft_aacenc",
vendor_available: true,
vndk: {
diff --git a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
new file mode 100644
index 0000000..94308c4
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2012 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 "C2SoftAacEnc"
+#include <utils/Log.h>
+
+#include <inttypes.h>
+
+#include <C2PlatformSupport.h>
+#include <SimpleC2Interface.h>
+#include <media/stagefright/foundation/hexdump.h>
+
+#include "C2SoftAacEnc.h"
+
+namespace android {
+
+C2SoftAacEnc::C2SoftAacEnc(
+ const char *name,
+ c2_node_id_t id)
+ : SimpleC2Component(
+ SimpleC2Interface::Builder(name, id)
+ .inputFormat(C2FormatAudio)
+ .outputFormat(C2FormatCompressed)
+ .build()),
+ mAACEncoder(NULL),
+ mNumChannels(1),
+ mSampleRate(44100),
+ mBitRate(64000),
+ mSBRMode(-1),
+ mSBRRatio(0),
+ mAACProfile(AOT_AAC_LC),
+ mNumBytesPerInputFrame(0u),
+ mOutBufferSize(0u),
+ mSentCodecSpecificData(false),
+ mInputSize(0),
+ mInputTimeUs(-1ll),
+ mSignalledError(false) {
+}
+
+C2SoftAacEnc::~C2SoftAacEnc() {
+ onReset();
+}
+
+c2_status_t C2SoftAacEnc::onInit() {
+ status_t err = initEncoder();
+ return err == OK ? C2_OK : C2_CORRUPTED;
+}
+
+status_t C2SoftAacEnc::initEncoder() {
+ if (AACENC_OK != aacEncOpen(&mAACEncoder, 0, 0)) {
+ ALOGE("Failed to init AAC encoder");
+ return UNKNOWN_ERROR;
+ }
+ return setAudioParams();
+}
+
+c2_status_t C2SoftAacEnc::onStop() {
+ mSentCodecSpecificData = false;
+ mInputSize = 0u;
+ mInputTimeUs = -1ll;
+ mSignalledError = false;
+ return C2_OK;
+}
+
+void C2SoftAacEnc::onReset() {
+ (void)onStop();
+ aacEncClose(&mAACEncoder);
+}
+
+void C2SoftAacEnc::onRelease() {
+ // no-op
+}
+
+c2_status_t C2SoftAacEnc::onFlush_sm() {
+ mSentCodecSpecificData = false;
+ mInputSize = 0u;
+ return C2_OK;
+}
+
+static CHANNEL_MODE getChannelMode(uint32_t nChannels) {
+ CHANNEL_MODE chMode = MODE_INVALID;
+ switch (nChannels) {
+ case 1: chMode = MODE_1; break;
+ case 2: chMode = MODE_2; break;
+ case 3: chMode = MODE_1_2; break;
+ case 4: chMode = MODE_1_2_1; break;
+ case 5: chMode = MODE_1_2_2; break;
+ case 6: chMode = MODE_1_2_2_1; break;
+ default: chMode = MODE_INVALID;
+ }
+ return chMode;
+}
+
+//static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
+// if (profile == OMX_AUDIO_AACObjectLC) {
+// return AOT_AAC_LC;
+// } else if (profile == OMX_AUDIO_AACObjectHE) {
+// return AOT_SBR;
+// } else if (profile == OMX_AUDIO_AACObjectHE_PS) {
+// return AOT_PS;
+// } else if (profile == OMX_AUDIO_AACObjectLD) {
+// return AOT_ER_AAC_LD;
+// } else if (profile == OMX_AUDIO_AACObjectELD) {
+// return AOT_ER_AAC_ELD;
+// } else {
+// ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
+// return AOT_AAC_LC;
+// }
+//}
+
+status_t C2SoftAacEnc::setAudioParams() {
+ // We call this whenever sample rate, number of channels, bitrate or SBR mode change
+ // in reponse to setParameter calls.
+
+ ALOGV("setAudioParams: %u Hz, %u channels, %u bps, %i sbr mode, %i sbr ratio",
+ mSampleRate, mNumChannels, mBitRate, mSBRMode, mSBRRatio);
+
+ if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT, mAACProfile)) {
+ ALOGE("Failed to set AAC encoder parameters");
+ return UNKNOWN_ERROR;
+ }
+
+ if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mSampleRate)) {
+ ALOGE("Failed to set AAC encoder parameters");
+ return UNKNOWN_ERROR;
+ }
+ if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mBitRate)) {
+ ALOGE("Failed to set AAC encoder parameters");
+ return UNKNOWN_ERROR;
+ }
+ if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE,
+ getChannelMode(mNumChannels))) {
+ ALOGE("Failed to set AAC encoder parameters");
+ return UNKNOWN_ERROR;
+ }
+ if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) {
+ ALOGE("Failed to set AAC encoder parameters");
+ return UNKNOWN_ERROR;
+ }
+
+ if (mSBRMode != -1 && mAACProfile == AOT_ER_AAC_ELD) {
+ if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, mSBRMode)) {
+ ALOGE("Failed to set AAC encoder parameters");
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ /* SBR ratio parameter configurations:
+ 0: Default configuration wherein SBR ratio is configured depending on audio object type by
+ the FDK.
+ 1: Downsampled SBR (default for ELD)
+ 2: Dualrate SBR (default for HE-AAC)
+ */
+ if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, mSBRRatio)) {
+ ALOGE("Failed to set AAC encoder parameters");
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+void C2SoftAacEnc::process(
+ const std::unique_ptr<C2Work> &work,
+ const std::shared_ptr<C2BlockPool> &pool) {
+ work->worklets_processed = 0u;
+
+ if (mSignalledError) {
+ return;
+ }
+ bool eos = (work->input.flags & C2BufferPack::FLAG_END_OF_STREAM) != 0;
+
+ if (!mSentCodecSpecificData) {
+ // The very first thing we want to output is the codec specific
+ // data.
+
+ if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) {
+ ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
+ // TODO: notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
+ uint32_t actualBitRate = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
+ if (mBitRate != actualBitRate) {
+ ALOGW("Requested bitrate %u unsupported, using %u", mBitRate, actualBitRate);
+ }
+
+ AACENC_InfoStruct encInfo;
+ if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
+ ALOGE("Failed to get AAC encoder info");
+ // TODO: notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
+ std::unique_ptr<C2StreamCsdInfo::output> csd =
+ C2StreamCsdInfo::output::alloc_unique(encInfo.confSize, 0u);
+ // TODO: check NO_MEMORY
+ memcpy(csd->m.value, encInfo.confBuf, encInfo.confSize);
+ ALOGV("put csd");
+#if defined(LOG_NDEBUG) && !LOG_NDEBUG
+ hexdump(csd->m.value, csd->flexCount());
+#endif
+ work->worklets.front()->output.infos.push_back(std::move(csd));
+
+ mOutBufferSize = encInfo.maxOutBufBytes;
+ mNumBytesPerInputFrame = encInfo.frameLength * mNumChannels * sizeof(int16_t);
+ mInputTimeUs = work->input.ordinal.timestamp;
+
+ mSentCodecSpecificData = true;
+ }
+
+ C2ReadView view = work->input.buffers[0]->data().linearBlocks().front().map().get();
+ uint64_t timestamp = mInputTimeUs;
+
+ size_t numFrames = (view.capacity() + mInputSize + (eos ? mNumBytesPerInputFrame - 1 : 0))
+ / mNumBytesPerInputFrame;
+ ALOGV("capacity = %u; mInputSize = %zu; numFrames = %zu", view.capacity(), mInputSize, numFrames);
+
+ std::shared_ptr<C2LinearBlock> block;
+ std::unique_ptr<C2WriteView> wView;
+ uint8_t *outPtr = nullptr;
+ size_t outAvailable = 0u;
+
+ if (numFrames) {
+ C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
+ // TODO: error handling, proper usage, etc.
+ c2_status_t err = pool->fetchLinearBlock(mOutBufferSize * numFrames, usage, &block);
+ if (err != C2_OK) {
+ ALOGE("err = %d", err);
+ }
+
+ wView.reset(new C2WriteView(block->map().get()));
+ outPtr = wView->data();
+ outAvailable = wView->size();
+ }
+
+ AACENC_InArgs inargs;
+ AACENC_OutArgs outargs;
+ memset(&inargs, 0, sizeof(inargs));
+ memset(&outargs, 0, sizeof(outargs));
+ inargs.numInSamples = view.capacity() / sizeof(int16_t);
+
+ void* inBuffer[] = { (unsigned char *)view.data() };
+ INT inBufferIds[] = { IN_AUDIO_DATA };
+ INT inBufferSize[] = { (INT)view.capacity() };
+ INT inBufferElSize[] = { sizeof(int16_t) };
+
+ AACENC_BufDesc inBufDesc;
+ inBufDesc.numBufs = sizeof(inBuffer) / sizeof(void*);
+ inBufDesc.bufs = (void**)&inBuffer;
+ inBufDesc.bufferIdentifiers = inBufferIds;
+ inBufDesc.bufSizes = inBufferSize;
+ inBufDesc.bufElSizes = inBufferElSize;
+
+ void* outBuffer[] = { outPtr };
+ INT outBufferIds[] = { OUT_BITSTREAM_DATA };
+ INT outBufferSize[] = { 0 };
+ INT outBufferElSize[] = { sizeof(UCHAR) };
+
+ AACENC_BufDesc outBufDesc;
+ outBufDesc.numBufs = sizeof(outBuffer) / sizeof(void*);
+ outBufDesc.bufs = (void**)&outBuffer;
+ outBufDesc.bufferIdentifiers = outBufferIds;
+ outBufDesc.bufSizes = outBufferSize;
+ outBufDesc.bufElSizes = outBufferElSize;
+
+ // Encode the mInputFrame, which is treated as a modulo buffer
+ AACENC_ERROR encoderErr = AACENC_OK;
+ size_t nOutputBytes = 0;
+
+ while (encoderErr == AACENC_OK && inargs.numInSamples > 0) {
+ memset(&outargs, 0, sizeof(outargs));
+
+ outBuffer[0] = outPtr;
+ outBufferSize[0] = outAvailable - nOutputBytes;
+
+ encoderErr = aacEncEncode(mAACEncoder,
+ &inBufDesc,
+ &outBufDesc,
+ &inargs,
+ &outargs);
+
+ if (encoderErr == AACENC_OK) {
+ if (outargs.numOutBytes > 0) {
+ mInputSize = 0;
+ int consumed = ((view.capacity() / sizeof(int16_t)) - inargs.numInSamples);
+ mInputTimeUs = work->input.ordinal.timestamp
+ + (consumed * 1000000ll / mNumChannels / mSampleRate);
+ } else {
+ mInputSize += outargs.numInSamples * sizeof(int16_t);
+ mInputTimeUs += outargs.numInSamples * 1000000ll / mNumChannels / mSampleRate;
+ }
+ outPtr += outargs.numOutBytes;
+ nOutputBytes += outargs.numOutBytes;
+
+ if (outargs.numInSamples > 0) {
+ inBuffer[0] = (int16_t *)inBuffer[0] + outargs.numInSamples;
+ inBufferSize[0] -= outargs.numInSamples * sizeof(int16_t);
+ inargs.numInSamples -= outargs.numInSamples;
+ }
+ }
+ ALOGV("nOutputBytes = %zu; inargs.numInSamples = %d", nOutputBytes, inargs.numInSamples);
+ }
+
+ if (eos && inBufferSize[0] > 0) {
+ memset(&outargs, 0, sizeof(outargs));
+
+ outBuffer[0] = outPtr;
+ outBufferSize[0] = outAvailable - nOutputBytes;
+
+ // Flush
+ inargs.numInSamples = -1;
+
+ (void)aacEncEncode(mAACEncoder,
+ &inBufDesc,
+ &outBufDesc,
+ &inargs,
+ &outargs);
+
+ nOutputBytes += outargs.numOutBytes;
+ }
+
+ work->worklets.front()->output.flags =
+ (C2BufferPack::flags_t)(eos ? C2BufferPack::FLAG_END_OF_STREAM : 0);
+ work->worklets.front()->output.buffers.clear();
+ work->worklets.front()->output.ordinal = work->input.ordinal;
+ work->worklets.front()->output.ordinal.timestamp = timestamp;
+ work->worklets_processed = 1u;
+ if (nOutputBytes) {
+ work->worklets.front()->output.buffers.push_back(
+ createLinearBuffer(block, 0, nOutputBytes));
+ } else {
+ work->worklets.front()->output.buffers.emplace_back(nullptr);
+ }
+
+#if 0
+ ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
+ nOutputBytes, mInputTimeUs, outHeader->nFlags);
+
+ hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
+#endif
+}
+
+c2_status_t C2SoftAacEnc::drain(
+ uint32_t drainMode,
+ const std::shared_ptr<C2BlockPool> &pool) {
+ switch (drainMode) {
+ case DRAIN_COMPONENT_NO_EOS: // fall-through
+ case NO_DRAIN:
+ // no-op
+ return C2_OK;
+ case DRAIN_CHAIN:
+ return C2_OMITTED;
+ case DRAIN_COMPONENT_WITH_EOS:
+ break;
+ default:
+ return C2_BAD_VALUE;
+ }
+
+ (void)pool;
+ mSentCodecSpecificData = false;
+ mInputSize = 0u;
+
+ // TODO: we don't have any pending work at this time to drain.
+ return C2_OK;
+}
+
+class C2SoftAacEncFactory : public C2ComponentFactory {
+public:
+ virtual c2_status_t createComponent(
+ c2_node_id_t id, std::shared_ptr<C2Component>* const component,
+ std::function<void(::android::C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftAacEnc("aacenc", id), deleter);
+ return C2_OK;
+ }
+
+ virtual c2_status_t createInterface(
+ c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
+ std::function<void(::android::C2ComponentInterface*)> deleter) override {
+ *interface =
+ SimpleC2Interface::Builder("aacenc", id, deleter)
+ .inputFormat(C2FormatAudio)
+ .outputFormat(C2FormatCompressed)
+ .build();
+ return C2_OK;
+ }
+
+ virtual ~C2SoftAacEncFactory() override = default;
+};
+
+} // namespace android
+
+extern "C" ::android::C2ComponentFactory* CreateCodec2Factory() {
+ ALOGV("in %s", __func__);
+ return new ::android::C2SoftAacEncFactory();
+}
+
+extern "C" void DestroyCodec2Factory(::android::C2ComponentFactory* factory) {
+ ALOGV("in %s", __func__);
+ delete factory;
+}
diff --git a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.h b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.h
new file mode 100644
index 0000000..947c960
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2018 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 C2_SOFT_AAC_ENC_H_
+
+#define C2_SOFT_AAC_ENC_H_
+
+#include <SimpleC2Component.h>
+#include <media/stagefright/foundation/ABase.h>
+
+#include "aacenc_lib.h"
+
+namespace android {
+
+class C2SoftAacEnc : public SimpleC2Component {
+public:
+ C2SoftAacEnc(const char *name, c2_node_id_t id);
+ virtual ~C2SoftAacEnc();
+
+ // From SimpleC2Component
+ c2_status_t onInit() override;
+ c2_status_t onStop() override;
+ void onReset() override;
+ void onRelease() override;
+ c2_status_t onFlush_sm() override;
+ void process(
+ const std::unique_ptr<C2Work> &work,
+ const std::shared_ptr<C2BlockPool> &pool) override;
+ c2_status_t drain(
+ uint32_t drainMode,
+ const std::shared_ptr<C2BlockPool> &pool) override;
+
+private:
+ HANDLE_AACENCODER mAACEncoder;
+
+ uint32_t mNumChannels;
+ uint32_t mSampleRate;
+ uint32_t mBitRate;
+ int32_t mSBRMode;
+ int32_t mSBRRatio;
+ AUDIO_OBJECT_TYPE mAACProfile;
+ UINT mNumBytesPerInputFrame;
+ UINT mOutBufferSize;
+
+ bool mSentCodecSpecificData;
+ size_t mInputSize;
+ int64_t mInputTimeUs;
+
+ bool mSignalledError;
+
+ status_t initEncoder();
+
+ status_t setAudioParams();
+
+ DISALLOW_EVIL_CONSTRUCTORS(C2SoftAacEnc);
+};
+
+} // namespace android
+
+#endif // C2_SOFT_AAC_ENC_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 55654f1..e5c67e1 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -48,8 +48,10 @@
static std::shared_ptr<List<sp<ExtractorPlugin>>> gPlugins;
static bool gPluginsRegistered;
- static void RegisterExtractors(
+ static void RegisterExtractorsInApk(
const char *apkPath, List<sp<ExtractorPlugin>> &pluginList);
+ static void RegisterExtractorsInSystem(
+ const char *libDirPath, List<sp<ExtractorPlugin>> &pluginList);
static void RegisterExtractor(
const sp<ExtractorPlugin> &plugin, List<sp<ExtractorPlugin>> &pluginList);
diff --git a/packages/MediaComponents/Android.mk b/packages/MediaComponents/Android.mk
index bbd2afa..bb3dc99 100644
--- a/packages/MediaComponents/Android.mk
+++ b/packages/MediaComponents/Android.mk
@@ -34,22 +34,19 @@
LOCAL_JAVA_LIBRARIES += android-support-annotations
-# Embed native libraries in package, rather than installing to /system/lib*.
-# TODO: Find a right way to include libs in the apk. b/72066556
-LOCAL_MODULE_TAGS := samples
-
# To embed native libraries in package, uncomment the lines below.
-LOCAL_JNI_SHARED_LIBRARIES := \
- libaacextractor \
- libamrextractor \
- libflacextractor \
- libmidiextractor \
- libmkvextractor \
- libmp3extractor \
- libmp4extractor \
- libmpeg2extractor \
- liboggextractor \
- libwavextractor \
+#LOCAL_MODULE_TAGS := samples
+#LOCAL_JNI_SHARED_LIBRARIES := \
+# libaacextractor \
+# libamrextractor \
+# libflacextractor \
+# libmidiextractor \
+# libmkvextractor \
+# libmp3extractor \
+# libmp4extractor \
+# libmpeg2extractor \
+# liboggextractor \
+# libwavextractor \
# TODO: Remove dependency with other support libraries.
LOCAL_STATIC_ANDROID_LIBRARIES += \
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index a9d0054..686e3e3 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -309,7 +309,7 @@
fullConfig.format = config->format;
ret = AudioSystem::getOutputForAttr(attr, &io,
actualSessionId,
- &streamType, client.clientUid,
+ &streamType, client.clientPid, client.clientUid,
&fullConfig,
(audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
AUDIO_OUTPUT_FLAG_DIRECT),
@@ -690,7 +690,7 @@
output.selectedDeviceId = input.selectedDeviceId;
lStatus = AudioSystem::getOutputForAttr(&input.attr, &output.outputId, sessionId, &streamType,
- clientUid, &input.config, input.flags,
+ clientPid, clientUid, &input.config, input.flags,
&output.selectedDeviceId, &portId);
if (lStatus != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index b13e551..979290f 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1027,7 +1027,9 @@
|| size > mInConversionBuffer->getSize())) {
mInConversionBuffer.clear();
ALOGV("%s: allocating mInConversionBuffer %zu", __func__, size);
- (void)EffectBufferHalInterface::allocate(size, &mInConversionBuffer);
+ sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
+ LOG_ALWAYS_FATAL_IF(audioFlinger == nullptr, "EM could not retrieved audioFlinger");
+ (void)audioFlinger->mEffectsFactoryHal->allocateBuffer(size, &mInConversionBuffer);
}
if (mInConversionBuffer.get() != nullptr) {
mInConversionBuffer->setFrameCount(inFrameCount);
@@ -1071,7 +1073,9 @@
|| size > mOutConversionBuffer->getSize())) {
mOutConversionBuffer.clear();
ALOGV("%s: allocating mOutConversionBuffer %zu", __func__, size);
- (void)EffectBufferHalInterface::allocate(size, &mOutConversionBuffer);
+ sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
+ LOG_ALWAYS_FATAL_IF(audioFlinger == nullptr, "EM could not retrieved audioFlinger");
+ (void)audioFlinger->mEffectsFactoryHal->allocateBuffer(size, &mOutConversionBuffer);
}
if (mOutConversionBuffer.get() != nullptr) {
mOutConversionBuffer->setFrameCount(outFrameCount);
@@ -2020,10 +2024,10 @@
size_t numSamples = thread->frameCount();
sp<EffectBufferHalInterface> halBuffer;
#ifdef FLOAT_EFFECT_CHAIN
- status_t result = EffectBufferHalInterface::allocate(
+ status_t result = thread->mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
numSamples * sizeof(float), &halBuffer);
#else
- status_t result = EffectBufferHalInterface::allocate(
+ status_t result = thread->mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
numSamples * sizeof(int32_t), &halBuffer);
#endif
if (result != OK) return result;
diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp
index c1044ef..f08698e 100644
--- a/services/audioflinger/ServiceUtilities.cpp
+++ b/services/audioflinger/ServiceUtilities.cpp
@@ -153,4 +153,11 @@
return ok;
}
+bool modifyPhoneStateAllowed(pid_t pid, uid_t uid) {
+ static const String16 sModifyPhoneState("android.permission.MODIFY_PHONE_STATE");
+ bool ok = checkPermission(sModifyPhoneState, pid, uid);
+ if (!ok) ALOGE("Request requires android.permission.MODIFY_PHONE_STATE");
+ return ok;
+}
+
} // namespace android
diff --git a/services/audioflinger/ServiceUtilities.h b/services/audioflinger/ServiceUtilities.h
index 04cb9cd..83533dd 100644
--- a/services/audioflinger/ServiceUtilities.h
+++ b/services/audioflinger/ServiceUtilities.h
@@ -26,4 +26,5 @@
bool settingsAllowed();
bool modifyAudioRoutingAllowed();
bool dumpAllowed();
+bool modifyPhoneStateAllowed(pid_t pid, uid_t uid);
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8bf50b1..70ac32c 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -56,6 +56,8 @@
#include <powermanager/PowerManager.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+
#include "AudioFlinger.h"
#include "FastMixer.h"
#include "FastCapture.h"
@@ -2882,7 +2884,7 @@
{
audio_session_t session = chain->sessionId();
sp<EffectBufferHalInterface> halInBuffer, halOutBuffer;
- status_t result = EffectBufferHalInterface::mirror(
+ status_t result = mAudioFlinger->mEffectsFactoryHal->mirrorBuffer(
mEffectBufferEnabled ? mEffectBuffer : mSinkBuffer,
mEffectBufferEnabled ? mEffectBufferSize : mSinkBufferSize,
&halInBuffer);
@@ -2895,7 +2897,7 @@
// the sink buffer as input
if (mType != DIRECT) {
size_t numSamples = mNormalFrameCount * mChannelCount;
- status_t result = EffectBufferHalInterface::allocate(
+ status_t result = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
numSamples * sizeof(effect_buffer_t),
&halInBuffer);
if (result != OK) return result;
@@ -7819,6 +7821,7 @@
ret = AudioSystem::getOutputForAttr(&mAttr, &io,
mSessionId,
&stream,
+ client.clientPid,
client.clientUid,
&config,
flags,
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 2a8f54d..7f09e9b 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -116,7 +116,7 @@
audio_stream_type_t *stream,
uid_t uid,
const audio_config_t *config,
- audio_output_flags_t flags,
+ audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
audio_port_handle_t *portId) = 0;
// indicates to the audio policy manager that the output starts being used by corresponding stream.
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 044d6db..d5e8e1b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -333,6 +333,10 @@
return true;
}
}
+ if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
+ ALOGV("max gain when output device is telephony tx");
+ return true;
+ }
return false;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 78a02b2..e058dc8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -741,7 +741,7 @@
audio_stream_type_t *stream,
uid_t uid,
const audio_config_t *config,
- audio_output_flags_t flags,
+ audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
audio_port_handle_t *portId)
{
@@ -801,12 +801,12 @@
audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
- flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
+ *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
}
ALOGV("getOutputForAttr() device 0x%x, sampling rate %d, format %#x, channel mask %#x, "
"flags %#x",
- device, config->sample_rate, config->format, config->channel_mask, flags);
+ device, config->sample_rate, config->format, config->channel_mask, *flags);
*output = getOutputForDevice(device, session, *stream, config, flags);
if (*output == AUDIO_IO_HANDLE_NONE) {
@@ -828,7 +828,7 @@
audio_session_t session,
audio_stream_type_t stream,
const audio_config_t *config,
- audio_output_flags_t flags)
+ audio_output_flags_t *flags)
{
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
status_t status;
@@ -837,35 +837,41 @@
//force direct flag if offload flag is set: offloading implies a direct output stream
// and all common behaviors are driven by checking only the direct flag
// this should normally be set appropriately in the policy configuration file
- if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
- flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
+ if ((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
+ *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT);
}
- if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
- flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
+ if ((*flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
+ *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT);
}
// only allow deep buffering for music stream type
if (stream != AUDIO_STREAM_MUSIC) {
- flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
+ *flags = (audio_output_flags_t)(*flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
} else if (/* stream == AUDIO_STREAM_MUSIC && */
- flags == AUDIO_OUTPUT_FLAG_NONE &&
+ *flags == AUDIO_OUTPUT_FLAG_NONE &&
property_get_bool("audio.deep_buffer.media", false /* default_value */)) {
// use DEEP_BUFFER as default output for music stream type
- flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+ *flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
}
if (stream == AUDIO_STREAM_TTS) {
- flags = AUDIO_OUTPUT_FLAG_TTS;
+ *flags = AUDIO_OUTPUT_FLAG_TTS;
} else if (stream == AUDIO_STREAM_VOICE_CALL &&
audio_is_linear_pcm(config->format)) {
- flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_VOIP_RX |
+ *flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_VOIP_RX |
AUDIO_OUTPUT_FLAG_DIRECT);
ALOGV("Set VoIP and Direct output flags for PCM format");
+ } else if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX &&
+ stream == AUDIO_STREAM_MUSIC &&
+ audio_is_linear_pcm(config->format) &&
+ isInCall()) {
+ *flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
}
+
sp<IOProfile> profile;
// skip direct output selection if the request can obviously be attached to a mixed output
// and not explicitly requested
- if (((flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
+ if (((*flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX &&
audio_channel_count_from_out_mask(config->channel_mask) <= 2) {
goto non_direct_output;
@@ -878,13 +884,13 @@
// This may prevent offloading in rare situations where effects are left active by apps
// in the background.
- if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
+ if (((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
!(mEffects.isNonOffloadableEffectEnabled() || mMasterMono)) {
profile = getProfileForDirectOutput(device,
config->sample_rate,
config->format,
config->channel_mask,
- (audio_output_flags_t)flags);
+ (audio_output_flags_t)*flags);
}
if (profile != 0) {
@@ -916,7 +922,7 @@
String8 address = outputDevices.size() > 0 ? outputDevices.itemAt(0)->mAddress
: String8("");
- status = outputDesc->open(config, device, address, stream, flags, &output);
+ status = outputDesc->open(config, device, address, stream, *flags, &output);
// only accept an output with the requested parameters
if (status != NO_ERROR ||
@@ -954,7 +960,7 @@
// A request for HW A/V sync cannot fallback to a mixed output because time
// stamps are embedded in audio data
- if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
+ if ((*flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
return AUDIO_IO_HANDLE_NONE;
}
@@ -969,12 +975,12 @@
SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
// at this stage we should ignore the DIRECT flag as no direct output could be found earlier
- flags = (audio_output_flags_t)(flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
- output = selectOutput(outputs, flags, config->format);
+ *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
+ output = selectOutput(outputs, *flags, config->format);
}
ALOGW_IF((output == 0), "getOutputForDevice() could not find output for stream %d, "
"sampling rate %d, format %#x, channels %#x, flags %#x",
- stream, config->sample_rate, config->format, config->channel_mask, flags);
+ stream, config->sample_rate, config->format, config->channel_mask, *flags);
return output;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 4fd73e6..2b68882 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -110,7 +110,7 @@
audio_stream_type_t *stream,
uid_t uid,
const audio_config_t *config,
- audio_output_flags_t flags,
+ audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
audio_port_handle_t *portId);
virtual status_t startOutput(audio_io_handle_t output,
@@ -629,7 +629,7 @@
audio_session_t session,
audio_stream_type_t stream,
const audio_config_t *config,
- audio_output_flags_t flags);
+ audio_output_flags_t *flags);
// internal method to return the input handle for the given device and format
audio_io_handle_t getInputForDevice(audio_devices_t device,
String8 address,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 680d7b9..f1d7d86 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -158,6 +158,7 @@
audio_io_handle_t *output,
audio_session_t session,
audio_stream_type_t *stream,
+ pid_t pid,
uid_t uid,
const audio_config_t *config,
audio_output_flags_t flags,
@@ -176,9 +177,26 @@
"%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, uid);
uid = callingUid;
}
- return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
+ audio_output_flags_t originalFlags = flags;
+ status_t result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
config,
- flags, selectedDeviceId, portId);
+ &flags, selectedDeviceId, portId);
+
+ // FIXME: Introduce a way to check for the the telephony device before opening the output
+ if ((result == NO_ERROR) &&
+ (flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) &&
+ !modifyPhoneStateAllowed(pid, uid)) {
+ // If the app tries to play music through the telephony device and doesn't have permission
+ // the fallback to the default output device.
+ mAudioPolicyManager->releaseOutput(*output, *stream, session);
+ flags = originalFlags;
+ *selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ *portId = AUDIO_PORT_HANDLE_NONE;
+ result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
+ config,
+ &flags, selectedDeviceId, portId);
+ }
+ return result;
}
status_t AudioPolicyService::startOutput(audio_io_handle_t output,
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 9bc13c2..c21aa58 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -78,6 +78,7 @@
audio_io_handle_t *output,
audio_session_t session,
audio_stream_type_t *stream,
+ pid_t pid,
uid_t uid,
const audio_config_t *config,
audio_output_flags_t flags,
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 910dd78..e848a3f 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -508,7 +508,7 @@
void CameraClient::releaseRecordingFrameHandle(native_handle_t *handle) {
if (handle == nullptr) return;
-
+ Mutex::Autolock lock(mLock);
sp<IMemory> dataPtr;
{
Mutex::Autolock l(mAvailableCallbackBuffersLock);
@@ -532,17 +532,22 @@
return;
}
- VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer());
- metadata->eType = kMetadataBufferTypeNativeHandleSource;
- metadata->pHandle = handle;
-
- mHardware->releaseRecordingFrame(dataPtr);
+ if (mHardware != nullptr) {
+ VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer());
+ metadata->eType = kMetadataBufferTypeNativeHandleSource;
+ metadata->pHandle = handle;
+ mHardware->releaseRecordingFrame(dataPtr);
+ }
}
void CameraClient::releaseRecordingFrameHandleBatch(const std::vector<native_handle_t*>& handles) {
+ Mutex::Autolock lock(mLock);
+ bool disconnected = (mHardware == nullptr);
size_t n = handles.size();
std::vector<sp<IMemory>> frames;
- frames.reserve(n);
+ if (!disconnected) {
+ frames.reserve(n);
+ }
bool error = false;
for (auto& handle : handles) {
sp<IMemory> dataPtr;
@@ -566,10 +571,12 @@
break;
}
- VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer());
- metadata->eType = kMetadataBufferTypeNativeHandleSource;
- metadata->pHandle = handle;
- frames.push_back(dataPtr);
+ if (!disconnected) {
+ VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer());
+ metadata->eType = kMetadataBufferTypeNativeHandleSource;
+ metadata->pHandle = handle;
+ frames.push_back(dataPtr);
+ }
}
if (error) {
@@ -577,7 +584,7 @@
native_handle_close(handle);
native_handle_delete(handle);
}
- } else {
+ } else if (!disconnected) {
mHardware->releaseRecordingFrameBatch(frames);
}
return;
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index 0d2dba1..a71a732 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2012-2018 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.
@@ -154,7 +154,8 @@
callbackFormat, params.previewFormat);
res = device->createStream(mCallbackWindow,
params.previewWidth, params.previewHeight, callbackFormat,
- HAL_DATASPACE_V0_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId);
+ HAL_DATASPACE_V0_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId,
+ String8());
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
"%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index d1bbdaf..cc4249f 100755
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2012-2018 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.
@@ -168,7 +168,8 @@
res = device->createStream(mCaptureWindow,
params.pictureWidth, params.pictureHeight,
HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_V0_JFIF,
- CAMERA3_STREAM_ROTATION_0, &mCaptureStreamId);
+ CAMERA3_STREAM_ROTATION_0, &mCaptureStreamId,
+ String8());
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for capture: "
"%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index 73dca73..0786f53 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2012-2018 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.
@@ -194,7 +194,7 @@
res = device->createStream(mPreviewWindow,
params.previewWidth, params.previewHeight,
CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, HAL_DATASPACE_UNKNOWN,
- CAMERA3_STREAM_ROTATION_0, &mPreviewStreamId);
+ CAMERA3_STREAM_ROTATION_0, &mPreviewStreamId, String8());
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
@@ -379,7 +379,8 @@
res = device->createStream(mRecordingWindow,
params.videoWidth, params.videoHeight,
params.videoFormat, params.videoDataSpace,
- CAMERA3_STREAM_ROTATION_0, &mRecordingStreamId);
+ CAMERA3_STREAM_ROTATION_0, &mRecordingStreamId,
+ String8());
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for recording: "
"%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index b0607fb..372a2c5 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -311,7 +311,8 @@
res = device->createStream(outSurface, params.fastInfo.arrayWidth,
params.fastInfo.arrayHeight, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
- HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mZslStreamId);
+ HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mZslStreamId,
+ String8());
if (res != OK) {
ALOGE("%s: Camera %d: Can't create ZSL stream: "
"%s (%d)", __FUNCTION__, client->getCameraId(),
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 5cbc158..c36c7cf 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -175,7 +175,7 @@
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Empty request list");
}
- List<const CameraMetadata> metadataRequestList;
+ List<const CameraDeviceBase::PhysicalCameraSettingsList> metadataRequestList;
std::list<const SurfaceMap> surfaceMapList;
submitInfo->mRequestId = mRequestIdCounter;
uint32_t loopCounter = 0;
@@ -193,28 +193,72 @@
mCameraIdStr.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
"Repeating reprocess requests not supported");
+ } else if (request.mPhysicalCameraSettings.size() > 1) {
+ ALOGE("%s: Camera %s: reprocess requests not supported for "
+ "multiple physical cameras.", __FUNCTION__,
+ mCameraIdStr.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Reprocess requests not supported for multiple cameras");
}
}
- CameraMetadata metadata(request.mMetadata);
- if (metadata.isEmpty()) {
- ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
- __FUNCTION__, mCameraIdStr.string());
+ if (request.mPhysicalCameraSettings.empty()) {
+ ALOGE("%s: Camera %s: request doesn't contain any settings.", __FUNCTION__,
+ mCameraIdStr.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
- "Request settings are empty");
- } else if (request.mSurfaceList.isEmpty() && request.mStreamIdxList.size() == 0) {
+ "Request doesn't contain any settings");
+ }
+
+ //The first capture settings should always match the logical camera id
+ String8 logicalId(request.mPhysicalCameraSettings.begin()->id.c_str());
+ if (mDevice->getId() != logicalId) {
+ ALOGE("%s: Camera %s: Invalid camera request settings.", __FUNCTION__,
+ mCameraIdStr.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Invalid camera request settings");
+ }
+
+ CameraDeviceBase::PhysicalCameraSettingsList physicalSettingsList;
+ for (const auto& it : request.mPhysicalCameraSettings) {
+ String8 physicalId(it.id.c_str());
+ if ((physicalId != mDevice->getId()) && !checkPhysicalCameraId(physicalId)) {
+ ALOGE("%s: Camera %s: Physical camera id: %s is invalid.", __FUNCTION__,
+ mCameraIdStr.string(), physicalId.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Invalid physical camera id");
+ }
+
+ CameraMetadata metadata(it.settings);
+ if (metadata.isEmpty()) {
+ ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
+ __FUNCTION__, mCameraIdStr.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Request settings are empty");
+ }
+
+ if (!enforceRequestPermissions(metadata)) {
+ // Callee logs
+ return STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED,
+ "Caller does not have permission to change restricted controls");
+ }
+
+ physicalSettingsList.push_back({it.id, metadata});
+ }
+
+ if (streaming && (physicalSettingsList.size() > 1)) {
+ ALOGE("%s: Camera %s: Individual physical camera settings are not supported in "
+ "streaming requests. Rejecting request.", __FUNCTION__, mCameraIdStr.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Streaming request contains individual physical requests");
+ }
+
+ if (request.mSurfaceList.isEmpty() && request.mStreamIdxList.size() == 0) {
ALOGE("%s: Camera %s: Requests must have at least one surface target. "
"Rejecting request.", __FUNCTION__, mCameraIdStr.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
"Request has no output targets");
}
- if (!enforceRequestPermissions(metadata)) {
- // Callee logs
- return STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED,
- "Caller does not have permission to change restricted controls");
- }
-
/**
* Write in the output stream IDs and map from stream ID to surface ID
* which we calculate from the capture request's list of surface target
@@ -261,20 +305,22 @@
}
}
- metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreamIds[0],
- outputStreamIds.size());
+ physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS,
+ &outputStreamIds[0], outputStreamIds.size());
if (request.mIsReprocess) {
- metadata.update(ANDROID_REQUEST_INPUT_STREAMS, &mInputStream.id, 1);
+ physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_INPUT_STREAMS,
+ &mInputStream.id, 1);
}
- metadata.update(ANDROID_REQUEST_ID, &(submitInfo->mRequestId), /*size*/1);
+ physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_ID,
+ &(submitInfo->mRequestId), /*size*/1);
loopCounter++; // loopCounter starts from 1
ALOGV("%s: Camera %s: Creating request with ID %d (%d of %zu)",
__FUNCTION__, mCameraIdStr.string(), submitInfo->mRequestId,
loopCounter, requests.size());
- metadataRequestList.push_back(metadata);
+ metadataRequestList.push_back(physicalSettingsList);
surfaceMapList.push_back(surfaceMap);
}
mRequestIdCounter++;
@@ -508,6 +554,7 @@
size_t numBufferProducers = bufferProducers.size();
bool deferredConsumer = outputConfiguration.isDeferred();
bool isShared = outputConfiguration.isShared();
+ String8 physicalCameraId = String8(outputConfiguration.getPhysicalCameraId());
if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
@@ -529,6 +576,12 @@
return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
}
+ if (!checkPhysicalCameraId(physicalCameraId)) {
+ String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
+ mCameraIdStr.string(), physicalCameraId.string());
+ ALOGE("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ }
std::vector<sp<Surface>> surfaces;
std::vector<sp<IBinder>> binders;
status_t err;
@@ -578,7 +631,8 @@
err = mDevice->createStream(surfaces, deferredConsumer, streamInfo.width,
streamInfo.height, streamInfo.format, streamInfo.dataSpace,
static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
- &streamId, &surfaceIds, outputConfiguration.getSurfaceSetID(), isShared);
+ &streamId, physicalCameraId, &surfaceIds, outputConfiguration.getSurfaceSetID(),
+ isShared);
if (err != OK) {
res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
@@ -640,10 +694,12 @@
int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
std::vector<sp<Surface>> noSurface;
std::vector<int> surfaceIds;
+ String8 physicalCameraId(outputConfiguration.getPhysicalCameraId());
err = mDevice->createStream(noSurface, /*hasDeferredConsumer*/true, width,
height, format, dataSpace,
static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
- &streamId, &surfaceIds, outputConfiguration.getSurfaceSetID(), isShared,
+ &streamId, physicalCameraId, &surfaceIds,
+ outputConfiguration.getSurfaceSetID(), isShared,
consumerUsage);
if (err != OK) {
@@ -1059,6 +1115,43 @@
return binder::Status::ok();
}
+bool CameraDeviceClient::checkPhysicalCameraId(const String8& physicalCameraId) {
+ if (0 == physicalCameraId.size()) {
+ return true;
+ }
+
+ CameraMetadata staticInfo = mDevice->info();
+ camera_metadata_entry_t entryCap;
+ bool isLogicalCam = false;
+
+ entryCap = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+ for (size_t i = 0; i < entryCap.count; ++i) {
+ uint8_t capability = entryCap.data.u8[i];
+ if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
+ isLogicalCam = true;
+ }
+ }
+ if (!isLogicalCam) {
+ return false;
+ }
+
+ camera_metadata_entry_t entryIds = staticInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
+ const uint8_t* ids = entryIds.data.u8;
+ size_t start = 0;
+ for (size_t i = 0; i < entryIds.count; ++i) {
+ if (ids[i] == '\0') {
+ if (start != i) {
+ String8 currentId((const char*)ids+start);
+ if (currentId == physicalCameraId) {
+ return true;
+ }
+ }
+ start = i+1;
+ }
+ }
+ return false;
+}
+
bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
/*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 4086c72..14aeed0 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -262,6 +262,10 @@
/*out*/SurfaceMap* surfaceMap,
/*out*/Vector<int32_t>* streamIds);
+ // Check that the physicalCameraId passed in is spported by the camera
+ // device.
+ bool checkPhysicalCameraId(const String8& physicalCameraId);
+
// IGraphicsBufferProducer binder -> Stream ID + Surface ID for output streams
KeyedVector<sp<IBinder>, StreamSurfaceId> mStreamMap;
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 3fd6921..7956be5 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -65,6 +65,12 @@
*/
virtual const CameraMetadata& info() const = 0;
+ struct PhysicalCameraSettings {
+ std::string cameraId;
+ CameraMetadata metadata;
+ };
+ typedef List<PhysicalCameraSettings> PhysicalCameraSettingsList;
+
/**
* Submit request for capture. The CameraDevice takes ownership of the
* passed-in buffer.
@@ -76,7 +82,7 @@
* Submit a list of requests.
* Output lastFrameNumber is the expected last frame number of the list of requests.
*/
- virtual status_t captureList(const List<const CameraMetadata> &requests,
+ virtual status_t captureList(const List<const PhysicalCameraSettingsList> &requests,
const std::list<const SurfaceMap> &surfaceMaps,
int64_t *lastFrameNumber = NULL) = 0;
@@ -92,7 +98,7 @@
* Submit a list of requests for streaming.
* Output lastFrameNumber is the last frame number of the previous streaming request.
*/
- virtual status_t setStreamingRequestList(const List<const CameraMetadata> &requests,
+ virtual status_t setStreamingRequestList(const List<const PhysicalCameraSettingsList> &requests,
const std::list<const SurfaceMap> &surfaceMaps,
int64_t *lastFrameNumber = NULL) = 0;
@@ -119,6 +125,7 @@
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,
+ const String8& physicalCameraId,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, uint64_t consumerUsage = 0) = 0;
@@ -133,6 +140,7 @@
virtual status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ const String8& physicalCameraId,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, uint64_t consumerUsage = 0) = 0;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 2ff200d..f2da232 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -35,6 +35,7 @@
// Hardcoded name for the passthrough HAL implementation, since it can't be discovered via the
// service manager
const std::string kLegacyProviderName("legacy/0");
+const std::string kExternalProviderName("external/0");
// Slash-separated list of provider types to consider for use via the old camera API
const std::string kStandardProviderTypes("internal/legacy");
@@ -69,6 +70,7 @@
// See if there's a passthrough HAL, but let's not complain if there's not
addProviderLocked(kLegacyProviderName, /*expected*/ false);
+ addProviderLocked(kExternalProviderName, /*expected*/ false);
return OK;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index d99fc1d..7e71c3b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -194,8 +194,14 @@
mTagMonitor.initialize(mVendorTagId);
+ Vector<int32_t> sessionParamKeys;
+ camera_metadata_entry_t sessionKeysEntry = mDeviceInfo.find(
+ ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
+ if (sessionKeysEntry.count > 0) {
+ sessionParamKeys.insertArrayAt(sessionKeysEntry.data.i32, 0, sessionKeysEntry.count);
+ }
/** Start up request queue thread */
- mRequestThread = new RequestThread(this, mStatusTracker, mInterface);
+ mRequestThread = new RequestThread(this, mStatusTracker, mInterface, sessionParamKeys);
res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
if (res != OK) {
SET_ERR_L("Unable to start request queue thread: %s (%d)",
@@ -735,7 +741,7 @@
}
status_t Camera3Device::convertMetadataListToRequestListLocked(
- const List<const CameraMetadata> &metadataList,
+ const List<const PhysicalCameraSettingsList> &metadataList,
const std::list<const SurfaceMap> &surfaceMaps,
bool repeating,
RequestList *requestList) {
@@ -745,7 +751,7 @@
}
int32_t burstId = 0;
- List<const CameraMetadata>::const_iterator metadataIt = metadataList.begin();
+ List<const PhysicalCameraSettingsList>::const_iterator metadataIt = metadataList.begin();
std::list<const SurfaceMap>::const_iterator surfaceMapIt = surfaceMaps.begin();
for (; metadataIt != metadataList.end() && surfaceMapIt != surfaceMaps.end();
++metadataIt, ++surfaceMapIt) {
@@ -759,12 +765,13 @@
// Setup burst Id and request Id
newRequest->mResultExtras.burstId = burstId++;
- if (metadataIt->exists(ANDROID_REQUEST_ID)) {
- if (metadataIt->find(ANDROID_REQUEST_ID).count == 0) {
+ if (metadataIt->begin()->metadata.exists(ANDROID_REQUEST_ID)) {
+ if (metadataIt->begin()->metadata.find(ANDROID_REQUEST_ID).count == 0) {
CLOGE("RequestID entry exists; but must not be empty in metadata");
return BAD_VALUE;
}
- newRequest->mResultExtras.requestId = metadataIt->find(ANDROID_REQUEST_ID).data.i32[0];
+ newRequest->mResultExtras.requestId = metadataIt->begin()->metadata.find(
+ ANDROID_REQUEST_ID).data.i32[0];
} else {
CLOGE("RequestID does not exist in metadata");
return BAD_VALUE;
@@ -796,17 +803,19 @@
status_t Camera3Device::capture(CameraMetadata &request, int64_t* /*lastFrameNumber*/) {
ATRACE_CALL();
- List<const CameraMetadata> requests;
+ List<const PhysicalCameraSettingsList> requestsList;
std::list<const SurfaceMap> surfaceMaps;
- convertToRequestList(requests, surfaceMaps, request);
+ convertToRequestList(requestsList, surfaceMaps, request);
- return captureList(requests, surfaceMaps, /*lastFrameNumber*/NULL);
+ return captureList(requestsList, surfaceMaps, /*lastFrameNumber*/NULL);
}
-void Camera3Device::convertToRequestList(List<const CameraMetadata>& requests,
+void Camera3Device::convertToRequestList(List<const PhysicalCameraSettingsList>& requestsList,
std::list<const SurfaceMap>& surfaceMaps,
const CameraMetadata& request) {
- requests.push_back(request);
+ PhysicalCameraSettingsList requestList;
+ requestList.push_back({std::string(getId().string()), request});
+ requestsList.push_back(requestList);
SurfaceMap surfaceMap;
camera_metadata_ro_entry streams = request.find(ANDROID_REQUEST_OUTPUT_STREAMS);
@@ -819,7 +828,7 @@
}
status_t Camera3Device::submitRequestsHelper(
- const List<const CameraMetadata> &requests,
+ const List<const PhysicalCameraSettingsList> &requests,
const std::list<const SurfaceMap> &surfaceMaps,
bool repeating,
/*out*/
@@ -1069,42 +1078,43 @@
notify(&m);
}
-status_t Camera3Device::captureList(const List<const CameraMetadata> &requests,
+status_t Camera3Device::captureList(const List<const PhysicalCameraSettingsList> &requestsList,
const std::list<const SurfaceMap> &surfaceMaps,
int64_t *lastFrameNumber) {
ATRACE_CALL();
- return submitRequestsHelper(requests, surfaceMaps, /*repeating*/false, lastFrameNumber);
+ return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/false, lastFrameNumber);
}
status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,
int64_t* /*lastFrameNumber*/) {
ATRACE_CALL();
- List<const CameraMetadata> requests;
+ List<const PhysicalCameraSettingsList> requestsList;
std::list<const SurfaceMap> surfaceMaps;
- convertToRequestList(requests, surfaceMaps, request);
+ convertToRequestList(requestsList, surfaceMaps, request);
- return setStreamingRequestList(requests, /*surfaceMap*/surfaceMaps,
+ return setStreamingRequestList(requestsList, /*surfaceMap*/surfaceMaps,
/*lastFrameNumber*/NULL);
}
-status_t Camera3Device::setStreamingRequestList(const List<const CameraMetadata> &requests,
- const std::list<const SurfaceMap> &surfaceMaps,
- int64_t *lastFrameNumber) {
+status_t Camera3Device::setStreamingRequestList(
+ const List<const PhysicalCameraSettingsList> &requestsList,
+ const std::list<const SurfaceMap> &surfaceMaps, int64_t *lastFrameNumber) {
ATRACE_CALL();
- return submitRequestsHelper(requests, surfaceMaps, /*repeating*/true, lastFrameNumber);
+ return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/true, lastFrameNumber);
}
sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
- const CameraMetadata &request, const SurfaceMap &surfaceMap) {
+ const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
status_t res;
if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {
// This point should only be reached via API1 (API2 must explicitly call configureStreams)
// so unilaterally select normal operating mode.
- res = configureStreamsLocked(CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE, mSessionParams);
+ res = filterParamsAndConfigureLocked(request.begin()->metadata,
+ CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
// Stream configuration failed. Client might try other configuraitons.
if (res != OK) {
CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
@@ -1224,6 +1234,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,
+ const String8& physicalCameraId,
std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
ATRACE_CALL();
@@ -1236,12 +1247,14 @@
consumers.push_back(consumer);
return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
- format, dataSpace, rotation, id, surfaceIds, streamSetId, isShared, consumerUsage);
+ format, dataSpace, rotation, id, physicalCameraId, surfaceIds, streamSetId,
+ isShared, consumerUsage);
}
status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ const String8& physicalCameraId,
std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
ATRACE_CALL();
@@ -1249,8 +1262,9 @@
nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Mutex::Autolock l(mLock);
ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
- " consumer usage %" PRIu64 ", isShared %d", mId.string(), mNextStreamId, width, height, format,
- dataSpace, rotation, consumerUsage, isShared);
+ " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s", mId.string(),
+ mNextStreamId, width, height, format, dataSpace, rotation, consumerUsage, isShared,
+ physicalCameraId.string());
status_t res;
bool wasActive = false;
@@ -1310,7 +1324,7 @@
}
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, blobBufferSize, format, dataSpace, rotation,
- mTimestampOffset, streamSetId);
+ mTimestampOffset, physicalCameraId, streamSetId);
} else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height);
if (rawOpaqueBufferSize <= 0) {
@@ -1319,19 +1333,19 @@
}
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
- mTimestampOffset, streamSetId);
+ mTimestampOffset, physicalCameraId, streamSetId);
} else if (isShared) {
newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
width, height, format, consumerUsage, dataSpace, rotation,
- mTimestampOffset, streamSetId);
+ mTimestampOffset, physicalCameraId, streamSetId);
} else if (consumers.size() == 0 && hasDeferredConsumer) {
newStream = new Camera3OutputStream(mNextStreamId,
width, height, format, consumerUsage, dataSpace, rotation,
- mTimestampOffset, streamSetId);
+ mTimestampOffset, physicalCameraId, streamSetId);
} else {
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, format, dataSpace, rotation,
- mTimestampOffset, streamSetId);
+ mTimestampOffset, physicalCameraId, streamSetId);
}
size_t consumerCount = consumers.size();
@@ -1508,11 +1522,20 @@
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
+ return filterParamsAndConfigureLocked(sessionParams, operatingMode);
+}
+
+status_t Camera3Device::filterParamsAndConfigureLocked(const CameraMetadata& sessionParams,
+ int operatingMode) {
//Filter out any incoming session parameters
const CameraMetadata params(sessionParams);
- CameraMetadata filteredParams;
camera_metadata_entry_t availableSessionKeys = mDeviceInfo.find(
ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
+ CameraMetadata filteredParams(availableSessionKeys.count);
+ camera_metadata_t *meta = const_cast<camera_metadata_t *>(
+ filteredParams.getAndLock());
+ set_camera_metadata_vendor_id(meta, mVendorTagId);
+ filteredParams.unlock(meta);
if (availableSessionKeys.count > 0) {
for (size_t i = 0; i < availableSessionKeys.count; i++) {
camera_metadata_ro_entry entry = params.find(
@@ -2075,15 +2098,15 @@
*/
sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
- const CameraMetadata &request, const SurfaceMap &surfaceMap) {
+ const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
ATRACE_CALL();
status_t res;
sp<CaptureRequest> newRequest = new CaptureRequest;
- newRequest->mSettings = request;
+ newRequest->mSettingsList = request;
camera_metadata_entry_t inputStreams =
- newRequest->mSettings.find(ANDROID_REQUEST_INPUT_STREAMS);
+ newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_INPUT_STREAMS);
if (inputStreams.count > 0) {
if (mInputStream == NULL ||
mInputStream->getId() != inputStreams.data.i32[0]) {
@@ -2109,11 +2132,11 @@
}
newRequest->mInputStream = mInputStream;
- newRequest->mSettings.erase(ANDROID_REQUEST_INPUT_STREAMS);
+ newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_INPUT_STREAMS);
}
camera_metadata_entry_t streams =
- newRequest->mSettings.find(ANDROID_REQUEST_OUTPUT_STREAMS);
+ newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_OUTPUT_STREAMS);
if (streams.count == 0) {
CLOGE("Zero output streams specified!");
return NULL;
@@ -2161,7 +2184,7 @@
newRequest->mOutputStreams.push(stream);
}
- newRequest->mSettings.erase(ANDROID_REQUEST_OUTPUT_STREAMS);
+ newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_OUTPUT_STREAMS);
newRequest->mBatchSize = 1;
return newRequest;
@@ -2203,10 +2226,47 @@
// properly clean things up
internalUpdateStatusLocked(STATUS_UNCONFIGURED);
mNeedConfig = true;
+
+ res = mPreparerThread->resume();
+ if (res != OK) {
+ ALOGE("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
+ }
+}
+
+bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams) {
+ ATRACE_CALL();
+ bool ret = false;
+
+ Mutex::Autolock il(mInterfaceLock);
+ nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
+
+ Mutex::Autolock l(mLock);
+ auto rc = internalPauseAndWaitLocked(maxExpectedDuration);
+ if (rc == NO_ERROR) {
+ mNeedConfig = true;
+ rc = configureStreamsLocked(mOperatingMode, sessionParams, /*notifyRequestThread*/ false);
+ if (rc == NO_ERROR) {
+ ret = true;
+ mPauseStateNotify = false;
+ //Moving to active state while holding 'mLock' is important.
+ //There could be pending calls to 'create-/deleteStream' which
+ //will trigger another stream configuration while the already
+ //present streams end up with outstanding buffers that will
+ //not get drained.
+ internalUpdateStatusLocked(STATUS_ACTIVE);
+ } else {
+ setErrorStateLocked("%s: Failed to re-configure camera: %d",
+ __FUNCTION__, rc);
+ }
+ } else {
+ ALOGE("%s: Failed to pause streaming: %d", __FUNCTION__, rc);
+ }
+
+ return ret;
}
status_t Camera3Device::configureStreamsLocked(int operatingMode,
- const CameraMetadata& sessionParams) {
+ const CameraMetadata& sessionParams, bool notifyRequestThread) {
ATRACE_CALL();
status_t res;
@@ -2247,6 +2307,8 @@
// Start configuring the streams
ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.string());
+ mPreparerThread->pause();
+
camera3_stream_configuration config;
config.operation_mode = mOperatingMode;
config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
@@ -2338,7 +2400,9 @@
// Request thread needs to know to avoid using repeat-last-settings protocol
// across configure_streams() calls
- mRequestThread->configurationComplete(mIsConstrainedHighSpeedConfiguration);
+ if (notifyRequestThread) {
+ mRequestThread->configurationComplete(mIsConstrainedHighSpeedConfiguration, sessionParams);
+ }
char value[PROPERTY_VALUE_MAX];
property_get("camera.fifo.disable", value, "0");
@@ -2376,6 +2440,12 @@
// tear down the deleted streams after configure streams.
mDeletedStreams.clear();
+ auto rc = mPreparerThread->resume();
+ if (rc != OK) {
+ SET_ERR_L("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
+ return rc;
+ }
+
return OK;
}
@@ -3260,10 +3330,13 @@
// Convert stream config to HIDL
std::set<int> activeStreams;
- device::V3_4::StreamConfiguration requestedConfiguration;
- requestedConfiguration.v3_2.streams.resize(config->num_streams);
+ device::V3_2::StreamConfiguration requestedConfiguration3_2;
+ device::V3_4::StreamConfiguration requestedConfiguration3_4;
+ requestedConfiguration3_2.streams.resize(config->num_streams);
+ requestedConfiguration3_4.streams.resize(config->num_streams);
for (size_t i = 0; i < config->num_streams; i++) {
- Stream &dst = requestedConfiguration.v3_2.streams[i];
+ device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
+ device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
camera3_stream_t *src = config->streams[i];
Camera3Stream* cam3stream = Camera3Stream::cast(src);
@@ -3282,14 +3355,18 @@
__FUNCTION__, streamId, config->streams[i]->stream_type);
return BAD_VALUE;
}
- dst.id = streamId;
- dst.streamType = streamType;
- dst.width = src->width;
- dst.height = src->height;
- dst.format = mapToPixelFormat(src->format);
- dst.usage = mapToConsumerUsage(cam3stream->getUsage());
- dst.dataSpace = mapToHidlDataspace(src->data_space);
- dst.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
+ dst3_2.id = streamId;
+ dst3_2.streamType = streamType;
+ dst3_2.width = src->width;
+ dst3_2.height = src->height;
+ dst3_2.format = mapToPixelFormat(src->format);
+ dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
+ dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
+ dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
+ dst3_4.v3_2 = dst3_2;
+ if (src->physical_camera_id != nullptr) {
+ dst3_4.physicalCameraId = src->physical_camera_id;
+ }
activeStreams.insert(streamId);
// Create Buffer ID map if necessary
@@ -3308,19 +3385,20 @@
}
}
+ StreamConfigurationMode operationMode;
res = mapToStreamConfigurationMode(
(camera3_stream_configuration_mode_t) config->operation_mode,
- /*out*/ &requestedConfiguration.v3_2.operationMode);
+ /*out*/ &operationMode);
if (res != OK) {
return res;
}
-
- requestedConfiguration.sessionParams.setToExternal(
+ requestedConfiguration3_2.operationMode = operationMode;
+ requestedConfiguration3_4.operationMode = operationMode;
+ requestedConfiguration3_4.sessionParams.setToExternal(
reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
get_camera_metadata_size(sessionParams));
// Invoke configureStreams
-
device::V3_3::HalStreamConfiguration finalConfiguration;
common::V1_0::Status status;
@@ -3338,22 +3416,28 @@
}
if (hidlSession_3_4 != nullptr) {
- // We do; use v3.4 for the call
+ // We do; use v3.4 for the call, and construct a v3.4
+ // HalStreamConfiguration
ALOGV("%s: v3.4 device found", __FUNCTION__);
- auto err = hidlSession_3_4->configureStreams_3_4(requestedConfiguration,
- [&status, &finalConfiguration]
- (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
- finalConfiguration = halConfiguration;
+ device::V3_4::HalStreamConfiguration finalConfiguration3_4;
+ auto err = hidlSession_3_4->configureStreams_3_4(requestedConfiguration3_4,
+ [&status, &finalConfiguration3_4]
+ (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
+ finalConfiguration3_4 = halConfiguration;
status = s;
});
if (!err.isOk()) {
ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
return DEAD_OBJECT;
}
+ finalConfiguration.streams.resize(finalConfiguration3_4.streams.size());
+ for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) {
+ finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3;
+ }
} else if (hidlSession_3_3 != nullptr) {
// We do; use v3.3 for the call
ALOGV("%s: v3.3 device found", __FUNCTION__);
- auto err = hidlSession_3_3->configureStreams_3_3(requestedConfiguration.v3_2,
+ auto err = hidlSession_3_3->configureStreams_3_3(requestedConfiguration3_2,
[&status, &finalConfiguration]
(common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
finalConfiguration = halConfiguration;
@@ -3367,7 +3451,7 @@
// We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
ALOGV("%s: v3.2 device found", __FUNCTION__);
HalStreamConfiguration finalConfiguration_3_2;
- auto err = mHidlSession->configureStreams(requestedConfiguration.v3_2,
+ auto err = mHidlSession->configureStreams(requestedConfiguration3_2,
[&status, &finalConfiguration_3_2]
(common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
finalConfiguration_3_2 = halConfiguration;
@@ -3381,7 +3465,7 @@
for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
finalConfiguration.streams[i].overrideDataSpace =
- requestedConfiguration.v3_2.streams[i].dataSpace;
+ requestedConfiguration3_2.streams[i].dataSpace;
}
}
@@ -3535,13 +3619,29 @@
ATRACE_NAME("CameraHal::processBatchCaptureRequests");
if (!valid()) return INVALID_OPERATION;
+ sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
+ auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_4.isOk()) {
+ hidlSession_3_4 = castResult_3_4;
+ }
+
hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
+ hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
size_t batchSize = requests.size();
- captureRequests.resize(batchSize);
+ if (hidlSession_3_4 != nullptr) {
+ captureRequests_3_4.resize(batchSize);
+ } else {
+ captureRequests.resize(batchSize);
+ }
std::vector<native_handle_t*> handlesCreated;
for (size_t i = 0; i < batchSize; i++) {
- wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i], /*out*/&handlesCreated);
+ if (hidlSession_3_4 != nullptr) {
+ wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
+ /*out*/&handlesCreated);
+ } else {
+ wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i], /*out*/&handlesCreated);
+ }
}
std::vector<device::V3_2::BufferCache> cachesToRemove;
@@ -3562,7 +3662,12 @@
// Write metadata to FMQ.
for (size_t i = 0; i < batchSize; i++) {
camera3_capture_request_t* request = requests[i];
- device::V3_2::CaptureRequest* captureRequest = &captureRequests[i];
+ device::V3_2::CaptureRequest* captureRequest;
+ if (hidlSession_3_4 != nullptr) {
+ captureRequest = &captureRequests_3_4[i].v3_2;
+ } else {
+ captureRequest = &captureRequests[i];
+ }
if (request->settings != nullptr) {
size_t settingsSize = get_camera_metadata_size(request->settings);
@@ -3584,12 +3689,46 @@
captureRequest->settings.resize(0);
captureRequest->fmqSettingsSize = 0u;
}
+
+ if (hidlSession_3_4 != nullptr) {
+ captureRequests_3_4[i].physicalCameraSettings.resize(request->num_physcam_settings);
+ for (size_t j = 0; j < request->num_physcam_settings; j++) {
+ size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
+ if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
+ reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
+ settingsSize)) {
+ captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
+ captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = settingsSize;
+ } else {
+ if (mRequestMetadataQueue != nullptr) {
+ ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
+ }
+ captureRequests_3_4[i].physicalCameraSettings[j].settings.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
+ request->physcam_settings[j])),
+ get_camera_metadata_size(request->physcam_settings[j]));
+ captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
+ }
+ captureRequests_3_4[i].physicalCameraSettings[j].physicalCameraId =
+ request->physcam_id[j];
+ }
+ }
}
- auto err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
+
+ hardware::details::return_status err;
+ if (hidlSession_3_4 != nullptr) {
+ err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
[&status, &numRequestProcessed] (auto s, uint32_t n) {
status = s;
*numRequestProcessed = n;
});
+ } else {
+ err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
+ [&status, &numRequestProcessed] (auto s, uint32_t n) {
+ status = s;
+ *numRequestProcessed = n;
+ });
+ }
if (!err.isOk()) {
ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
return DEAD_OBJECT;
@@ -3747,7 +3886,7 @@
Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
sp<StatusTracker> statusTracker,
- sp<HalInterface> interface) :
+ sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys) :
Thread(/*canCallJava*/false),
mParent(parent),
mStatusTracker(statusTracker),
@@ -3764,7 +3903,9 @@
mRepeatingLastFrameNumber(
hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
mPrepareVideoStream(false),
- mRequestLatency(kRequestLatencyBinSize) {
+ mRequestLatency(kRequestLatencyBinSize),
+ mSessionParamKeys(sessionParamKeys),
+ mLatestSessionParams(sessionParamKeys.size()) {
mStatusId = statusTracker->addComponent();
}
@@ -3777,10 +3918,12 @@
mListener = listener;
}
-void Camera3Device::RequestThread::configurationComplete(bool isConstrainedHighSpeed) {
+void Camera3Device::RequestThread::configurationComplete(bool isConstrainedHighSpeed,
+ const CameraMetadata& sessionParams) {
ATRACE_CALL();
Mutex::Autolock l(mRequestLock);
mReconfigured = true;
+ mLatestSessionParams = sessionParams;
// Prepare video stream for high speed recording.
mPrepareVideoStream = isConstrainedHighSpeed;
}
@@ -4068,9 +4211,12 @@
}
if (nextRequest.halRequest.settings != NULL) {
- nextRequest.captureRequest->mSettings.unlock(nextRequest.halRequest.settings);
+ nextRequest.captureRequest->mSettingsList.begin()->metadata.unlock(
+ nextRequest.halRequest.settings);
}
+ cleanupPhysicalSettings(nextRequest.captureRequest, &nextRequest.halRequest);
+
if (!triggerRemoveFailed) {
// Remove any previously queued triggers (after unlock)
status_t removeTriggerRes = removeTriggers(mPrevRequest);
@@ -4139,9 +4285,12 @@
}
if (nextRequest.halRequest.settings != NULL) {
- nextRequest.captureRequest->mSettings.unlock(nextRequest.halRequest.settings);
+ nextRequest.captureRequest->mSettingsList.begin()->metadata.unlock(
+ nextRequest.halRequest.settings);
}
+ cleanupPhysicalSettings(nextRequest.captureRequest, &nextRequest.halRequest);
+
// Remove any previously queued triggers (after unlock)
res = removeTriggers(mPrevRequest);
if (res != OK) {
@@ -4191,6 +4340,52 @@
return maxExpectedDuration;
}
+bool Camera3Device::RequestThread::updateSessionParameters(const CameraMetadata& settings) {
+ ATRACE_CALL();
+ bool updatesDetected = false;
+
+ for (auto tag : mSessionParamKeys) {
+ camera_metadata_ro_entry entry = settings.find(tag);
+ camera_metadata_entry lastEntry = mLatestSessionParams.find(tag);
+
+ if (entry.count > 0) {
+ bool isDifferent = false;
+ if (lastEntry.count > 0) {
+ // Have a last value, compare to see if changed
+ if (lastEntry.type == entry.type &&
+ lastEntry.count == entry.count) {
+ // Same type and count, compare values
+ size_t bytesPerValue = camera_metadata_type_size[lastEntry.type];
+ size_t entryBytes = bytesPerValue * lastEntry.count;
+ int cmp = memcmp(entry.data.u8, lastEntry.data.u8, entryBytes);
+ if (cmp != 0) {
+ isDifferent = true;
+ }
+ } else {
+ // Count or type has changed
+ isDifferent = true;
+ }
+ } else {
+ // No last entry, so always consider to be different
+ isDifferent = true;
+ }
+
+ if (isDifferent) {
+ ALOGV("%s: Session parameter tag id %d changed", __FUNCTION__, tag);
+ mLatestSessionParams.update(entry);
+ updatesDetected = true;
+ }
+ } else if (lastEntry.count > 0) {
+ // Value has been removed
+ ALOGV("%s: Session parameter tag id %d removed", __FUNCTION__, tag);
+ mLatestSessionParams.erase(tag);
+ updatesDetected = true;
+ }
+ }
+
+ return updatesDetected;
+}
+
bool Camera3Device::RequestThread::threadLoop() {
ATRACE_CALL();
status_t res;
@@ -4209,7 +4404,7 @@
// Get the latest request ID, if any
int latestRequestId;
camera_metadata_entry_t requestIdEntry = mNextRequests[mNextRequests.size() - 1].
- captureRequest->mSettings.find(ANDROID_REQUEST_ID);
+ captureRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_ID);
if (requestIdEntry.count > 0) {
latestRequestId = requestIdEntry.data.i32[0];
} else {
@@ -4217,6 +4412,49 @@
latestRequestId = NAME_NOT_FOUND;
}
+ // 'mNextRequests' will at this point contain either a set of HFR batched requests
+ // or a single request from streaming or burst. In either case the first element
+ // should contain the latest camera settings that we need to check for any session
+ // parameter updates.
+ if (updateSessionParameters(mNextRequests[0].captureRequest->mSettingsList.begin()->metadata)) {
+ res = OK;
+
+ //Input stream buffers are already acquired at this point so an input stream
+ //will not be able to move to idle state unless we force it.
+ if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
+ res = mNextRequests[0].captureRequest->mInputStream->forceToIdle();
+ if (res != OK) {
+ ALOGE("%s: Failed to force idle input stream: %d", __FUNCTION__, res);
+ cleanUpFailedRequests(/*sendRequestError*/ false);
+ return false;
+ }
+ }
+
+ if (res == OK) {
+ sp<StatusTracker> statusTracker = mStatusTracker.promote();
+ if (statusTracker != 0) {
+ statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
+
+ sp<Camera3Device> parent = mParent.promote();
+ if (parent != nullptr) {
+ mReconfigured |= parent->reconfigureCamera(mLatestSessionParams);
+ }
+
+ statusTracker->markComponentActive(mStatusId);
+ setPaused(false);
+ }
+
+ if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
+ mNextRequests[0].captureRequest->mInputStream->restoreConfiguredState();
+ if (res != OK) {
+ ALOGE("%s: Failed to restore configured input stream: %d", __FUNCTION__, res);
+ cleanUpFailedRequests(/*sendRequestError*/ false);
+ return false;
+ }
+ }
+ }
+ }
+
// Prepare a batch of HAL requests and output buffers.
res = prepareHalRequests();
if (res == TIMED_OUT) {
@@ -4320,8 +4558,8 @@
* The request should be presorted so accesses in HAL
* are O(logn). Sidenote, sorting a sorted metadata is nop.
*/
- captureRequest->mSettings.sort();
- halRequest->settings = captureRequest->mSettings.getAndLock();
+ captureRequest->mSettingsList.begin()->metadata.sort();
+ halRequest->settings = captureRequest->mSettingsList.begin()->metadata.getAndLock();
mPrevRequest = captureRequest;
ALOGVV("%s: Request settings are NEW", __FUNCTION__);
@@ -4345,6 +4583,20 @@
__FUNCTION__);
}
+ if (captureRequest->mSettingsList.size() > 1) {
+ halRequest->num_physcam_settings = captureRequest->mSettingsList.size() - 1;
+ halRequest->physcam_id = new const char* [halRequest->num_physcam_settings];
+ halRequest->physcam_settings =
+ new const camera_metadata* [halRequest->num_physcam_settings];
+ auto it = ++captureRequest->mSettingsList.begin();
+ size_t i = 0;
+ for (; it != captureRequest->mSettingsList.end(); it++, i++) {
+ halRequest->physcam_id[i] = it->cameraId.c_str();
+ it->metadata.sort();
+ halRequest->physcam_settings[i] = it->metadata.getAndLock();
+ }
+ }
+
uint32_t totalNumBuffers = 0;
// Fill in buffers
@@ -4515,6 +4767,30 @@
mExpectedInflightDuration : kMinInflightDuration;
}
+void Camera3Device::RequestThread::cleanupPhysicalSettings(sp<CaptureRequest> request,
+ camera3_capture_request_t *halRequest) {
+ if ((request == nullptr) || (halRequest == nullptr)) {
+ ALOGE("%s: Invalid request!", __FUNCTION__);
+ return;
+ }
+
+ if (halRequest->num_physcam_settings > 0) {
+ if (halRequest->physcam_id != nullptr) {
+ delete [] halRequest->physcam_id;
+ halRequest->physcam_id = nullptr;
+ }
+ if (halRequest->physcam_settings != nullptr) {
+ auto it = ++(request->mSettingsList.begin());
+ size_t i = 0;
+ for (; it != request->mSettingsList.end(); it++, i++) {
+ it->metadata.unlock(halRequest->physcam_settings[i]);
+ }
+ delete [] halRequest->physcam_settings;
+ halRequest->physcam_settings = nullptr;
+ }
+ }
+}
+
void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) {
if (mNextRequests.empty()) {
return;
@@ -4531,9 +4807,11 @@
Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
if (halRequest->settings != NULL) {
- captureRequest->mSettings.unlock(halRequest->settings);
+ captureRequest->mSettingsList.begin()->metadata.unlock(halRequest->settings);
}
+ cleanupPhysicalSettings(captureRequest, halRequest);
+
if (captureRequest->mInputStream != NULL) {
captureRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
captureRequest->mInputStream->returnInputBuffer(captureRequest->mInputBuffer);
@@ -4797,7 +5075,7 @@
return DEAD_OBJECT;
}
- CameraMetadata &metadata = request->mSettings;
+ CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
size_t count = mTriggerMap.size();
for (size_t i = 0; i < count; ++i) {
@@ -4880,7 +5158,7 @@
ATRACE_CALL();
Mutex::Autolock al(mTriggerMutex);
- CameraMetadata &metadata = request->mSettings;
+ CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
/**
* Replace all old entries with their old values.
@@ -4945,7 +5223,7 @@
static const int32_t dummyTriggerId = 1;
status_t res;
- CameraMetadata &metadata = request->mSettings;
+ CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
// If AF trigger is active, insert a dummy AF trigger ID if none already
// exists
@@ -4980,7 +5258,7 @@
Camera3Device::PreparerThread::PreparerThread() :
Thread(/*canCallJava*/false), mListener(nullptr),
- mActive(false), mCancelNow(false) {
+ mActive(false), mCancelNow(false), mCurrentMaxCount(0), mCurrentPrepareComplete(false) {
}
Camera3Device::PreparerThread::~PreparerThread() {
@@ -5031,18 +5309,101 @@
}
// queue up the work
- mPendingStreams.push_back(stream);
+ mPendingStreams.emplace(maxCount, stream);
ALOGV("%s: Stream %d queued for preparing", __FUNCTION__, stream->getId());
return OK;
}
+void Camera3Device::PreparerThread::pause() {
+ ATRACE_CALL();
+
+ Mutex::Autolock l(mLock);
+
+ std::unordered_map<int, sp<camera3::Camera3StreamInterface> > pendingStreams;
+ pendingStreams.insert(mPendingStreams.begin(), mPendingStreams.end());
+ sp<camera3::Camera3StreamInterface> currentStream = mCurrentStream;
+ int currentMaxCount = mCurrentMaxCount;
+ mPendingStreams.clear();
+ mCancelNow = true;
+ while (mActive) {
+ auto res = mThreadActiveSignal.waitRelative(mLock, kActiveTimeout);
+ if (res == TIMED_OUT) {
+ ALOGE("%s: Timed out waiting on prepare thread!", __FUNCTION__);
+ return;
+ } else if (res != OK) {
+ ALOGE("%s: Encountered an error: %d waiting on prepare thread!", __FUNCTION__, res);
+ return;
+ }
+ }
+
+ //Check whether the prepare thread was able to complete the current
+ //stream. In case work is still pending emplace it along with the rest
+ //of the streams in the pending list.
+ if (currentStream != nullptr) {
+ if (!mCurrentPrepareComplete) {
+ pendingStreams.emplace(currentMaxCount, currentStream);
+ }
+ }
+
+ mPendingStreams.insert(pendingStreams.begin(), pendingStreams.end());
+ for (const auto& it : mPendingStreams) {
+ it.second->cancelPrepare();
+ }
+}
+
+status_t Camera3Device::PreparerThread::resume() {
+ ATRACE_CALL();
+ status_t res;
+
+ Mutex::Autolock l(mLock);
+ sp<NotificationListener> listener = mListener.promote();
+
+ if (mActive) {
+ ALOGE("%s: Trying to resume an already active prepare thread!", __FUNCTION__);
+ return NO_INIT;
+ }
+
+ auto it = mPendingStreams.begin();
+ for (; it != mPendingStreams.end();) {
+ res = it->second->startPrepare(it->first);
+ if (res == OK) {
+ if (listener != NULL) {
+ listener->notifyPrepared(it->second->getId());
+ }
+ it = mPendingStreams.erase(it);
+ } else if (res != NOT_ENOUGH_DATA) {
+ ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__,
+ res, strerror(-res));
+ it = mPendingStreams.erase(it);
+ } else {
+ it++;
+ }
+ }
+
+ if (mPendingStreams.empty()) {
+ return OK;
+ }
+
+ res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
+ if (res != OK) {
+ ALOGE("%s: Unable to start preparer stream: %d (%s)",
+ __FUNCTION__, res, strerror(-res));
+ return res;
+ }
+ mCancelNow = false;
+ mActive = true;
+ ALOGV("%s: Preparer stream started", __FUNCTION__);
+
+ return OK;
+}
+
status_t Camera3Device::PreparerThread::clear() {
ATRACE_CALL();
Mutex::Autolock l(mLock);
- for (const auto& stream : mPendingStreams) {
- stream->cancelPrepare();
+ for (const auto& it : mPendingStreams) {
+ it.second->cancelPrepare();
}
mPendingStreams.clear();
mCancelNow = true;
@@ -5067,12 +5428,15 @@
// threadLoop _must not_ re-acquire mLock after it sets mActive to false; would
// cause deadlock with prepare()'s requestExitAndWait triggered by !mActive.
mActive = false;
+ mThreadActiveSignal.signal();
return false;
}
// Get next stream to prepare
auto it = mPendingStreams.begin();
- mCurrentStream = *it;
+ mCurrentStream = it->second;
+ mCurrentMaxCount = it->first;
+ mCurrentPrepareComplete = false;
mPendingStreams.erase(it);
ATRACE_ASYNC_BEGIN("stream prepare", mCurrentStream->getId());
ALOGV("%s: Preparing stream %d", __FUNCTION__, mCurrentStream->getId());
@@ -5107,6 +5471,7 @@
ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
mCurrentStream.clear();
+ mCurrentPrepareComplete = true;
return true;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index cc7eb35..63e6219 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -99,12 +99,12 @@
// Capture and setStreamingRequest will configure streams if currently in
// idle state
status_t capture(CameraMetadata &request, int64_t *lastFrameNumber = NULL) override;
- status_t captureList(const List<const CameraMetadata> &requests,
+ status_t captureList(const List<const PhysicalCameraSettingsList> &requestsList,
const std::list<const SurfaceMap> &surfaceMaps,
int64_t *lastFrameNumber = NULL) override;
status_t setStreamingRequest(const CameraMetadata &request,
int64_t *lastFrameNumber = NULL) override;
- status_t setStreamingRequestList(const List<const CameraMetadata> &requests,
+ status_t setStreamingRequestList(const List<const PhysicalCameraSettingsList> &requestsList,
const std::list<const SurfaceMap> &surfaceMaps,
int64_t *lastFrameNumber = NULL) override;
status_t clearStreamingRequest(int64_t *lastFrameNumber = NULL) override;
@@ -119,12 +119,14 @@
status_t createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ const String8& physicalCameraId,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, uint64_t consumerUsage = 0) override;
status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+ const String8& physicalCameraId,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, uint64_t consumerUsage = 0) override;
@@ -426,7 +428,7 @@
class CaptureRequest : public LightRefBase<CaptureRequest> {
public:
- CameraMetadata mSettings;
+ PhysicalCameraSettingsList mSettingsList;
sp<camera3::Camera3Stream> mInputStream;
camera3_stream_buffer_t mInputBuffer;
Vector<sp<camera3::Camera3OutputStreamInterface> >
@@ -446,17 +448,17 @@
status_t checkStatusOkToCaptureLocked();
status_t convertMetadataListToRequestListLocked(
- const List<const CameraMetadata> &metadataList,
+ const List<const PhysicalCameraSettingsList> &metadataList,
const std::list<const SurfaceMap> &surfaceMaps,
bool repeating,
/*out*/
RequestList *requestList);
- void convertToRequestList(List<const CameraMetadata>& requests,
+ void convertToRequestList(List<const PhysicalCameraSettingsList>& requestsList,
std::list<const SurfaceMap>& surfaceMaps,
const CameraMetadata& request);
- status_t submitRequestsHelper(const List<const CameraMetadata> &requests,
+ status_t submitRequestsHelper(const List<const PhysicalCameraSettingsList> &requestsList,
const std::list<const SurfaceMap> &surfaceMaps,
bool repeating,
int64_t *lastFrameNumber = NULL);
@@ -541,22 +543,34 @@
* Do common work for setting up a streaming or single capture request.
* On success, will transition to ACTIVE if in IDLE.
*/
- sp<CaptureRequest> setUpRequestLocked(const CameraMetadata &request,
+ sp<CaptureRequest> setUpRequestLocked(const PhysicalCameraSettingsList &request,
const SurfaceMap &surfaceMap);
/**
* Build a CaptureRequest request from the CameraDeviceBase request
* settings.
*/
- sp<CaptureRequest> createCaptureRequest(const CameraMetadata &request,
+ sp<CaptureRequest> createCaptureRequest(const PhysicalCameraSettingsList &request,
const SurfaceMap &surfaceMap);
/**
+ * Internally re-configure camera device using new session parameters.
+ * This will get triggered by the request thread.
+ */
+ bool reconfigureCamera(const CameraMetadata& sessionParams);
+
+ /**
+ * Filter stream session parameters and configure camera HAL.
+ */
+ status_t filterParamsAndConfigureLocked(const CameraMetadata& sessionParams,
+ int operatingMode);
+
+ /**
* Take the currently-defined set of streams and configure the HAL to use
* them. This is a long-running operation (may be several hundered ms).
*/
status_t configureStreamsLocked(int operatingMode,
- const CameraMetadata& sessionParams);
+ const CameraMetadata& sessionParams, bool notifyRequestThread = true);
/**
* Cancel stream configuration that did not finish successfully.
@@ -655,7 +669,7 @@
RequestThread(wp<Camera3Device> parent,
sp<camera3::StatusTracker> statusTracker,
- sp<HalInterface> interface);
+ sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys);
~RequestThread();
void setNotificationListener(wp<NotificationListener> listener);
@@ -663,7 +677,8 @@
/**
* Call after stream (re)-configuration is completed.
*/
- void configurationComplete(bool isConstrainedHighSpeed);
+ void configurationComplete(bool isConstrainedHighSpeed,
+ const CameraMetadata& sessionParams);
/**
* Set or clear the list of repeating requests. Does not block
@@ -790,6 +805,10 @@
// Stop the repeating request if any of its output streams is abandoned.
void checkAndStopRepeatingRequest();
+ // Release physical camera settings and camera id resources.
+ void cleanupPhysicalSettings(sp<CaptureRequest> request,
+ /*out*/camera3_capture_request_t *halRequest);
+
// Pause handling
bool waitIfPaused();
void unpauseForNewRequests();
@@ -812,6 +831,12 @@
// Calculate the expected maximum duration for a request
nsecs_t calculateMaxExpectedDuration(const camera_metadata_t *request);
+ // Check and update latest session parameters based on the current request settings.
+ bool updateSessionParameters(const CameraMetadata& settings);
+
+ // Re-configure camera using the latest session parameters.
+ bool reconfigureCamera();
+
wp<Camera3Device> mParent;
wp<camera3::StatusTracker> mStatusTracker;
sp<HalInterface> mInterface;
@@ -869,6 +894,9 @@
static const int32_t kRequestLatencyBinSize = 40; // in ms
CameraLatencyHistogram mRequestLatency;
+
+ Vector<int32_t> mSessionParamKeys;
+ CameraMetadata mLatestSessionParams;
};
sp<RequestThread> mRequestThread;
@@ -1006,21 +1034,34 @@
*/
status_t clear();
+ /**
+ * Pause all preparation activities
+ */
+ void pause();
+
+ /**
+ * Resume preparation activities
+ */
+ status_t resume();
+
private:
Mutex mLock;
+ Condition mThreadActiveSignal;
virtual bool threadLoop();
// Guarded by mLock
wp<NotificationListener> mListener;
- List<sp<camera3::Camera3StreamInterface> > mPendingStreams;
+ std::unordered_map<int, sp<camera3::Camera3StreamInterface> > mPendingStreams;
bool mActive;
bool mCancelNow;
// Only accessed by threadLoop and the destructor
sp<camera3::Camera3StreamInterface> mCurrentStream;
+ int mCurrentMaxCount;
+ bool mCurrentPrepareComplete;
};
sp<PreparerThread> mPreparerThread;
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
index 0a245c4..44eb68a 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2014-2018 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.
@@ -26,9 +26,12 @@
namespace camera3 {
+const String8 Camera3DummyStream::DUMMY_ID;
+
Camera3DummyStream::Camera3DummyStream(int id) :
Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, DUMMY_WIDTH, DUMMY_HEIGHT,
- /*maxSize*/0, DUMMY_FORMAT, DUMMY_DATASPACE, DUMMY_ROTATION) {
+ /*maxSize*/0, DUMMY_FORMAT, DUMMY_DATASPACE, DUMMY_ROTATION,
+ DUMMY_ID) {
}
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.h b/services/camera/libcameraservice/device3/Camera3DummyStream.h
index 684f4b0..dcf9160 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.h
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2014-2018 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.
@@ -114,6 +114,7 @@
static const android_dataspace DUMMY_DATASPACE = HAL_DATASPACE_UNKNOWN;
static const camera3_stream_rotation_t DUMMY_ROTATION = CAMERA3_STREAM_ROTATION_0;
static const uint64_t DUMMY_USAGE = GRALLOC_USAGE_HW_COMPOSER;
+ static const String8 DUMMY_ID;
/**
* Internal Camera3Stream interface
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index a52422d..3c1e43d 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -31,9 +31,11 @@
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, int setId) :
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ const String8& physicalCameraId, int setId) :
Camera3Stream(id, type,
- width, height, maxSize, format, dataSpace, rotation, setId),
+ width, height, maxSize, format, dataSpace, rotation,
+ physicalCameraId, setId),
mTotalBufferCount(0),
mHandoutTotalBufferCount(0),
mHandoutOutputBufferCount(0),
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index 2376058..0a31d44 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -35,6 +35,7 @@
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,
+ const String8& physicalCameraId,
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 2cb1ea7..017d7be 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -27,10 +27,13 @@
namespace camera3 {
+const String8 Camera3InputStream::DUMMY_ID;
+
Camera3InputStream::Camera3InputStream(int id,
uint32_t width, uint32_t height, int format) :
Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height, /*maxSize*/0,
- format, HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0) {
+ format, HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0,
+ DUMMY_ID) {
if (format == HAL_PIXEL_FORMAT_BLOB) {
ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__);
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index 81226f8..0732464 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -53,6 +53,8 @@
sp<IGraphicBufferProducer> mProducer;
Vector<BufferItem> mBuffersInFlight;
+ static const String8 DUMMY_ID;
+
/**
* Camera3IOStreamBase
*/
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index e79eecc..b73e256 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -35,9 +35,11 @@
sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation,
- nsecs_t timestampOffset, int setId) :
+ nsecs_t timestampOffset, const String8& physicalCameraId,
+ int setId) :
Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
- /*maxSize*/0, format, dataSpace, rotation, setId),
+ /*maxSize*/0, format, dataSpace, rotation,
+ physicalCameraId, setId),
mConsumer(consumer),
mTransform(0),
mTraceFirstBuffer(true),
@@ -61,9 +63,9 @@
sp<Surface> consumer,
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation,
- nsecs_t timestampOffset, int setId) :
+ nsecs_t timestampOffset, const String8& physicalCameraId, int setId) :
Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, maxSize,
- format, dataSpace, rotation, setId),
+ format, dataSpace, rotation, physicalCameraId, setId),
mConsumer(consumer),
mTransform(0),
mTraceFirstBuffer(true),
@@ -93,9 +95,11 @@
Camera3OutputStream::Camera3OutputStream(int id,
uint32_t width, uint32_t height, int format,
uint64_t consumerUsage, android_dataspace dataSpace,
- camera3_stream_rotation_t rotation, nsecs_t timestampOffset, int setId) :
+ camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
+ const String8& physicalCameraId, int setId) :
Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
- /*maxSize*/0, format, dataSpace, rotation, setId),
+ /*maxSize*/0, format, dataSpace, rotation,
+ physicalCameraId, setId),
mConsumer(nullptr),
mTransform(0),
mTraceFirstBuffer(true),
@@ -131,11 +135,13 @@
int format,
android_dataspace dataSpace,
camera3_stream_rotation_t rotation,
+ const String8& physicalCameraId,
uint64_t consumerUsage, nsecs_t timestampOffset,
int setId) :
Camera3IOStreamBase(id, type, width, height,
/*maxSize*/0,
- format, dataSpace, rotation, setId),
+ format, dataSpace, rotation,
+ physicalCameraId, setId),
mTransform(0),
mTraceFirstBuffer(true),
mUseMonoTimestamp(false),
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 18b1901..824aef7 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -82,7 +82,8 @@
Camera3OutputStream(int id, sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation,
- nsecs_t timestampOffset, int setId = CAMERA3_STREAM_SET_ID_INVALID);
+ nsecs_t timestampOffset, const String8& physicalCameraId,
+ int setId = CAMERA3_STREAM_SET_ID_INVALID);
/**
* Set up a stream for formats that have a variable buffer size for the same
@@ -93,7 +94,8 @@
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,
- nsecs_t timestampOffset, int setId = CAMERA3_STREAM_SET_ID_INVALID);
+ nsecs_t timestampOffset, const String8& physicalCameraId,
+ int setId = CAMERA3_STREAM_SET_ID_INVALID);
/**
* Set up a stream with deferred consumer for formats that have 2 dimensions, such as
@@ -103,6 +105,7 @@
Camera3OutputStream(int id, uint32_t width, uint32_t height, int format,
uint64_t consumerUsage, android_dataspace dataSpace,
camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
+ const String8& physicalCameraId,
int setId = CAMERA3_STREAM_SET_ID_INVALID);
virtual ~Camera3OutputStream();
@@ -194,6 +197,7 @@
Camera3OutputStream(int id, camera3_stream_type_t type,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ const String8& physicalCameraId,
uint64_t consumerUsage = 0, nsecs_t timestampOffset = 0,
int setId = CAMERA3_STREAM_SET_ID_INVALID);
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index 1c9417b..2bb9ff7 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2016-2018 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.
@@ -27,10 +27,11 @@
uint32_t width, uint32_t height, int format,
uint64_t consumerUsage, android_dataspace dataSpace,
camera3_stream_rotation_t rotation,
- nsecs_t timestampOffset, int setId) :
+ nsecs_t timestampOffset, const String8& physicalCameraId,
+ int setId) :
Camera3OutputStream(id, CAMERA3_STREAM_OUTPUT, width, height,
- format, dataSpace, rotation, consumerUsage,
- timestampOffset, setId) {
+ format, dataSpace, rotation, physicalCameraId,
+ consumerUsage, timestampOffset, setId) {
size_t consumerCount = std::min(surfaces.size(), kMaxOutputs);
if (surfaces.size() > consumerCount) {
ALOGE("%s: Trying to add more consumers than the maximum ", __func__);
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index 6eab8bd..02b1c09 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2016-2018 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.
@@ -36,6 +36,7 @@
uint32_t width, uint32_t height, int format,
uint64_t consumerUsage, android_dataspace dataSpace,
camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
+ const String8& physicalCameraId,
int setId = CAMERA3_STREAM_SET_ID_INVALID);
virtual ~Camera3SharedOutputStream();
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index fbe8f4f..0d91620 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -47,7 +47,8 @@
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, int setId) :
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+ const String8& physicalCameraId, int setId) :
camera3_stream(),
mId(id),
mSetId(setId),
@@ -64,7 +65,8 @@
mLastMaxCount(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX),
mBufferLimitLatency(kBufferLimitLatencyBinSize),
mFormatOverridden(false),
- mOriginalFormat(-1) {
+ mOriginalFormat(-1),
+ mPhysicalCameraId(physicalCameraId) {
camera3_stream::stream_type = type;
camera3_stream::width = width;
@@ -74,6 +76,7 @@
camera3_stream::rotation = rotation;
camera3_stream::max_buffers = 0;
camera3_stream::priv = NULL;
+ camera3_stream::physical_camera_id = mPhysicalCameraId.string();
if ((format == HAL_PIXEL_FORMAT_BLOB || format == HAL_PIXEL_FORMAT_RAW_OPAQUE) &&
maxSize == 0) {
@@ -140,6 +143,75 @@
return mOriginalDataSpace;
}
+status_t Camera3Stream::forceToIdle() {
+ ATRACE_CALL();
+ Mutex::Autolock l(mLock);
+ status_t res;
+
+ switch (mState) {
+ case STATE_ERROR:
+ case STATE_CONSTRUCTED:
+ case STATE_IN_CONFIG:
+ case STATE_PREPARING:
+ case STATE_IN_RECONFIG:
+ ALOGE("%s: Invalid state: %d", __FUNCTION__, mState);
+ res = NO_INIT;
+ break;
+ case STATE_CONFIGURED:
+ if (hasOutstandingBuffersLocked()) {
+ sp<StatusTracker> statusTracker = mStatusTracker.promote();
+ if (statusTracker != 0) {
+ statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
+ }
+ }
+
+ mState = STATE_IN_IDLE;
+ res = OK;
+
+ break;
+ default:
+ ALOGE("%s: Unknown state %d", __FUNCTION__, mState);
+ res = NO_INIT;
+ }
+
+ return res;
+}
+
+status_t Camera3Stream::restoreConfiguredState() {
+ ATRACE_CALL();
+ Mutex::Autolock l(mLock);
+ status_t res;
+
+ switch (mState) {
+ case STATE_ERROR:
+ case STATE_CONSTRUCTED:
+ case STATE_IN_CONFIG:
+ case STATE_PREPARING:
+ case STATE_IN_RECONFIG:
+ case STATE_CONFIGURED:
+ ALOGE("%s: Invalid state: %d", __FUNCTION__, mState);
+ res = NO_INIT;
+ break;
+ case STATE_IN_IDLE:
+ if (hasOutstandingBuffersLocked()) {
+ sp<StatusTracker> statusTracker = mStatusTracker.promote();
+ if (statusTracker != 0) {
+ statusTracker->markComponentActive(mStatusId);
+ }
+ }
+
+ mState = STATE_CONFIGURED;
+ res = OK;
+
+ break;
+ default:
+ ALOGE("%s: Unknown state %d", __FUNCTION__, mState);
+ res = NO_INIT;
+ }
+
+ return res;
+}
+
camera3_stream* Camera3Stream::startConfiguration() {
ATRACE_CALL();
Mutex::Autolock l(mLock);
@@ -150,6 +222,7 @@
ALOGE("%s: In error state", __FUNCTION__);
return NULL;
case STATE_CONSTRUCTED:
+ case STATE_IN_IDLE:
// OK
break;
case STATE_IN_CONFIG:
@@ -179,6 +252,11 @@
return NULL;
}
+ if (mState == STATE_IN_IDLE) {
+ // Skip configuration.
+ return this;
+ }
+
// Stop tracking if currently doing so
if (mStatusId != StatusTracker::NO_STATUS_ID) {
sp<StatusTracker> statusTracker = mStatusTracker.promote();
@@ -219,6 +297,9 @@
ALOGE("%s: Cannot finish configuration that hasn't been started",
__FUNCTION__);
return INVALID_OPERATION;
+ case STATE_IN_IDLE:
+ //Skip configuration in this state
+ return OK;
default:
ALOGE("%s: Unknown state", __FUNCTION__);
return INVALID_OPERATION;
@@ -267,6 +348,7 @@
return INVALID_OPERATION;
case STATE_IN_CONFIG:
case STATE_IN_RECONFIG:
+ case STATE_IN_IDLE:
// OK
break;
case STATE_CONSTRUCTED:
@@ -282,7 +364,9 @@
mUsage = mOldUsage;
camera3_stream::max_buffers = mOldMaxBuffers;
- mState = (mState == STATE_IN_RECONFIG) ? STATE_CONFIGURED : STATE_CONSTRUCTED;
+ mState = ((mState == STATE_IN_RECONFIG) || (mState == STATE_IN_IDLE)) ? STATE_CONFIGURED :
+ STATE_CONSTRUCTED;
+
return OK;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 6e7912e..f85dff2 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -68,6 +68,12 @@
* duration. In this state, only prepareNextBuffer() and cancelPrepare()
* may be called.
*
+ * STATE_IN_IDLE: This is a temporary state only intended to be used for input
+ * streams and only for the case where we need to re-configure the camera device
+ * while the input stream has an outstanding buffer. All other streams should not
+ * be able to switch to this state. For them this is invalid and should be handled
+ * as an unknown state.
+ *
* Transition table:
*
* <none> => STATE_CONSTRUCTED:
@@ -98,6 +104,11 @@
* all stream buffers, or cancelPrepare is called.
* STATE_CONFIGURED => STATE_ABANDONED:
* When the buffer queue of the stream is abandoned.
+ * STATE_CONFIGURED => STATE_IN_IDLE:
+ * Only for an input stream which has an outstanding buffer.
+ * STATE_IN_IDLE => STATE_CONFIGURED:
+ * After the internal re-configuration, the input should revert back to
+ * the configured state.
*
* Status Tracking:
* Each stream is tracked by StatusTracker as a separate component,
@@ -108,7 +119,9 @@
*
* - ACTIVE: One or more buffers have been handed out (with #getBuffer).
* - IDLE: All buffers have been returned (with #returnBuffer), and their
- * respective release_fence(s) have been signaled.
+ * respective release_fence(s) have been signaled. The only exception to this
+ * rule is an input stream that moves to "STATE_IN_IDLE" during internal
+ * re-configuration.
*
* A typical use case is output streams. When the HAL has any buffers
* dequeued, the stream is marked ACTIVE. When the HAL returns all buffers
@@ -386,6 +399,19 @@
*/
bool isAbandoned() const;
+ /**
+ * Switch a configured stream with possibly outstanding buffers in idle
+ * state. Configuration for such streams will be skipped assuming there
+ * are no changes to the stream parameters.
+ */
+ status_t forceToIdle();
+
+ /**
+ * Restore a forced idle stream to configured state, marking it active
+ * in case it contains outstanding buffers.
+ */
+ status_t restoreConfiguredState();
+
protected:
const int mId;
/**
@@ -414,7 +440,8 @@
STATE_IN_RECONFIG,
STATE_CONFIGURED,
STATE_PREPARING,
- STATE_ABANDONED
+ STATE_ABANDONED,
+ STATE_IN_IDLE
} mState;
mutable Mutex mLock;
@@ -422,7 +449,7 @@
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,
- int setId);
+ const String8& physicalCameraId, int setId);
wp<Camera3StreamBufferFreedListener> mBufferFreedListener;
@@ -529,6 +556,7 @@
bool mDataSpaceOverridden;
android_dataspace mOriginalDataSpace;
+ String8 mPhysicalCameraId;
}; // class Camera3Stream
}; // namespace camera3
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index 4980316..9f3746f 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -21,6 +21,16 @@
# extractor libraries
LOCAL_REQUIRED_MODULES := \
+ libaacextractor \
+ libamrextractor \
+ libflacextractor \
+ libmidiextractor \
+ libmkvextractor \
+ libmp3extractor \
+ libmp4extractor \
+ libmpeg2extractor \
+ liboggextractor \
+ libwavextractor \
MediaComponents \
LOCAL_SRC_FILES := main_extractorservice.cpp
diff --git a/services/soundtrigger/Android.mk b/services/soundtrigger/Android.mk
index ca44737..ad3666e 100644
--- a/services/soundtrigger/Android.mk
+++ b/services/soundtrigger/Android.mk
@@ -53,6 +53,7 @@
libhidltransport \
libbase \
libaudiohal \
+ libaudiohal_deathhandler \
android.hardware.soundtrigger@2.0 \
android.hardware.soundtrigger@2.1 \
android.hardware.audio.common@2.0 \