Merge "Add graphics composer support for HWC > HWC1.1"
diff --git a/automotive/vehicle/2.1/Android.bp b/automotive/vehicle/2.1/Android.bp
index dcf395c..cf4d8b0 100644
--- a/automotive/vehicle/2.1/Android.bp
+++ b/automotive/vehicle/2.1/Android.bp
@@ -51,6 +51,7 @@
"libutils",
"libcutils",
"android.hardware.automotive.vehicle@2.0",
+ "android.hidl.base@1.0",
],
export_shared_lib_headers: [
"libhidlbase",
@@ -58,5 +59,6 @@
"libhwbinder",
"libutils",
"android.hardware.automotive.vehicle@2.0",
+ "android.hidl.base@1.0",
],
}
diff --git a/bluetooth/1.0/default/bluetooth_hci.cc b/bluetooth/1.0/default/bluetooth_hci.cc
index 5a282bf..fec5b81 100644
--- a/bluetooth/1.0/default/bluetooth_hci.cc
+++ b/bluetooth/1.0/default/bluetooth_hci.cc
@@ -30,6 +30,19 @@
static const uint8_t HCI_DATA_TYPE_ACL = 2;
static const uint8_t HCI_DATA_TYPE_SCO = 3;
+class BluetoothDeathRecipient : public hidl_death_recipient {
+ public:
+ BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {}
+
+ virtual void serviceDied(
+ uint64_t /*cookie*/,
+ const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+ ALOGE("BluetoothDeathRecipient::serviceDied - Bluetooth service died");
+ mHci->close();
+ }
+ sp<IBluetoothHci> mHci;
+};
+
BluetoothHci::BluetoothHci()
: deathRecipient(new BluetoothDeathRecipient(this)) {}
@@ -41,19 +54,37 @@
bool rc = VendorInterface::Initialize(
[this](bool status) {
- event_cb_->initializationComplete(
+ auto hidl_status = event_cb_->initializationComplete(
status ? Status::SUCCESS : Status::INITIALIZATION_ERROR);
+ if (!hidl_status.isOk()) {
+ ALOGE("VendorInterface -> Unable to call initializationComplete()");
+ }
},
[this](const hidl_vec<uint8_t>& packet) {
- event_cb_->hciEventReceived(packet);
+ auto hidl_status = event_cb_->hciEventReceived(packet);
+ if (!hidl_status.isOk()) {
+ ALOGE("VendorInterface -> Unable to call hciEventReceived()");
+ }
},
[this](const hidl_vec<uint8_t>& packet) {
- event_cb_->aclDataReceived(packet);
+ auto hidl_status = event_cb_->aclDataReceived(packet);
+ if (!hidl_status.isOk()) {
+ ALOGE("VendorInterface -> Unable to call aclDataReceived()");
+ }
},
[this](const hidl_vec<uint8_t>& packet) {
- event_cb_->scoDataReceived(packet);
+ auto hidl_status = event_cb_->scoDataReceived(packet);
+ if (!hidl_status.isOk()) {
+ ALOGE("VendorInterface -> Unable to call scoDataReceived()");
+ }
});
- if (!rc) event_cb_->initializationComplete(Status::INITIALIZATION_ERROR);
+ if (!rc) {
+ auto hidl_status =
+ event_cb_->initializationComplete(Status::INITIALIZATION_ERROR);
+ if (!hidl_status.isOk()) {
+ ALOGE("VendorInterface -> Unable to call initializationComplete(ERR)");
+ }
+ }
return Void();
}
diff --git a/bluetooth/1.0/default/bluetooth_hci.h b/bluetooth/1.0/default/bluetooth_hci.h
index 67d6c37..4f92231 100644
--- a/bluetooth/1.0/default/bluetooth_hci.h
+++ b/bluetooth/1.0/default/bluetooth_hci.h
@@ -30,16 +30,7 @@
using ::android::hardware::Return;
using ::android::hardware::hidl_vec;
-struct BluetoothDeathRecipient : hidl_death_recipient {
- BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {}
-
- virtual void serviceDied(
- uint64_t /*cookie*/,
- const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
- mHci->close();
- }
- sp<IBluetoothHci> mHci;
-};
+class BluetoothDeathRecipient;
class BluetoothHci : public IBluetoothHci {
public:
diff --git a/broadcastradio/1.1/Android.bp b/broadcastradio/1.1/Android.bp
index c9a8b10..570d1ae 100644
--- a/broadcastradio/1.1/Android.bp
+++ b/broadcastradio/1.1/Android.bp
@@ -65,6 +65,7 @@
"libutils",
"libcutils",
"android.hardware.broadcastradio@1.0",
+ "android.hidl.base@1.0",
],
export_shared_lib_headers: [
"libhidlbase",
@@ -72,5 +73,6 @@
"libhwbinder",
"libutils",
"android.hardware.broadcastradio@1.0",
+ "android.hidl.base@1.0",
],
}
diff --git a/camera/device/3.2/ICameraDeviceCallback.hal b/camera/device/3.2/ICameraDeviceCallback.hal
index 753d085..bf51da2 100644
--- a/camera/device/3.2/ICameraDeviceCallback.hal
+++ b/camera/device/3.2/ICameraDeviceCallback.hal
@@ -35,7 +35,8 @@
/**
* processCaptureResult:
*
- * Send results from a completed capture to the framework.
+ * Send results from one or more completed or partially completed captures
+ * to the framework.
* processCaptureResult() may be invoked multiple times by the HAL in
* response to a single capture request. This allows, for example, the
* metadata and low-resolution buffers to be returned in one call, and
@@ -61,11 +62,14 @@
* acceptable and expected that the buffer for request 5 for stream A may be
* returned after the buffer for request 6 for stream B is. And it is
* acceptable that the result metadata for request 6 for stream B is
- * returned before the buffer for request 5 for stream A is.
+ * returned before the buffer for request 5 for stream A is. If multiple
+ * capture results are included in a single call, camera framework must
+ * process results sequentially from lower index to higher index, as if
+ * these results were sent to camera framework one by one, from lower index
+ * to higher index.
*
* The HAL retains ownership of result structure, which only needs to be
- * valid to access during this call. The framework must copy whatever it
- * needs before this call returns.
+ * valid to access during this call.
*
* The output buffers do not need to be filled yet; the framework must wait
* on the stream buffer release sync fence before reading the buffer
@@ -93,20 +97,23 @@
*
* Performance requirements:
*
- * This is a non-blocking call. The framework must return this call in 5ms.
+ * This is a non-blocking call. The framework must handle each CaptureResult
+ * within 5ms.
*
* The pipeline latency (see S7 for definition) should be less than or equal to
* 4 frame intervals, and must be less than or equal to 8 frame intervals.
*
*/
- processCaptureResult(CaptureResult result);
+ processCaptureResult(vec<CaptureResult> results);
/**
* notify:
*
* Asynchronous notification callback from the HAL, fired for various
* reasons. Only for information independent of frame capture, or that
- * require specific timing.
+ * require specific timing. Multiple messages may be sent in one call; a
+ * message with a higher index must be considered to have occurred after a
+ * message with a lower index.
*
* Multiple threads may call notify() simultaneously.
*
@@ -119,8 +126,8 @@
* ------------------------------------------------------------------------
* Performance requirements:
*
- * This is a non-blocking call. The framework must return this call in 5ms.
+ * This is a non-blocking call. The framework must handle each message in 5ms.
*/
- notify(NotifyMsg msg);
+ notify(vec<NotifyMsg> msgs);
};
diff --git a/camera/device/3.2/ICameraDeviceSession.hal b/camera/device/3.2/ICameraDeviceSession.hal
index e92d756..d8d3177 100644
--- a/camera/device/3.2/ICameraDeviceSession.hal
+++ b/camera/device/3.2/ICameraDeviceSession.hal
@@ -171,14 +171,16 @@
/**
* processCaptureRequest:
*
- * Send a new capture request to the HAL. The HAL must not return from
- * this call until it is ready to accept the next request to process. Only
- * one call to processCaptureRequest() must be made at a time by the
- * framework, and the calls must all be from the same thread. The next call
- * to processCaptureRequest() must be made as soon as a new request and
- * its associated buffers are available. In a normal preview scenario, this
- * means the function is generally called again by the framework almost
- * instantly.
+ * Send a list of capture requests to the HAL. The HAL must not return from
+ * this call until it is ready to accept the next set of requests to
+ * process. Only one call to processCaptureRequest() must be made at a time
+ * by the framework, and the calls must all be from the same thread. The
+ * next call to processCaptureRequest() must be made as soon as a new
+ * request and its associated buffers are available. In a normal preview
+ * scenario, this means the function is generally called again by the
+ * framework almost instantly. If more than one request is provided by the
+ * client, the HAL must process the requests in order of lowest index to
+ * highest index.
*
* The actual request processing is asynchronous, with the results of
* capture being returned by the HAL through the processCaptureResult()
@@ -229,10 +231,14 @@
* If the camera device has encountered a serious error. After this
* error is returned, only the close() method can be successfully
* called by the framework.
+ * @return numRequestProcessed Number of requests successfully processed by
+ * camera HAL. When status is OK, this must be equal to the size of
+ * requests. When the call fails, this number is the number of requests
+ * that HAL processed successfully before HAL runs into an error.
*
*/
- processCaptureRequest(CaptureRequest request)
- generates (Status status);
+ processCaptureRequest(vec<CaptureRequest> requests)
+ generates (Status status, uint32_t numRequestProcessed);
/**
* flush:
diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp
index 0a457ad..a742335 100644
--- a/camera/device/3.2/default/CameraDevice.cpp
+++ b/camera/device/3.2/default/CameraDevice.cpp
@@ -229,7 +229,18 @@
return Void();
}
- session = new CameraDeviceSession(device, callback);
+ struct camera_info info;
+ res = mModule->getCameraInfo(mCameraIdInt, &info);
+ if (res != OK) {
+ ALOGE("%s: Could not open camera: getCameraInfo failed", __FUNCTION__);
+ device->common.close(&device->common);
+ mLock.unlock();
+ _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+ return Void();
+ }
+
+ session = new CameraDeviceSession(
+ device, info.static_camera_characteristics, callback);
if (session == nullptr) {
ALOGE("%s: camera device session allocation failed", __FUNCTION__);
mLock.unlock();
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index ae5d576..fb1d1ff 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "CamDevSession@3.2-impl"
#include <android/log.h>
+#include <set>
#include <utils/Trace.h>
#include <hardware/gralloc.h>
#include <hardware/gralloc1.h>
@@ -30,12 +31,25 @@
namespace implementation {
HandleImporter& CameraDeviceSession::sHandleImporter = HandleImporter::getInstance();
+const int CameraDeviceSession::ResultBatcher::NOT_BATCHED;
CameraDeviceSession::CameraDeviceSession(
- camera3_device_t* device, const sp<ICameraDeviceCallback>& callback) :
+ camera3_device_t* device,
+ const camera_metadata_t* deviceInfo,
+ const sp<ICameraDeviceCallback>& callback) :
camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
mDevice(device),
- mCallback(callback) {
+ mResultBatcher(callback) {
+
+ mDeviceInfo = deviceInfo;
+ uint32_t numPartialResults = 1;
+ camera_metadata_entry partialResultsCount =
+ mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
+ if (partialResultsCount.count > 0) {
+ numPartialResults = partialResultsCount.data.i32[0];
+ }
+ mResultBatcher.setNumPartialResults(numPartialResults);
+
mInitFail = initialize();
}
@@ -177,6 +191,354 @@
}
}
+CameraDeviceSession::ResultBatcher::ResultBatcher(
+ const sp<ICameraDeviceCallback>& callback) : mCallback(callback) {};
+
+bool CameraDeviceSession::ResultBatcher::InflightBatch::allDelivered() const {
+ if (!mShutterDelivered) return false;
+
+ if (mPartialResultProgress < mNumPartialResults) {
+ return false;
+ }
+
+ for (const auto& pair : mBatchBufs) {
+ if (!pair.second.mDelivered) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void CameraDeviceSession::ResultBatcher::setNumPartialResults(uint32_t n) {
+ Mutex::Autolock _l(mLock);
+ mNumPartialResults = n;
+}
+
+void CameraDeviceSession::ResultBatcher::setBatchedStreams(
+ const std::vector<int>& streamsToBatch) {
+ Mutex::Autolock _l(mLock);
+ mStreamsToBatch = streamsToBatch;
+}
+
+void CameraDeviceSession::ResultBatcher::registerBatch(
+ const hidl_vec<CaptureRequest>& requests) {
+ auto batch = std::make_shared<InflightBatch>();
+ batch->mFirstFrame = requests[0].frameNumber;
+ batch->mBatchSize = requests.size();
+ batch->mLastFrame = batch->mFirstFrame + batch->mBatchSize - 1;
+ batch->mNumPartialResults = mNumPartialResults;
+ for (int id : mStreamsToBatch) {
+ batch->mBatchBufs[id] = InflightBatch::BufferBatch();
+ }
+ Mutex::Autolock _l(mLock);
+ mInflightBatches.push_back(batch);
+}
+
+std::pair<int, std::shared_ptr<CameraDeviceSession::ResultBatcher::InflightBatch>>
+CameraDeviceSession::ResultBatcher::getBatch(
+ uint32_t frameNumber) {
+ Mutex::Autolock _l(mLock);
+ int numBatches = mInflightBatches.size();
+ if (numBatches == 0) {
+ return std::make_pair(NOT_BATCHED, nullptr);
+ }
+ uint32_t frameMin = mInflightBatches[0]->mFirstFrame;
+ uint32_t frameMax = mInflightBatches[numBatches - 1]->mLastFrame;
+ if (frameNumber < frameMin || frameNumber > frameMax) {
+ return std::make_pair(NOT_BATCHED, nullptr);
+ }
+ for (int i = 0; i < numBatches; i++) {
+ if (frameNumber >= mInflightBatches[i]->mFirstFrame &&
+ frameNumber <= mInflightBatches[i]->mLastFrame) {
+ return std::make_pair(i, mInflightBatches[i]);
+ }
+ }
+ return std::make_pair(NOT_BATCHED, nullptr);
+}
+
+void CameraDeviceSession::ResultBatcher::checkAndRemoveFirstBatch() {
+ Mutex::Autolock _l(mLock);
+ if (mInflightBatches.size() > 0) {
+ std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
+ bool shouldRemove = false;
+ {
+ Mutex::Autolock _l(batch->mLock);
+ if (batch->allDelivered()) {
+ batch->mRemoved = true;
+ shouldRemove = true;
+ }
+ }
+ if (shouldRemove) {
+ mInflightBatches.pop_front();
+ }
+ }
+}
+
+void CameraDeviceSession::ResultBatcher::sendBatchShutterCbsLocked(std::shared_ptr<InflightBatch> batch) {
+ if (batch->mShutterDelivered) {
+ ALOGW("%s: batch shutter callback already sent!", __FUNCTION__);
+ return;
+ }
+
+ mCallback->notify(batch->mShutterMsgs);
+ batch->mShutterDelivered = true;
+ batch->mShutterMsgs.clear();
+}
+
+void CameraDeviceSession::ResultBatcher::freeReleaseFences(hidl_vec<CaptureResult>& results) {
+ for (auto& result : results) {
+ if (result.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
+ native_handle_t* handle = const_cast<native_handle_t*>(
+ result.inputBuffer.releaseFence.getNativeHandle());
+ native_handle_delete(handle);
+ }
+ for (auto& buf : result.outputBuffers) {
+ if (buf.releaseFence.getNativeHandle() != nullptr) {
+ native_handle_t* handle = const_cast<native_handle_t*>(
+ buf.releaseFence.getNativeHandle());
+ native_handle_delete(handle);
+ }
+ }
+ }
+ return;
+}
+
+void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch) {
+ sendBatchBuffersLocked(batch, mStreamsToBatch);
+}
+
+void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
+ std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams) {
+ size_t batchSize = 0;
+ for (int streamId : streams) {
+ auto it = batch->mBatchBufs.find(streamId);
+ if (it != batch->mBatchBufs.end()) {
+ InflightBatch::BufferBatch& bb = it->second;
+ if (bb.mDelivered) {
+ continue;
+ }
+ if (bb.mBuffers.size() > batchSize) {
+ batchSize = bb.mBuffers.size();
+ }
+ } else {
+ ALOGE("%s: stream ID %d is not batched!", __FUNCTION__, streamId);
+ return;
+ }
+ }
+
+ if (batchSize == 0) {
+ ALOGW("%s: there is no buffer to be delivered for this batch.", __FUNCTION__);
+ for (int streamId : streams) {
+ InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
+ bb.mDelivered = true;
+ }
+ return;
+ }
+
+ hidl_vec<CaptureResult> results;
+ results.resize(batchSize);
+ for (size_t i = 0; i < batchSize; i++) {
+ results[i].frameNumber = batch->mFirstFrame + i;
+ results[i].partialResult = 0; // 0 for buffer only results
+ results[i].inputBuffer.streamId = -1;
+ results[i].inputBuffer.bufferId = 0;
+ results[i].inputBuffer.buffer = nullptr;
+ std::vector<StreamBuffer> outBufs;
+ for (int streamId : streams) {
+ InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
+ if (bb.mDelivered) {
+ continue;
+ }
+ if (i < bb.mBuffers.size()) {
+ outBufs.push_back(bb.mBuffers[i]);
+ }
+ }
+ results[i].outputBuffers = outBufs;
+ }
+ mCallback->processCaptureResult(results);
+ freeReleaseFences(results);
+ for (int streamId : streams) {
+ InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
+ bb.mDelivered = true;
+ bb.mBuffers.clear();
+ }
+}
+
+void CameraDeviceSession::ResultBatcher::sendBatchMetadataLocked(
+ std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx) {
+ if (lastPartialResultIdx <= batch->mPartialResultProgress) {
+ // Result has been delivered. Return
+ ALOGW("%s: partial result %u has been delivered", __FUNCTION__, lastPartialResultIdx);
+ return;
+ }
+
+ std::vector<CaptureResult> results;
+ std::vector<uint32_t> toBeRemovedIdxes;
+ for (auto& pair : batch->mResultMds) {
+ uint32_t partialIdx = pair.first;
+ if (partialIdx > lastPartialResultIdx) {
+ continue;
+ }
+ toBeRemovedIdxes.push_back(partialIdx);
+ InflightBatch::MetadataBatch& mb = pair.second;
+ for (const auto& p : mb.mMds) {
+ CaptureResult result;
+ result.frameNumber = p.first;
+ result.result = std::move(p.second);
+ result.inputBuffer.streamId = -1;
+ result.inputBuffer.bufferId = 0;
+ result.inputBuffer.buffer = nullptr;
+ result.partialResult = partialIdx;
+ results.push_back(std::move(result));
+ }
+ mb.mMds.clear();
+ }
+ mCallback->processCaptureResult(results);
+ batch->mPartialResultProgress = lastPartialResultIdx;
+ for (uint32_t partialIdx : toBeRemovedIdxes) {
+ batch->mResultMds.erase(partialIdx);
+ }
+}
+
+void CameraDeviceSession::ResultBatcher::notifySingleMsg(NotifyMsg& msg) {
+ mCallback->notify({msg});
+ return;
+}
+
+void CameraDeviceSession::ResultBatcher::notify(NotifyMsg& msg) {
+ uint32_t frameNumber;
+ if (CC_LIKELY(msg.type == MsgType::SHUTTER)) {
+ frameNumber = msg.msg.shutter.frameNumber;
+ } else {
+ frameNumber = msg.msg.error.frameNumber;
+ }
+
+ auto pair = getBatch(frameNumber);
+ int batchIdx = pair.first;
+ if (batchIdx == NOT_BATCHED) {
+ notifySingleMsg(msg);
+ return;
+ }
+
+ // When error happened, stop batching for all batches earlier
+ if (CC_UNLIKELY(msg.type == MsgType::ERROR)) {
+ Mutex::Autolock _l(mLock);
+ for (int i = 0; i <= batchIdx; i++) {
+ // Send batched data up
+ std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
+ {
+ Mutex::Autolock _l(batch->mLock);
+ sendBatchShutterCbsLocked(batch);
+ sendBatchBuffersLocked(batch);
+ sendBatchMetadataLocked(batch, mNumPartialResults);
+ if (!batch->allDelivered()) {
+ ALOGE("%s: error: some batch data not sent back to framework!",
+ __FUNCTION__);
+ }
+ batch->mRemoved = true;
+ }
+ mInflightBatches.pop_front();
+ }
+ // Send the error up
+ notifySingleMsg(msg);
+ return;
+ }
+ // Queue shutter callbacks for future delivery
+ std::shared_ptr<InflightBatch> batch = pair.second;
+ {
+ Mutex::Autolock _l(batch->mLock);
+ // Check if the batch is removed (mostly by notify error) before lock was acquired
+ if (batch->mRemoved) {
+ // Fall back to non-batch path
+ notifySingleMsg(msg);
+ return;
+ }
+
+ batch->mShutterMsgs.push_back(msg);
+ if (frameNumber == batch->mLastFrame) {
+ sendBatchShutterCbsLocked(batch);
+ }
+ } // end of batch lock scope
+
+ // see if the batch is complete
+ if (frameNumber == batch->mLastFrame) {
+ checkAndRemoveFirstBatch();
+ }
+}
+
+void CameraDeviceSession::ResultBatcher::processOneCaptureResult(CaptureResult& result) {
+ hidl_vec<CaptureResult> results = {result};
+ mCallback->processCaptureResult(results);
+ freeReleaseFences(results);
+ return;
+}
+
+void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& result) {
+ auto pair = getBatch(result.frameNumber);
+ int batchIdx = pair.first;
+ if (batchIdx == NOT_BATCHED) {
+ processOneCaptureResult(result);
+ return;
+ }
+ std::shared_ptr<InflightBatch> batch = pair.second;
+ {
+ Mutex::Autolock _l(batch->mLock);
+ // Check if the batch is removed (mostly by notify error) before lock was acquired
+ if (batch->mRemoved) {
+ // Fall back to non-batch path
+ processOneCaptureResult(result);
+ return;
+ }
+
+ // queue metadata
+ if (result.result.size() != 0) {
+ // Save a copy of metadata
+ batch->mResultMds[result.partialResult].mMds.push_back(
+ std::make_pair(result.frameNumber, result.result));
+ }
+
+ // queue buffer
+ std::vector<int> filledStreams;
+ std::vector<StreamBuffer> nonBatchedBuffers;
+ for (auto& buffer : result.outputBuffers) {
+ auto it = batch->mBatchBufs.find(buffer.streamId);
+ if (it != batch->mBatchBufs.end()) {
+ InflightBatch::BufferBatch& bb = it->second;
+ bb.mBuffers.push_back(buffer);
+ filledStreams.push_back(buffer.streamId);
+ } else {
+ nonBatchedBuffers.push_back(buffer);
+ }
+ }
+
+ // send non-batched buffers up
+ if (nonBatchedBuffers.size() > 0 || result.inputBuffer.streamId != -1) {
+ CaptureResult nonBatchedResult;
+ nonBatchedResult.frameNumber = result.frameNumber;
+ nonBatchedResult.outputBuffers = nonBatchedBuffers;
+ nonBatchedResult.inputBuffer = result.inputBuffer;
+ nonBatchedResult.partialResult = 0; // 0 for buffer only results
+ processOneCaptureResult(nonBatchedResult);
+ }
+
+ if (result.frameNumber == batch->mLastFrame) {
+ // Send data up
+ if (result.partialResult > 0) {
+ sendBatchMetadataLocked(batch, result.partialResult);
+ }
+ // send buffer up
+ if (filledStreams.size() > 0) {
+ sendBatchBuffersLocked(batch, filledStreams);
+ }
+ }
+ } // end of batch lock scope
+
+ // see if the batch is complete
+ if (result.frameNumber == batch->mLastFrame) {
+ checkAndRemoveFirstBatch();
+ }
+}
+
// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
Return<void> CameraDeviceSession::constructDefaultRequestSettings(
RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) {
@@ -283,6 +645,16 @@
++it;
}
}
+
+ // Track video streams
+ mVideoStreamIds.clear();
+ for (const auto& stream : requestedConfiguration.streams) {
+ if (stream.streamType == StreamType::OUTPUT &&
+ stream.usage & graphics::allocator::V2_0::ConsumerUsage::VIDEO_ENCODER) {
+ mVideoStreamIds.push_back(stream.id);
+ }
+ }
+ mResultBatcher.setBatchedStreams(mVideoStreamIds);
}
if (ret == -EINVAL) {
@@ -306,7 +678,26 @@
mCirculatingBuffers.erase(id);
}
-Return<Status> CameraDeviceSession::processCaptureRequest(const CaptureRequest& request) {
+Return<void> CameraDeviceSession::processCaptureRequest(
+ const hidl_vec<CaptureRequest>& requests, processCaptureRequest_cb _hidl_cb) {
+ uint32_t numRequestProcessed = 0;
+ Status s = Status::OK;
+ for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
+ s = processOneCaptureRequest(requests[i]);
+ if (s != Status::OK) {
+ break;
+ }
+ }
+
+ if (s == Status::OK && requests.size() > 1) {
+ mResultBatcher.registerBatch(requests);
+ }
+
+ _hidl_cb(s, numRequestProcessed);
+ return Void();
+}
+
+Status CameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request) {
Status status = initStatus();
if (status != Status::OK) {
ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
@@ -437,7 +828,7 @@
bool hasInputBuf = (hal_result->input_buffer != nullptr);
size_t numOutputBufs = hal_result->num_output_buffers;
size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
- {
+ if (numBufs > 0) {
Mutex::Autolock _l(d->mInflightLock);
if (hasInputBuf) {
int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
@@ -463,10 +854,7 @@
}
// We don't need to validate/import fences here since we will be passing them to camera service
// within the scope of this function
-
CaptureResult result;
- hidl_vec<native_handle_t*> releaseFences;
- releaseFences.resize(numBufs);
result.frameNumber = frameNumber;
result.partialResult = hal_result->partial_result;
convertToHidl(hal_result->result, &result.result);
@@ -477,11 +865,11 @@
result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
// skip acquire fence since it's no use to camera service
if (hal_result->input_buffer->release_fence != -1) {
- releaseFences[numOutputBufs] = native_handle_create(/*numFds*/1, /*numInts*/0);
- releaseFences[numOutputBufs]->data[0] = hal_result->input_buffer->release_fence;
- result.inputBuffer.releaseFence = releaseFences[numOutputBufs];
+ native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
+ handle->data[0] = hal_result->input_buffer->release_fence;
+ result.inputBuffer.releaseFence = handle;
} else {
- releaseFences[numOutputBufs] = nullptr;
+ result.inputBuffer.releaseFence = nullptr;
}
} else {
result.inputBuffer.streamId = -1;
@@ -495,11 +883,11 @@
result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
// skip acquire fence since it's of no use to camera service
if (hal_result->output_buffers[i].release_fence != -1) {
- releaseFences[i] = native_handle_create(/*numFds*/1, /*numInts*/0);
- releaseFences[i]->data[0] = hal_result->output_buffers[i].release_fence;
- result.outputBuffers[i].releaseFence = releaseFences[i];
+ native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
+ handle->data[0] = hal_result->output_buffers[i].release_fence;
+ result.outputBuffers[i].releaseFence = handle;
} else {
- releaseFences[i] = nullptr;
+ result.outputBuffers[i].releaseFence = nullptr;
}
}
@@ -507,21 +895,17 @@
// Do this before call back to camera service because camera service might jump to
// configure_streams right after the processCaptureResult call so we need to finish
// updating inflight queues first
- {
+ if (numBufs > 0) {
Mutex::Autolock _l(d->mInflightLock);
if (hasInputBuf) {
int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
auto key = std::make_pair(streamId, frameNumber);
- // TODO (b/34169301): currently HAL closed the fence
- //sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
d->mInflightBuffers.erase(key);
}
for (size_t i = 0; i < numOutputBufs; i++) {
int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
auto key = std::make_pair(streamId, frameNumber);
- // TODO (b/34169301): currently HAL closed the fence
- //sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
d->mInflightBuffers.erase(key);
}
@@ -530,12 +914,7 @@
}
}
- d->mCallback->processCaptureResult(result);
-
- for (size_t i = 0; i < releaseFences.size(); i++) {
- // We don't close the FD here as HAL needs to signal it later.
- native_handle_delete(releaseFences[i]);
- }
+ d->mResultBatcher.processCaptureResult(result);
}
void CameraDeviceSession::sNotify(
@@ -545,15 +924,16 @@
const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
NotifyMsg hidlMsg;
convertToHidl(msg, &hidlMsg);
+
if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
hidlMsg.msg.error.errorStreamId != -1) {
if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
ALOGE("%s: unknown stream ID %d reports an error!",
__FUNCTION__, hidlMsg.msg.error.errorStreamId);
+ return;
}
- return;
}
- d->mCallback->notify(hidlMsg);
+ d->mResultBatcher.notify(hidlMsg);
}
} // namespace implementation
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index 3786e4b..8923c05 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE3SESSION_H
#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE3SESSION_H
+#include <deque>
+#include <map>
#include <unordered_map>
#include "hardware/camera_common.h"
#include "hardware/camera3.h"
@@ -27,6 +29,7 @@
#include <hidl/MQDescriptor.h>
#include <include/convert.h>
#include "HandleImporter.h"
+#include "CameraMetadata.h"
namespace android {
namespace hardware {
@@ -64,7 +67,9 @@
struct CameraDeviceSession : public ICameraDeviceSession, private camera3_callback_ops {
- CameraDeviceSession(camera3_device_t*, const sp<ICameraDeviceCallback>&);
+ CameraDeviceSession(camera3_device_t*,
+ const camera_metadata_t* deviceInfo,
+ const sp<ICameraDeviceCallback>&);
~CameraDeviceSession();
// Call by CameraDevice to dump active device states
void dumpState(const native_handle_t* fd);
@@ -75,9 +80,12 @@
bool isClosed();
// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
- Return<void> constructDefaultRequestSettings(RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) override;
- Return<void> configureStreams(const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) override;
- Return<Status> processCaptureRequest(const CaptureRequest& request) override;
+ Return<void> constructDefaultRequestSettings(
+ RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) override;
+ Return<void> configureStreams(
+ const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) override;
+ Return<void> processCaptureRequest(
+ const hidl_vec<CaptureRequest>& requests, processCaptureRequest_cb _hidl_cb) override;
Return<Status> flush() override;
Return<void> close() override;
@@ -94,7 +102,6 @@
bool mDisconnected = false;
camera3_device_t* mDevice;
- const sp<ICameraDeviceCallback> mCallback;
// Stream ID -> Camera3Stream cache
std::map<int, Camera3Stream> mStreamMap;
@@ -114,6 +121,104 @@
static HandleImporter& sHandleImporter;
bool mInitFail;
+
+ common::V1_0::helper::CameraMetadata mDeviceInfo;
+
+ class ResultBatcher {
+ public:
+ ResultBatcher(const sp<ICameraDeviceCallback>& callback);
+ void setNumPartialResults(uint32_t n);
+ void setBatchedStreams(const std::vector<int>& streamsToBatch);
+
+ void registerBatch(const hidl_vec<CaptureRequest>& requests);
+ void notify(NotifyMsg& msg);
+ void processCaptureResult(CaptureResult& result);
+
+ private:
+ struct InflightBatch {
+ // Protect access to entire struct. Acquire this lock before read/write any data or
+ // calling any methods. processCaptureResult and notify will compete for this lock
+ // HIDL IPCs might be issued while the lock is held
+ Mutex mLock;
+
+ bool allDelivered() const;
+
+ uint32_t mFirstFrame;
+ uint32_t mLastFrame;
+ uint32_t mBatchSize;
+
+ bool mShutterDelivered = false;
+ std::vector<NotifyMsg> mShutterMsgs;
+
+ struct BufferBatch {
+ bool mDelivered = false;
+ // This currently assumes every batched request will output to the batched stream
+ // and since HAL must always send buffers in order, no frameNumber tracking is
+ // needed
+ std::vector<StreamBuffer> mBuffers;
+ };
+ // Stream ID -> VideoBatch
+ std::unordered_map<int, BufferBatch> mBatchBufs;
+
+ struct MetadataBatch {
+ // (frameNumber, metadata)
+ std::vector<std::pair<uint32_t, CameraMetadata>> mMds;
+ };
+ // Partial result IDs that has been delivered to framework
+ uint32_t mNumPartialResults;
+ uint32_t mPartialResultProgress = 0;
+ // partialResult -> MetadataBatch
+ std::map<uint32_t, MetadataBatch> mResultMds;
+
+ // Set to true when batch is removed from mInflightBatches
+ // processCaptureResult and notify must check this flag after acquiring mLock to make
+ // sure this batch isn't removed while waiting for mLock
+ bool mRemoved = false;
+ };
+
+ static const int NOT_BATCHED = -1;
+
+ // Get the batch index and pointer to InflightBatch (nullptrt if the frame is not batched)
+ // Caller must acquire the InflightBatch::mLock before accessing the InflightBatch
+ // It's possible that the InflightBatch is removed from mInflightBatches before the
+ // InflightBatch::mLock is acquired (most likely caused by an error notification), so
+ // caller must check InflightBatch::mRemoved flag after the lock is acquried.
+ // This method will hold ResultBatcher::mLock briefly
+ std::pair<int, std::shared_ptr<InflightBatch>> getBatch(uint32_t frameNumber);
+
+ // Check if the first batch in mInflightBatches is ready to be removed, and remove it if so
+ // This method will hold ResultBatcher::mLock briefly
+ void checkAndRemoveFirstBatch();
+
+ // The following sendXXXX methods must be called while the InflightBatch::mLock is locked
+ // HIDL IPC methods will be called during these methods.
+ void sendBatchShutterCbsLocked(std::shared_ptr<InflightBatch> batch);
+ // send buffers for all batched streams
+ void sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch);
+ // send buffers for specified streams
+ void sendBatchBuffersLocked(
+ std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams);
+ void sendBatchMetadataLocked(
+ std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx);
+ // End of sendXXXX methods
+
+ // helper methods
+ void freeReleaseFences(hidl_vec<CaptureResult>&);
+ void notifySingleMsg(NotifyMsg& msg);
+ void processOneCaptureResult(CaptureResult& result);
+
+ // Protect access to mInflightBatches, mNumPartialResults and mStreamsToBatch
+ // processCaptureRequest, processCaptureResult, notify will compete for this lock
+ // Do NOT issue HIDL IPCs while holding this lock (except when HAL reports error)
+ mutable Mutex mLock;
+ std::deque<std::shared_ptr<InflightBatch>> mInflightBatches;
+ uint32_t mNumPartialResults;
+ std::vector<int> mStreamsToBatch;
+ const sp<ICameraDeviceCallback> mCallback;
+ } mResultBatcher;
+
+ std::vector<int> mVideoStreamIds;
+
bool initialize();
Status initStatus() const;
@@ -129,6 +234,7 @@
void cleanupBuffersLocked(int id);
+ Status processOneCaptureRequest(const CaptureRequest& request);
/**
* Static callback forwarding methods from HAL to instance
*/
diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp
index 3369a3c..1656325 100644
--- a/camera/provider/2.4/Android.bp
+++ b/camera/provider/2.4/Android.bp
@@ -57,6 +57,8 @@
"android.hardware.camera.common@1.0",
"android.hardware.camera.device@1.0",
"android.hardware.camera.device@3.2",
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.common@1.0",
"android.hidl.base@1.0",
],
export_shared_lib_headers: [
@@ -67,6 +69,8 @@
"android.hardware.camera.common@1.0",
"android.hardware.camera.device@1.0",
"android.hardware.camera.device@3.2",
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.common@1.0",
"android.hidl.base@1.0",
],
}
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 598127f..a79c9fa 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -445,13 +445,13 @@
hidl_vec<hidl_string> getCameraDeviceNames();
struct EmptyDeviceCb : public ICameraDeviceCallback {
- virtual Return<void> processCaptureResult(const CaptureResult& /*result*/) override {
+ virtual Return<void> processCaptureResult(const hidl_vec<CaptureResult>& /*results*/) override {
ALOGI("processCaptureResult callback");
ADD_FAILURE(); // Empty callback should not reach here
return Void();
}
- virtual Return<void> notify(const NotifyMsg& /*msg*/) override {
+ virtual Return<void> notify(const hidl_vec<NotifyMsg>& /*msgs*/) override {
ALOGI("notify callback");
ADD_FAILURE(); // Empty callback should not reach here
return Void();
@@ -460,8 +460,8 @@
struct DeviceCb : public ICameraDeviceCallback {
DeviceCb(CameraHidlTest *parent) : mParent(parent) {}
- Return<void> processCaptureResult(const CaptureResult& result) override;
- Return<void> notify(const NotifyMsg& msg) override;
+ Return<void> processCaptureResult(const hidl_vec<CaptureResult>& results) override;
+ Return<void> notify(const hidl_vec<NotifyMsg>& msgs) override;
private:
CameraHidlTest *mParent; // Parent object
@@ -667,12 +667,13 @@
}
Return<void> CameraHidlTest::DeviceCb::processCaptureResult(
- const CaptureResult& result) {
+ const hidl_vec<CaptureResult>& results) {
if (nullptr == mParent) {
return Void();
}
std::unique_lock<std::mutex> l(mParent->mLock);
+ const CaptureResult& result = results[0];
if(mParent->mResultFrameNumber != result.frameNumber) {
ALOGE("%s: Unexpected frame number! Expected: %u received: %u",
@@ -695,7 +696,8 @@
}
Return<void> CameraHidlTest::DeviceCb::notify(
- const NotifyMsg& message) {
+ const hidl_vec<NotifyMsg>& messages) {
+ const NotifyMsg& message = messages[0];
if (MsgType::ERROR == message.type) {
{
@@ -2477,10 +2479,17 @@
mResultFrameNumber = frameNumber;
}
- Return<Status> returnStatus = session->processCaptureRequest(
- request);
+ Status status = Status::INTERNAL_ERROR;
+ uint32_t numRequestProcessed = 0;
+ Return<void> returnStatus = session->processCaptureRequest(
+ {request},
+ [&status, &numRequestProcessed] (auto s, uint32_t n) {
+ status = s;
+ numRequestProcessed = n;
+ });
ASSERT_TRUE(returnStatus.isOk());
- ASSERT_EQ(Status::OK, returnStatus);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_EQ(numRequestProcessed, 1u);
{
std::unique_lock<std::mutex> l(mLock);
@@ -2503,9 +2512,14 @@
}
returnStatus = session->processCaptureRequest(
- request);
+ {request},
+ [&status, &numRequestProcessed] (auto s, uint32_t n) {
+ status = s;
+ numRequestProcessed = n;
+ });
ASSERT_TRUE(returnStatus.isOk());
- ASSERT_EQ(Status::OK, returnStatus);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_EQ(numRequestProcessed, 1u);
{
std::unique_lock<std::mutex> l(mLock);
@@ -2563,12 +2577,19 @@
emptyInputBuffer, outputBuffers};
//Settings were not correctly initialized, we should fail here
- Return<Status> returnStatus = session->processCaptureRequest(
- request);
- ASSERT_TRUE(returnStatus.isOk());
- ASSERT_EQ(Status::INTERNAL_ERROR, returnStatus);
+ Status status = Status::OK;
+ uint32_t numRequestProcessed = 0;
+ Return<void> ret = session->processCaptureRequest(
+ {request},
+ [&status, &numRequestProcessed] (auto s, uint32_t n) {
+ status = s;
+ numRequestProcessed = n;
+ });
+ ASSERT_TRUE(ret.isOk());
+ ASSERT_EQ(Status::INTERNAL_ERROR, status);
+ ASSERT_EQ(numRequestProcessed, 0u);
- Return<void> ret = session->close();
+ ret = session->close();
ASSERT_TRUE(ret.isOk());
}
}
@@ -2609,11 +2630,17 @@
emptyInputBuffer, emptyOutputBuffers};
//Output buffers are missing, we should fail here
- Return<Status> returnStatus = session->processCaptureRequest(
- request);
- ASSERT_TRUE(returnStatus.isOk());
- ASSERT_EQ(Status::INTERNAL_ERROR,
- returnStatus);
+ Status status = Status::OK;
+ uint32_t numRequestProcessed = 0;
+ ret = session->processCaptureRequest(
+ {request},
+ [&status, &numRequestProcessed] (auto s, uint32_t n) {
+ status = s;
+ numRequestProcessed = n;
+ });
+ ASSERT_TRUE(ret.isOk());
+ ASSERT_EQ(Status::INTERNAL_ERROR, status);
+ ASSERT_EQ(numRequestProcessed, 0u);
ret = session->close();
ASSERT_TRUE(ret.isOk());
@@ -2672,12 +2699,20 @@
mResultFrameNumber = frameNumber;
}
- Return<Status> returnStatus = session->processCaptureRequest(
- request);
- ASSERT_TRUE(returnStatus.isOk());
- ASSERT_EQ(Status::OK, returnStatus);
+ Status status = Status::INTERNAL_ERROR;
+ uint32_t numRequestProcessed = 0;
+ ret = session->processCaptureRequest(
+ {request},
+ [&status, &numRequestProcessed] (auto s, uint32_t n) {
+ status = s;
+ numRequestProcessed = n;
+ });
+
+ ASSERT_TRUE(ret.isOk());
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_EQ(numRequestProcessed, 1u);
//Flush before waiting for request to complete.
- returnStatus = session->flush();
+ Return<Status> returnStatus = session->flush();
ASSERT_TRUE(returnStatus.isOk());
ASSERT_EQ(Status::OK, returnStatus);
diff --git a/configstore/1.0/default/service.cpp b/configstore/1.0/default/service.cpp
index caec0ba..cb04215 100644
--- a/configstore/1.0/default/service.cpp
+++ b/configstore/1.0/default/service.cpp
@@ -24,10 +24,18 @@
using android::hardware::registerPassthroughServiceImplementation;
using android::hardware::joinRpcThreadpool;
+using android::status_t;
+using android::OK;
+
int main() {
// TODO(b/34857894): tune the max thread count.
configureRpcThreadpool(10, true);
- registerPassthroughServiceImplementation<ISurfaceFlingerConfigs>();
+
+ status_t status;
+
+ status = registerPassthroughServiceImplementation<ISurfaceFlingerConfigs>();
+ LOG_ALWAYS_FATAL_IF(status != OK, "Could not register ISurfaceFlingerConfigs");
+
// other interface registration comes here
joinRpcThreadpool();
return 0;
diff --git a/tests/Android.bp b/tests/Android.bp
index 6606d94..31dc75e 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -23,4 +23,5 @@
"versioning/1.0",
"versioning/2.2",
"versioning/2.3",
+ "versioning/2.4",
]
diff --git a/tests/extension/light/2.0/Android.bp b/tests/extension/light/2.0/Android.bp
index 5203da6..123bea1 100644
--- a/tests/extension/light/2.0/Android.bp
+++ b/tests/extension/light/2.0/Android.bp
@@ -51,6 +51,7 @@
"libutils",
"libcutils",
"android.hardware.light@2.0",
+ "android.hidl.base@1.0",
],
export_shared_lib_headers: [
"libhidlbase",
@@ -58,5 +59,6 @@
"libhwbinder",
"libutils",
"android.hardware.light@2.0",
+ "android.hidl.base@1.0",
],
}
diff --git a/tests/versioning/2.3/Android.bp b/tests/versioning/2.3/Android.bp
index 122c484..3cc2076 100644
--- a/tests/versioning/2.3/Android.bp
+++ b/tests/versioning/2.3/Android.bp
@@ -63,6 +63,7 @@
"libcutils",
"android.hardware.tests.versioning@1.0",
"android.hardware.tests.versioning@2.2",
+ "android.hidl.base@1.0",
],
export_shared_lib_headers: [
"libhidlbase",
@@ -71,5 +72,6 @@
"libutils",
"android.hardware.tests.versioning@1.0",
"android.hardware.tests.versioning@2.2",
+ "android.hidl.base@1.0",
],
}
diff --git a/tests/versioning/2.4/Android.bp b/tests/versioning/2.4/Android.bp
new file mode 100644
index 0000000..9d8303c
--- /dev/null
+++ b/tests/versioning/2.4/Android.bp
@@ -0,0 +1,63 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+ name: "android.hardware.tests.versioning@2.4_hal",
+ srcs: [
+ "IFoo.hal",
+ ],
+}
+
+genrule {
+ name: "android.hardware.tests.versioning@2.4_genc++",
+ tools: ["hidl-gen"],
+ cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.versioning@2.4",
+ srcs: [
+ ":android.hardware.tests.versioning@2.4_hal",
+ ],
+ out: [
+ "android/hardware/tests/versioning/2.4/FooAll.cpp",
+ ],
+}
+
+genrule {
+ name: "android.hardware.tests.versioning@2.4_genc++_headers",
+ tools: ["hidl-gen"],
+ cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.versioning@2.4",
+ srcs: [
+ ":android.hardware.tests.versioning@2.4_hal",
+ ],
+ out: [
+ "android/hardware/tests/versioning/2.4/IFoo.h",
+ "android/hardware/tests/versioning/2.4/IHwFoo.h",
+ "android/hardware/tests/versioning/2.4/BnHwFoo.h",
+ "android/hardware/tests/versioning/2.4/BpHwFoo.h",
+ "android/hardware/tests/versioning/2.4/BsFoo.h",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.tests.versioning@2.4",
+ generated_sources: ["android.hardware.tests.versioning@2.4_genc++"],
+ generated_headers: ["android.hardware.tests.versioning@2.4_genc++_headers"],
+ export_generated_headers: ["android.hardware.tests.versioning@2.4_genc++_headers"],
+ shared_libs: [
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "liblog",
+ "libutils",
+ "libcutils",
+ "android.hardware.tests.versioning@2.2",
+ "android.hardware.tests.versioning@2.3",
+ "android.hidl.base@1.0",
+ ],
+ export_shared_lib_headers: [
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "libutils",
+ "android.hardware.tests.versioning@2.2",
+ "android.hardware.tests.versioning@2.3",
+ "android.hidl.base@1.0",
+ ],
+}
diff --git a/tests/versioning/2.4/Android.mk b/tests/versioning/2.4/Android.mk
new file mode 100644
index 0000000..e41397f
--- /dev/null
+++ b/tests/versioning/2.4/Android.mk
@@ -0,0 +1,80 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tests.versioning@2.4-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+ android.hardware.tests.versioning@2.2-java \
+ android.hardware.tests.versioning@2.3-java \
+ android.hidl.base@1.0-java \
+
+
+#
+# Build IFoo.hal
+#
+GEN := $(intermediates)/android/hardware/tests/versioning/V2_4/IFoo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IFoo.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.tests.versioning@2.4::IFoo
+
+$(GEN): $(LOCAL_PATH)/IFoo.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tests.versioning@2.4-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android.hardware.tests.versioning@2.2-java-static \
+ android.hardware.tests.versioning@2.3-java-static \
+ android.hidl.base@1.0-java-static \
+
+
+#
+# Build IFoo.hal
+#
+GEN := $(intermediates)/android/hardware/tests/versioning/V2_4/IFoo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IFoo.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.tests.versioning@2.4::IFoo
+
+$(GEN): $(LOCAL_PATH)/IFoo.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/versioning/2.4/IFoo.hal b/tests/versioning/2.4/IFoo.hal
new file mode 100644
index 0000000..358b56f
--- /dev/null
+++ b/tests/versioning/2.4/IFoo.hal
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.hardware.tests.versioning@2.4;
+
+import @2.3::IFoo;
+
+// Must extend @2.3::IFoo.
+interface IFoo extends @2.3::IFoo {
+
+};
diff --git a/usb/1.0/default/service.cpp b/usb/1.0/default/service.cpp
index b4db241..4605a4c 100644
--- a/usb/1.0/default/service.cpp
+++ b/usb/1.0/default/service.cpp
@@ -28,12 +28,11 @@
using android::hardware::usb::V1_0::implementation::Usb;
int main() {
- const char instance[] = "usb_hal";
android::sp<IUsb> service = new Usb();
configureRpcThreadpool(1, true /*callerWillJoin*/);
- service->registerAsService(instance);
+ service->registerAsService();
ALOGI("USB HAL Ready.");
joinRpcThreadpool();
diff --git a/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp b/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
index 54db8c2..ea6d4a9 100644
--- a/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
+++ b/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
@@ -47,8 +47,6 @@
using ::android::hardware::Void;
using ::android::sp;
-#define USB_SERVICE_NAME "usb_hal"
-
// The main test class for the USB hidl HAL
class UsbHidlTest : public ::testing::VtsHalHidlTargetTestBase {
public:
@@ -97,7 +95,7 @@
virtual void SetUp() override {
ALOGI("Setup");
- usb = ::testing::VtsHalHidlTargetTestBase::getService<IUsb>(USB_SERVICE_NAME);
+ usb = ::testing::VtsHalHidlTargetTestBase::getService<IUsb>();
ASSERT_NE(usb, nullptr);
usb_cb_2 = new UsbCallback(*this, 2);