Merge "HIDL changes to support Stadium Wifi."
diff --git a/automotive/audiocontrol/1.0/default/android.hardware.automotive.audiocontrol@1.0-service.rc b/automotive/audiocontrol/1.0/default/android.hardware.automotive.audiocontrol@1.0-service.rc
index 79edad6..c02db08 100644
--- a/automotive/audiocontrol/1.0/default/android.hardware.automotive.audiocontrol@1.0-service.rc
+++ b/automotive/audiocontrol/1.0/default/android.hardware.automotive.audiocontrol@1.0-service.rc
@@ -1,4 +1,4 @@
-service vendor.evs-hal-mock /vendor/bin/hw/android.hardware.automotive.audiocontrol@1.0-service
+service vendor.audiocontrol-hal-1.0 /vendor/bin/hw/android.hardware.automotive.audiocontrol@1.0-service
class hal
user audioserver
group system
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
index fca8e9e..bf7be09 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
@@ -138,6 +138,7 @@
VehiclePropValue val = {
.prop = protoVal.prop(),
.areaId = protoVal.area_id(),
+ .status = (VehiclePropertyStatus)protoVal.status(),
.timestamp = elapsedRealtimeNano(),
};
@@ -288,6 +289,7 @@
protoVal->set_prop(val->prop);
protoVal->set_value_type(toInt(getPropType(val->prop)));
protoVal->set_timestamp(val->timestamp);
+ protoVal->set_status((emulator::VehiclePropStatus)(val->status));
protoVal->set_area_id(val->areaId);
// Copy value data if it is set.
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
index 86433f5..2ef64fb 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
@@ -46,6 +46,12 @@
ERROR_INVALID_OPERATION = 8;
}
+enum VehiclePropStatus {
+ AVAILABLE = 0;
+ UNAVAILABLE = 1;
+ ERROR = 2;
+}
+
message VehicleAreaConfig {
required int32 area_id = 1;
optional sint32 min_int32_value = 2;
@@ -61,7 +67,7 @@
optional int32 access = 2;
optional int32 change_mode = 3;
optional int32 value_type = 4;
- optional int32 supported_areas = 5;
+ optional int32 supported_areas = 5; // Deprecated - DO NOT USE
repeated VehicleAreaConfig area_configs = 6;
optional int32 config_flags = 7;
repeated int32 config_array = 8;
@@ -75,6 +81,7 @@
required int32 prop = 1;
optional int32 value_type = 2;
optional int64 timestamp = 3; // required for valid data from HAL, skipped for set
+ optional VehiclePropStatus status = 10; // required for valid data from HAL, skipped for set
// values
optional int32 area_id = 4;
diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp
index e9741ef..21706a8 100644
--- a/camera/common/1.0/default/HandleImporter.cpp
+++ b/camera/common/1.0/default/HandleImporter.cpp
@@ -134,6 +134,38 @@
}
}
+void* HandleImporter::lock(
+ buffer_handle_t& buf, uint64_t cpuUsage, size_t size) {
+ Mutex::Autolock lock(mLock);
+ void *ret = 0;
+ IMapper::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
+
+ if (!mInitialized) {
+ initializeLocked();
+ }
+
+ if (mMapper == nullptr) {
+ ALOGE("%s: mMapper is null!", __FUNCTION__);
+ return ret;
+ }
+
+ hidl_handle acquireFenceHandle;
+ auto buffer = const_cast<native_handle_t*>(buf);
+ mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+ [&](const auto& tmpError, const auto& tmpPtr) {
+ if (tmpError == MapperError::NONE) {
+ ret = tmpPtr;
+ } else {
+ ALOGE("%s: failed to lock error %d!",
+ __FUNCTION__, tmpError);
+ }
+ });
+
+ ALOGV("%s: ptr %p size: %zu", __FUNCTION__, ret, size);
+ return ret;
+}
+
+
YCbCrLayout HandleImporter::lockYCbCr(
buffer_handle_t& buf, uint64_t cpuUsage,
const IMapper::Rect& accessRegion) {
diff --git a/camera/common/1.0/default/include/HandleImporter.h b/camera/common/1.0/default/include/HandleImporter.h
index 443362d..f9cd9fb 100644
--- a/camera/common/1.0/default/include/HandleImporter.h
+++ b/camera/common/1.0/default/include/HandleImporter.h
@@ -45,6 +45,9 @@
void closeFence(int fd) const;
// Assume caller has done waiting for acquire fences
+ void* lock(buffer_handle_t& buf, uint64_t cpuUsage, size_t size);
+
+ // Assume caller has done waiting for acquire fences
YCbCrLayout lockYCbCr(buffer_handle_t& buf, uint64_t cpuUsage,
const IMapper::Rect& accessRegion);
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index ae275ae..975fb01 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -1198,26 +1198,19 @@
return Void();
}
-/**
- * Static callback forwarding methods from HAL to instance
- */
-void CameraDeviceSession::sProcessCaptureResult(
- const camera3_callback_ops *cb,
- const camera3_capture_result *hal_result) {
- CameraDeviceSession *d =
- const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
-
+void CameraDeviceSession::constructCaptureResult(CaptureResult& result,
+ const camera3_capture_result *hal_result) {
uint32_t frameNumber = hal_result->frame_number;
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);
+ Mutex::Autolock _l(mInflightLock);
if (hasInputBuf) {
int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
// validate if buffer is inflight
auto key = std::make_pair(streamId, frameNumber);
- if (d->mInflightBuffers.count(key) != 1) {
+ if (mInflightBuffers.count(key) != 1) {
ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
__FUNCTION__, streamId, frameNumber);
return;
@@ -1228,7 +1221,7 @@
int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
// validate if buffer is inflight
auto key = std::make_pair(streamId, frameNumber);
- if (d->mInflightBuffers.count(key) != 1) {
+ if (mInflightBuffers.count(key) != 1) {
ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
__FUNCTION__, streamId, frameNumber);
return;
@@ -1237,64 +1230,63 @@
}
// 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;
result.frameNumber = frameNumber;
result.fmqResultSize = 0;
result.partialResult = hal_result->partial_result;
convertToHidl(hal_result->result, &result.result);
if (nullptr != hal_result->result) {
bool resultOverriden = false;
- Mutex::Autolock _l(d->mInflightLock);
+ Mutex::Autolock _l(mInflightLock);
// Derive some new keys for backward compatibility
- if (d->mDerivePostRawSensKey) {
+ if (mDerivePostRawSensKey) {
camera_metadata_ro_entry entry;
if (find_camera_metadata_ro_entry(hal_result->result,
ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST, &entry) == 0) {
- d->mInflightRawBoostPresent[frameNumber] = true;
+ mInflightRawBoostPresent[frameNumber] = true;
} else {
- auto entry = d->mInflightRawBoostPresent.find(frameNumber);
- if (d->mInflightRawBoostPresent.end() == entry) {
- d->mInflightRawBoostPresent[frameNumber] = false;
+ auto entry = mInflightRawBoostPresent.find(frameNumber);
+ if (mInflightRawBoostPresent.end() == entry) {
+ mInflightRawBoostPresent[frameNumber] = false;
}
}
- if ((hal_result->partial_result == d->mNumPartialResults)) {
- if (!d->mInflightRawBoostPresent[frameNumber]) {
+ if ((hal_result->partial_result == mNumPartialResults)) {
+ if (!mInflightRawBoostPresent[frameNumber]) {
if (!resultOverriden) {
- d->mOverridenResult.clear();
- d->mOverridenResult.append(hal_result->result);
+ mOverridenResult.clear();
+ mOverridenResult.append(hal_result->result);
resultOverriden = true;
}
int32_t defaultBoost[1] = {100};
- d->mOverridenResult.update(
+ mOverridenResult.update(
ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
defaultBoost, 1);
}
- d->mInflightRawBoostPresent.erase(frameNumber);
+ mInflightRawBoostPresent.erase(frameNumber);
}
}
- auto entry = d->mInflightAETriggerOverrides.find(frameNumber);
- if (d->mInflightAETriggerOverrides.end() != entry) {
+ auto entry = mInflightAETriggerOverrides.find(frameNumber);
+ if (mInflightAETriggerOverrides.end() != entry) {
if (!resultOverriden) {
- d->mOverridenResult.clear();
- d->mOverridenResult.append(hal_result->result);
+ mOverridenResult.clear();
+ mOverridenResult.append(hal_result->result);
resultOverriden = true;
}
- d->overrideResultForPrecaptureCancelLocked(entry->second,
- &d->mOverridenResult);
- if (hal_result->partial_result == d->mNumPartialResults) {
- d->mInflightAETriggerOverrides.erase(frameNumber);
+ overrideResultForPrecaptureCancelLocked(entry->second,
+ &mOverridenResult);
+ if (hal_result->partial_result == mNumPartialResults) {
+ mInflightAETriggerOverrides.erase(frameNumber);
}
}
if (resultOverriden) {
const camera_metadata_t *metaBuffer =
- d->mOverridenResult.getAndLock();
+ mOverridenResult.getAndLock();
convertToHidl(metaBuffer, &result.result);
- d->mOverridenResult.unlock(metaBuffer);
+ mOverridenResult.unlock(metaBuffer);
}
}
if (hasInputBuf) {
@@ -1335,24 +1327,38 @@
// configure_streams right after the processCaptureResult call so we need to finish
// updating inflight queues first
if (numBufs > 0) {
- Mutex::Autolock _l(d->mInflightLock);
+ Mutex::Autolock _l(mInflightLock);
if (hasInputBuf) {
int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
auto key = std::make_pair(streamId, frameNumber);
- d->mInflightBuffers.erase(key);
+ 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);
- d->mInflightBuffers.erase(key);
+ mInflightBuffers.erase(key);
}
- if (d->mInflightBuffers.empty()) {
+ if (mInflightBuffers.empty()) {
ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
}
}
+}
+
+/**
+ * Static callback forwarding methods from HAL to instance
+ */
+void CameraDeviceSession::sProcessCaptureResult(
+ const camera3_callback_ops *cb,
+ const camera3_capture_result *hal_result) {
+ CameraDeviceSession *d =
+ const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
+
+ CaptureResult result;
+ d->constructCaptureResult(result, hal_result);
+
d->mResultBatcher.processCaptureResult(result);
}
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index dd73b39..61db671 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -190,7 +190,7 @@
void notify(NotifyMsg& msg);
void processCaptureResult(CaptureResult& result);
- private:
+ protected:
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
@@ -235,7 +235,6 @@
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
@@ -245,6 +244,16 @@
// This method will hold ResultBatcher::mLock briefly
std::pair<int, std::shared_ptr<InflightBatch>> getBatch(uint32_t frameNumber);
+ static const int NOT_BATCHED = -1;
+
+ // move/push function avoids "hidl_handle& operator=(hidl_handle&)", which clones native
+ // handle
+ void moveStreamBuffer(StreamBuffer&& src, StreamBuffer& dst);
+ void pushStreamBuffer(StreamBuffer&& src, std::vector<StreamBuffer>& dst);
+
+ void sendBatchMetadataLocked(
+ std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx);
+
// 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();
@@ -257,9 +266,7 @@
// 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
+ // End of sendXXXX methods
// helper methods
void freeReleaseFences(hidl_vec<CaptureResult>&);
@@ -267,11 +274,6 @@
void processOneCaptureResult(CaptureResult& result);
void invokeProcessCaptureResultCallback(hidl_vec<CaptureResult> &results, bool tryWriteFmq);
- // move/push function avoids "hidl_handle& operator=(hidl_handle&)", which clones native
- // handle
- void moveStreamBuffer(StreamBuffer&& src, StreamBuffer& dst);
- void pushStreamBuffer(StreamBuffer&& src, std::vector<StreamBuffer>& dst);
-
// 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)
@@ -325,6 +327,8 @@
static callbacks_process_capture_result_t sProcessCaptureResult;
static callbacks_notify_t sNotify;
+ void constructCaptureResult(CaptureResult& result,
+ const camera3_capture_result *hal_result);
private:
struct TrampolineSessionInterface_3_2 : public ICameraDeviceSession {
diff --git a/camera/device/3.4/Android.bp b/camera/device/3.4/Android.bp
index b3757c0..87acd25 100644
--- a/camera/device/3.4/Android.bp
+++ b/camera/device/3.4/Android.bp
@@ -8,6 +8,7 @@
},
srcs: [
"types.hal",
+ "ICameraDeviceCallback.hal",
"ICameraDeviceSession.hal",
],
interfaces: [
@@ -19,8 +20,10 @@
],
types: [
"CaptureRequest",
+ "CaptureResult",
"HalStream",
"HalStreamConfiguration",
+ "PhysicalCameraMetadata",
"PhysicalCameraSetting",
"RequestTemplate",
"Stream",
diff --git a/camera/device/3.4/ICameraDeviceCallback.hal b/camera/device/3.4/ICameraDeviceCallback.hal
new file mode 100644
index 0000000..8ce8d4b
--- /dev/null
+++ b/camera/device/3.4/ICameraDeviceCallback.hal
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.device@3.4;
+
+import @3.2::ICameraDeviceCallback;
+
+/**
+ *
+ * Callback methods for the HAL to call into the framework.
+ *
+ * These methods are used to return metadata and image buffers for a completed
+ * or failed captures, and to notify the framework of asynchronous events such
+ * as errors.
+ *
+ * The framework must not call back into the HAL from within these callbacks,
+ * and these calls must not block for extended periods.
+ *
+ */
+interface ICameraDeviceCallback extends @3.2::ICameraDeviceCallback {
+ /**
+ * processCaptureResult_3_4:
+ *
+ * Identical to @3.2::ICameraDeviceCallback.processCaptureResult, except
+ * that it takes a list of @3.4::CaptureResult, which could contain
+ * physical camera metadata for logical multi-camera.
+ *
+ */
+ processCaptureResult_3_4(vec<@3.4::CaptureResult> results);
+};
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index d054788..f6c6b2b 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -34,7 +34,23 @@
camera3_device_t* device,
const camera_metadata_t* deviceInfo,
const sp<V3_2::ICameraDeviceCallback>& callback) :
- V3_3::implementation::CameraDeviceSession(device, deviceInfo, callback) {
+ V3_3::implementation::CameraDeviceSession(device, deviceInfo, callback),
+ mResultBatcher_3_4(callback) {
+
+ mHasCallback_3_4 = false;
+
+ auto castResult = ICameraDeviceCallback::castFrom(callback);
+ if (castResult.isOk()) {
+ sp<ICameraDeviceCallback> callback3_4 = castResult;
+ if (callback3_4 != nullptr) {
+ process_capture_result = sProcessCaptureResult_3_4;
+ notify = sNotify_3_4;
+ mHasCallback_3_4 = true;
+ if (!mInitFail) {
+ mResultBatcher_3_4.setResultMetadataQueue(mResultMetadataQueue);
+ }
+ }
+ }
}
CameraDeviceSession::~CameraDeviceSession() {
@@ -54,6 +70,18 @@
Status status = initStatus();
HalStreamConfiguration outStreams;
+ // If callback is 3.2, make sure no physical stream is configured
+ if (!mHasCallback_3_4) {
+ for (size_t i = 0; i < requestedConfiguration.streams.size(); i++) {
+ if (requestedConfiguration.streams[i].physicalCameraId.size() > 0) {
+ ALOGE("%s: trying to configureStreams with physical camera id with V3.2 callback",
+ __FUNCTION__);
+ _hidl_cb(Status::INTERNAL_ERROR, outStreams);
+ return Void();
+ }
+ }
+ }
+
// hold the inflight lock for entire configureStreams scope since there must not be any
// inflight request/results during stream configuration.
Mutex::Autolock _l(mInflightLock);
@@ -205,7 +233,7 @@
mVideoStreamIds.push_back(stream.v3_2.id);
}
}
- mResultBatcher.setBatchedStreams(mVideoStreamIds);
+ mResultBatcher_3_4.setBatchedStreams(mVideoStreamIds);
}
Return<void> CameraDeviceSession::processCaptureRequest_3_4(
@@ -224,7 +252,7 @@
}
if (s == Status::OK && requests.size() > 1) {
- mResultBatcher.registerBatch(requests[0].v3_2.frameNumber, requests.size());
+ mResultBatcher_3_4.registerBatch(requests[0].v3_2.frameNumber, requests.size());
}
_hidl_cb(s, numRequestProcessed);
@@ -237,6 +265,14 @@
ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
return status;
}
+ // If callback is 3.2, make sure there are no physical settings.
+ if (!mHasCallback_3_4) {
+ if (request.physicalCameraSettings.size() > 0) {
+ ALOGE("%s: trying to call processCaptureRequest_3_4 with physical camera id "
+ "and V3.2 callback", __FUNCTION__);
+ return Status::INTERNAL_ERROR;
+ }
+ }
camera3_capture_request_t halRequest;
halRequest.frame_number = request.v3_2.frameNumber;
@@ -407,6 +443,228 @@
return Status::OK;
}
+/**
+ * Static callback forwarding methods from HAL to instance
+ */
+void CameraDeviceSession::sProcessCaptureResult_3_4(
+ const camera3_callback_ops *cb,
+ const camera3_capture_result *hal_result) {
+ CameraDeviceSession *d =
+ const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
+
+ CaptureResult result;
+ d->constructCaptureResult(result.v3_2, hal_result);
+ result.physicalCameraMetadata.resize(hal_result->num_physcam_metadata);
+ for (uint32_t i = 0; i < hal_result->num_physcam_metadata; i++) {
+ std::string physicalId = hal_result->physcam_ids[i];
+ V3_2::CameraMetadata physicalMetadata;
+ V3_2::implementation::convertToHidl(hal_result->physcam_metadata[i], &physicalMetadata);
+ PhysicalCameraMetadata physicalCameraMetadata = {
+ .fmqMetadataSize = 0,
+ .physicalCameraId = physicalId,
+ .metadata = physicalMetadata };
+ result.physicalCameraMetadata[i] = physicalCameraMetadata;
+ }
+ d->mResultBatcher_3_4.processCaptureResult_3_4(result);
+}
+
+void CameraDeviceSession::sNotify_3_4(
+ const camera3_callback_ops *cb,
+ const camera3_notify_msg *msg) {
+ CameraDeviceSession *d =
+ const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
+ V3_2::NotifyMsg hidlMsg;
+ V3_2::implementation::convertToHidl(msg, &hidlMsg);
+
+ if (hidlMsg.type == (V3_2::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;
+ }
+ }
+
+ if (static_cast<camera3_msg_type_t>(hidlMsg.type) == CAMERA3_MSG_ERROR) {
+ switch (hidlMsg.msg.error.errorCode) {
+ case V3_2::ErrorCode::ERROR_DEVICE:
+ case V3_2::ErrorCode::ERROR_REQUEST:
+ case V3_2::ErrorCode::ERROR_RESULT: {
+ Mutex::Autolock _l(d->mInflightLock);
+ auto entry = d->mInflightAETriggerOverrides.find(
+ hidlMsg.msg.error.frameNumber);
+ if (d->mInflightAETriggerOverrides.end() != entry) {
+ d->mInflightAETriggerOverrides.erase(
+ hidlMsg.msg.error.frameNumber);
+ }
+
+ auto boostEntry = d->mInflightRawBoostPresent.find(
+ hidlMsg.msg.error.frameNumber);
+ if (d->mInflightRawBoostPresent.end() != boostEntry) {
+ d->mInflightRawBoostPresent.erase(
+ hidlMsg.msg.error.frameNumber);
+ }
+
+ }
+ break;
+ case V3_2::ErrorCode::ERROR_BUFFER:
+ default:
+ break;
+ }
+
+ }
+
+ d->mResultBatcher_3_4.notify(hidlMsg);
+}
+
+CameraDeviceSession::ResultBatcher_3_4::ResultBatcher_3_4(
+ const sp<V3_2::ICameraDeviceCallback>& callback) :
+ V3_3::implementation::CameraDeviceSession::ResultBatcher(callback) {
+ auto castResult = ICameraDeviceCallback::castFrom(callback);
+ if (castResult.isOk()) {
+ mCallback_3_4 = castResult;
+ }
+}
+
+void CameraDeviceSession::ResultBatcher_3_4::processCaptureResult_3_4(CaptureResult& result) {
+ auto pair = getBatch(result.v3_2.frameNumber);
+ int batchIdx = pair.first;
+ if (batchIdx == NOT_BATCHED) {
+ processOneCaptureResult_3_4(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_3_4(result);
+ return;
+ }
+
+ // queue metadata
+ if (result.v3_2.result.size() != 0) {
+ // Save a copy of metadata
+ batch->mResultMds[result.v3_2.partialResult].mMds.push_back(
+ std::make_pair(result.v3_2.frameNumber, result.v3_2.result));
+ }
+
+ // queue buffer
+ std::vector<int> filledStreams;
+ std::vector<V3_2::StreamBuffer> nonBatchedBuffers;
+ for (auto& buffer : result.v3_2.outputBuffers) {
+ auto it = batch->mBatchBufs.find(buffer.streamId);
+ if (it != batch->mBatchBufs.end()) {
+ InflightBatch::BufferBatch& bb = it->second;
+ pushStreamBuffer(std::move(buffer), bb.mBuffers);
+ filledStreams.push_back(buffer.streamId);
+ } else {
+ pushStreamBuffer(std::move(buffer), nonBatchedBuffers);
+ }
+ }
+
+ // send non-batched buffers up
+ if (nonBatchedBuffers.size() > 0 || result.v3_2.inputBuffer.streamId != -1) {
+ CaptureResult nonBatchedResult;
+ nonBatchedResult.v3_2.frameNumber = result.v3_2.frameNumber;
+ nonBatchedResult.v3_2.fmqResultSize = 0;
+ nonBatchedResult.v3_2.outputBuffers.resize(nonBatchedBuffers.size());
+ for (size_t i = 0; i < nonBatchedBuffers.size(); i++) {
+ moveStreamBuffer(
+ std::move(nonBatchedBuffers[i]), nonBatchedResult.v3_2.outputBuffers[i]);
+ }
+ moveStreamBuffer(std::move(result.v3_2.inputBuffer), nonBatchedResult.v3_2.inputBuffer);
+ nonBatchedResult.v3_2.partialResult = 0; // 0 for buffer only results
+ processOneCaptureResult_3_4(nonBatchedResult);
+ }
+
+ if (result.v3_2.frameNumber == batch->mLastFrame) {
+ // Send data up
+ if (result.v3_2.partialResult > 0) {
+ sendBatchMetadataLocked(batch, result.v3_2.partialResult);
+ }
+ // send buffer up
+ if (filledStreams.size() > 0) {
+ sendBatchBuffersLocked(batch, filledStreams);
+ }
+ }
+ } // end of batch lock scope
+
+ // see if the batch is complete
+ if (result.v3_2.frameNumber == batch->mLastFrame) {
+ checkAndRemoveFirstBatch();
+ }
+}
+
+void CameraDeviceSession::ResultBatcher_3_4::processOneCaptureResult_3_4(CaptureResult& result) {
+ hidl_vec<CaptureResult> results;
+ results.resize(1);
+ results[0] = std::move(result);
+ invokeProcessCaptureResultCallback_3_4(results, /* tryWriteFmq */true);
+ freeReleaseFences_3_4(results);
+ return;
+}
+
+void CameraDeviceSession::ResultBatcher_3_4::invokeProcessCaptureResultCallback_3_4(
+ hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
+ if (mProcessCaptureResultLock.tryLock() != OK) {
+ ALOGV("%s: previous call is not finished! waiting 1s...", __FUNCTION__);
+ if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
+ ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
+ __FUNCTION__);
+ return;
+ }
+ }
+ if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
+ for (CaptureResult &result : results) {
+ if (result.v3_2.result.size() > 0) {
+ if (mResultMetadataQueue->write(result.v3_2.result.data(),
+ result.v3_2.result.size())) {
+ result.v3_2.fmqResultSize = result.v3_2.result.size();
+ result.v3_2.result.resize(0);
+ } else {
+ ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
+ result.v3_2.fmqResultSize = 0;
+ }
+ }
+
+ for (auto& onePhysMetadata : result.physicalCameraMetadata) {
+ if (mResultMetadataQueue->write(onePhysMetadata.metadata.data(),
+ onePhysMetadata.metadata.size())) {
+ onePhysMetadata.fmqMetadataSize = onePhysMetadata.metadata.size();
+ onePhysMetadata.metadata.resize(0);
+ } else {
+ ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
+ onePhysMetadata.fmqMetadataSize = 0;
+ }
+ }
+ }
+ }
+ mCallback_3_4->processCaptureResult_3_4(results);
+ mProcessCaptureResultLock.unlock();
+}
+
+void CameraDeviceSession::ResultBatcher_3_4::freeReleaseFences_3_4(hidl_vec<CaptureResult>& results) {
+ for (auto& result : results) {
+ if (result.v3_2.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
+ native_handle_t* handle = const_cast<native_handle_t*>(
+ result.v3_2.inputBuffer.releaseFence.getNativeHandle());
+ native_handle_close(handle);
+ native_handle_delete(handle);
+ }
+ for (auto& buf : result.v3_2.outputBuffers) {
+ if (buf.releaseFence.getNativeHandle() != nullptr) {
+ native_handle_t* handle = const_cast<native_handle_t*>(
+ buf.releaseFence.getNativeHandle());
+ native_handle_close(handle);
+ native_handle_delete(handle);
+ }
+ }
+ }
+ return;
+}
+
} // namespace implementation
} // namespace V3_4
} // namespace device
diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
index 4ad1768..e6e0ae3 100644
--- a/camera/device/3.4/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -47,7 +47,7 @@
// Also make sure that can be done without editing source code
// TODO: b/72261675: make it dynamic since this affects memory usage
-const int kMaxJpegSize = {13 * 1024 * 1024}; // 13MB
+const int kMaxJpegSize = {5 * 1024 * 1024}; // 5MB
} // anonymous namespace
ExternalCameraDevice::ExternalCameraDevice(const std::string& cameraId) :
@@ -227,8 +227,7 @@
status_t ExternalCameraDevice::initDefaultCharsKeys(
::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
- // TODO: changed to HARDWARELEVEL_EXTERNAL later
- const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+ const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL;
UPDATE(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &hardware_level, 1);
// android.colorCorrection
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 507f092..0714ee2 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -57,8 +57,9 @@
HandleImporter ExternalCameraDeviceSession::sHandleImporter;
bool isAspectRatioClose(float ar1, float ar2) {
- const float kAspectRatioMatchThres = 0.01f; // This threshold is good enough to distinguish
+ const float kAspectRatioMatchThres = 0.025f; // This threshold is good enough to distinguish
// 4:3/16:9/20:9
+ // 1.33 / 1.78 / 2
return (std::abs(ar1 - ar2) < kAspectRatioMatchThres);
}
@@ -93,8 +94,8 @@
const std::vector<SupportedV4L2Format>& sortedFmts) {
const auto& maxSize = sortedFmts[sortedFmts.size() - 1];
float maxSizeAr = ASPECT_RATIO(maxSize);
- float minAr = kMinAspectRatio;
- float maxAr = kMaxAspectRatio;
+ float minAr = kMaxAspectRatio;
+ float maxAr = kMinAspectRatio;
for (const auto& fmt : sortedFmts) {
float ar = ASPECT_RATIO(fmt);
if (ar < minAr) {
@@ -724,11 +725,24 @@
ALOGE("%s: out is null", __FUNCTION__);
return -1;
}
+
uint32_t inW = inSize.width;
uint32_t inH = inSize.height;
uint32_t outW = outSize.width;
uint32_t outH = outSize.height;
+ // Handle special case where aspect ratio is close to input but scaled
+ // dimension is slightly larger than input
+ float arIn = ASPECT_RATIO(inSize);
+ float arOut = ASPECT_RATIO(outSize);
+ if (isAspectRatioClose(arIn, arOut)) {
+ out->left = 0;
+ out->top = 0;
+ out->width = inW;
+ out->height = inH;
+ return 0;
+ }
+
if (ct == VERTICAL) {
uint64_t scaledOutH = static_cast<uint64_t>(outH) * inW / outW;
if (scaledOutH > inH) {
@@ -1667,6 +1681,7 @@
switch (config.streams[i].format) {
case PixelFormat::BLOB:
case PixelFormat::YCBCR_420_888:
+ case PixelFormat::YV12: // Used by SurfaceTexture
// No override
out->streams[i].v3_2.overrideFormat = config.streams[i].format;
break;
@@ -1679,7 +1694,7 @@
mStreamMap[config.streams[i].id].format = out->streams[i].v3_2.overrideFormat;
break;
default:
- ALOGE("%s: unsupported format %x", __FUNCTION__, config.streams[i].format);
+ ALOGE("%s: unsupported format 0x%x", __FUNCTION__, config.streams[i].format);
return Status::ILLEGAL_ARGUMENT;
}
}
@@ -1833,15 +1848,14 @@
const uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;
UPDATE(md, ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);
-
- // TODO: b/72261912 AF should stay LOCKED until cancel is seen
- bool afTrigger = false;
+ bool afTrigger = mAfTrigger;
if (md.exists(ANDROID_CONTROL_AF_TRIGGER)) {
+ Mutex::Autolock _l(mLock);
camera_metadata_entry entry = md.find(ANDROID_CONTROL_AF_TRIGGER);
if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_START) {
- afTrigger = true;
+ mAfTrigger = afTrigger = true;
} else if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_CANCEL) {
- afTrigger = false;
+ mAfTrigger = afTrigger = false;
}
}
@@ -1871,6 +1885,9 @@
return -EINVAL;
}
+ const uint8_t flashState = ANDROID_FLASH_STATE_UNAVAILABLE;
+ UPDATE(md, ANDROID_FLASH_STATE, &flashState, 1);
+
// android.scaler
const int32_t crop_region[] = {
active_array_size.data.i32[0], active_array_size.data.i32[1],
diff --git a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
index 913bd78..9cd7da7 100644
--- a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
+++ b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
@@ -19,6 +19,7 @@
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
#include <../../3.3/default/CameraDeviceSession.h>
#include <../../3.3/default/include/convert.h>
#include <fmq/MessageQueue.h>
@@ -46,6 +47,7 @@
using ::android::hardware::camera::device::V3_4::StreamConfiguration;
using ::android::hardware::camera::device::V3_4::HalStreamConfiguration;
using ::android::hardware::camera::device::V3_4::ICameraDeviceSession;
+using ::android::hardware::camera::device::V3_4::ICameraDeviceCallback;
using ::android::hardware::camera::common::V1_0::Status;
using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
using ::android::hardware::kSynchronizedReadWrite;
@@ -94,6 +96,25 @@
Status processOneCaptureRequest_3_4(const V3_4::CaptureRequest& request);
std::map<int, std::string> mPhysicalCameraIdMap;
+
+ static V3_2::implementation::callbacks_process_capture_result_t sProcessCaptureResult_3_4;
+ static V3_2::implementation::callbacks_notify_t sNotify_3_4;
+
+ class ResultBatcher_3_4 : public V3_3::implementation::CameraDeviceSession::ResultBatcher {
+ public:
+ ResultBatcher_3_4(const sp<V3_2::ICameraDeviceCallback>& callback);
+ void processCaptureResult_3_4(CaptureResult& result);
+ private:
+ void freeReleaseFences_3_4(hidl_vec<CaptureResult>&);
+ void processOneCaptureResult_3_4(CaptureResult& result);
+ void invokeProcessCaptureResultCallback_3_4(hidl_vec<CaptureResult> &results,
+ bool tryWriteFmq);
+
+ sp<ICameraDeviceCallback> mCallback_3_4;
+ } mResultBatcher_3_4;
+
+ // Whether this camera device session is created with version 3.4 callback.
+ bool mHasCallback_3_4;
private:
struct TrampolineSessionInterface_3_4 : public ICameraDeviceSession {
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
index d8a17f6..7d7f52c 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
@@ -359,6 +359,8 @@
// Stream ID -> circulating buffers map
std::map<int, CirculatingBuffers> mCirculatingBuffers;
+ bool mAfTrigger = false;
+
static HandleImporter sHandleImporter;
/* Beginning of members not changed after initialize() */
diff --git a/camera/device/3.4/types.hal b/camera/device/3.4/types.hal
index 429db3e..5ab6b88 100644
--- a/camera/device/3.4/types.hal
+++ b/camera/device/3.4/types.hal
@@ -22,6 +22,7 @@
import @3.3::HalStream;
import @3.2::CameraMetadata;
import @3.2::CaptureRequest;
+import @3.2::CaptureResult;
/**
* Stream:
@@ -226,3 +227,66 @@
*/
vec<PhysicalCameraSetting> physicalCameraSettings;
};
+
+/**
+ * PhysicalCameraMetadata:
+ *
+ * Individual camera metadata for a physical camera as part of a logical
+ * multi-camera. Camera HAL should return one such metadata for each physical
+ * camera being requested on.
+ */
+struct PhysicalCameraMetadata {
+ /**
+ * If non-zero, read metadata from result metadata queue instead
+ * (see ICameraDeviceSession.getCaptureResultMetadataQueue).
+ * If zero, read metadata from .metadata field.
+ */
+ uint64_t fmqMetadataSize;
+
+ /**
+ * Contains the physical device camera id. As long as the corresponding
+ * processCaptureRequest requests on a particular physical camera stream,
+ * the metadata for that physical camera should be generated for the capture
+ * result. */
+ string physicalCameraId;
+
+ /**
+ * If fmqMetadataSize is zero, the metadata buffer contains the metadata
+ * for the physical device with physicalCameraId.
+ *
+ * The v3_2 CaptureResult metadata is read first from the FMQ, followed by
+ * the physical cameras' metadata starting from index 0.
+ */
+ CameraMetadata metadata;
+};
+
+/**
+ * CaptureResult:
+ *
+ * Identical to @3.2::CaptureResult, except that it contains a list of
+ * physical camera metadata.
+ *
+ * Physical camera metadata needs to be generated if and only if a
+ * request is pending on a stream from that physical camera. For example,
+ * if the processCaptureRequest call doesn't request on physical camera
+ * streams, the physicalCameraMetadata field of the CaptureResult being returned
+ * should be an 0-size vector. If the processCaptureRequest call requests on
+ * streams from one of the physical camera, the physicalCameraMetadata field
+ * should contain one metadata describing the capture from that physical camera.
+ *
+ * For a CaptureResult that contains physical camera metadata, its
+ * partialResult field must be android.request.partialResultCount. In other
+ * words, the physicalCameraMetadata must only be contained in a final capture
+ * result.
+ */
+struct CaptureResult {
+ /**
+ * The definition of CaptureResult from the prior version.
+ */
+ @3.2::CaptureResult v3_2;
+
+ /**
+ * The physical metadata for logical multi-camera.
+ */
+ vec<PhysicalCameraMetadata> physicalCameraMetadata;
+};
diff --git a/gnss/1.1/IGnss.hal b/gnss/1.1/IGnss.hal
index 0c3d876..096f251 100644
--- a/gnss/1.1/IGnss.hal
+++ b/gnss/1.1/IGnss.hal
@@ -17,6 +17,7 @@
package android.hardware.gnss@1.1;
import @1.0::IGnss;
+import @1.0::GnssLocation;
import IGnssCallback;
import IGnssConfiguration;
@@ -78,4 +79,16 @@
* @return gnssMeasurementIface Handle to the IGnssMeasurement interface.
*/
getExtensionGnssMeasurement_1_1() generates (IGnssMeasurement gnssMeasurementIface);
+
+ /**
+ * Injects current location from the best available location provider.
+ *
+ * Unlike injectLocation, this method may inject a recent GNSS location from the HAL
+ * implementation, if that is the best available location known to the framework.
+ *
+ * @param location Location information from the best available location provider.
+ *
+ * @return success Returns true if successful.
+ */
+ injectBestLocation(GnssLocation location) generates (bool success);
};
\ No newline at end of file
diff --git a/gnss/1.1/IGnssCallback.hal b/gnss/1.1/IGnssCallback.hal
index 7a2849e..9fd71ae 100644
--- a/gnss/1.1/IGnssCallback.hal
+++ b/gnss/1.1/IGnssCallback.hal
@@ -35,4 +35,17 @@
* @param name String providing the name of the GNSS HAL implementation
*/
gnssNameCb(string name);
+
+ /**
+ * Callback for requesting Location.
+ *
+ * HAL implementation shall call this when it wants the framework to provide location to assist
+ * with GNSS HAL operation. For example, to assist with time to first fix, and/or error
+ * recovery, it may ask for a location that is independent from GNSS (e.g. from the "network"
+ * LocationProvier), or to provide a Device-Based-Hybrid location to supplement A-GPS/GNSS
+ * emergency call flows managed by the GNSS HAL.
+ *
+ * @param independentFromGnss True if requesting a location that is independent from GNSS.
+ */
+ gnssRequestLocationCb(bool independentFromGnss);
};
\ No newline at end of file
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.h b/gnss/1.1/vts/functional/gnss_hal_test.h
index a06db5d..6aab3cb 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test.h
+++ b/gnss/1.1/vts/functional/gnss_hal_test.h
@@ -74,6 +74,9 @@
}
Return<void> gnssAcquireWakelockCb() override { return Void(); }
Return<void> gnssReleaseWakelockCb() override { return Void(); }
+ Return<void> gnssRequestLocationCb(bool /* independentFromGnss */) override {
+ return Void();
+ }
Return<void> gnssRequestTimeCb() override { return Void(); }
// Actual (test) callback handlers
Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;
diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
index c9e36a9..55f0acc 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -23,6 +23,7 @@
using android::hardware::hidl_vec;
using android::hardware::gnss::V1_0::GnssConstellationType;
+using android::hardware::gnss::V1_0::GnssLocation;
using android::hardware::gnss::V1_1::IGnssConfiguration;
using android::hardware::gnss::V1_1::IGnssMeasurement;
@@ -363,4 +364,35 @@
result = gnss_configuration_hal->setBlacklist(sources);
ASSERT_TRUE(result.isOk());
EXPECT_TRUE(result);
-}
\ No newline at end of file
+}
+
+/*
+ * InjectBestLocation
+ *
+ * Ensure successfully injecting a location.
+ */
+TEST_F(GnssHalTest, InjectBestLocation) {
+ GnssLocation gnssLocation = {.gnssLocationFlags = 0, // set below
+ .latitudeDegrees = 43.0,
+ .longitudeDegrees = -180,
+ .altitudeMeters = 1000,
+ .speedMetersPerSec = 0,
+ .bearingDegrees = 0,
+ .horizontalAccuracyMeters = 0.1,
+ .verticalAccuracyMeters = 0.1,
+ .speedAccuracyMetersPerSecond = 0.1,
+ .bearingAccuracyDegrees = 0.1,
+ .timestamp = 1534567890123L};
+ gnssLocation.gnssLocationFlags |=
+ GnssLocationFlags::HAS_LAT_LONG | GnssLocationFlags::HAS_ALTITUDE |
+ GnssLocationFlags::HAS_SPEED | GnssLocationFlags::HAS_HORIZONTAL_ACCURACY |
+ GnssLocationFlags::HAS_VERTICAL_ACCURACY | GnssLocationFlags::HAS_SPEED_ACCURACY |
+ GnssLocationFlags::HAS_BEARING | GnssLocationFlags::HAS_BEARING_ACCURACY;
+
+ CheckLocation(gnssLocation, true);
+
+ auto result = gnss_hal_->injectBestLocation(gnssLocation);
+
+ ASSERT_TRUE(result.isOk());
+ EXPECT_TRUE(result);
+}
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index 0dfc735..9d6501b 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -104,46 +104,47 @@
typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \
static TAG_##name##_t TAG_##name;
+DECLARE_TYPED_TAG(ACTIVE_DATETIME);
+DECLARE_TYPED_TAG(ALGORITHM);
+DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY);
+DECLARE_TYPED_TAG(APPLICATION_DATA);
+DECLARE_TYPED_TAG(APPLICATION_ID);
+DECLARE_TYPED_TAG(ASSOCIATED_DATA);
+DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID);
+DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
+DECLARE_TYPED_TAG(AUTH_TIMEOUT);
+DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS);
+DECLARE_TYPED_TAG(BLOCK_MODE);
+DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
+DECLARE_TYPED_TAG(CALLER_NONCE);
+DECLARE_TYPED_TAG(CONFIRMATION_TOKEN);
+DECLARE_TYPED_TAG(CREATION_DATETIME);
+DECLARE_TYPED_TAG(DIGEST);
+DECLARE_TYPED_TAG(EC_CURVE);
+DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID);
DECLARE_TYPED_TAG(INVALID);
DECLARE_TYPED_TAG(KEY_SIZE);
DECLARE_TYPED_TAG(MAC_LENGTH);
-DECLARE_TYPED_TAG(CALLER_NONCE);
-DECLARE_TYPED_TAG(MIN_MAC_LENGTH);
-DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT);
-DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID);
-DECLARE_TYPED_TAG(ACTIVE_DATETIME);
-DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME);
-DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
-DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS);
DECLARE_TYPED_TAG(MAX_USES_PER_BOOT);
-DECLARE_TYPED_TAG(USER_SECURE_ID);
+DECLARE_TYPED_TAG(MIN_MAC_LENGTH);
+DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS);
+DECLARE_TYPED_TAG(NONCE);
DECLARE_TYPED_TAG(NO_AUTH_REQUIRED);
-DECLARE_TYPED_TAG(AUTH_TIMEOUT);
-DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY);
-DECLARE_TYPED_TAG(APPLICATION_ID);
-DECLARE_TYPED_TAG(APPLICATION_DATA);
-DECLARE_TYPED_TAG(CREATION_DATETIME);
+DECLARE_TYPED_TAG(ORIGIN);
+DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME);
+DECLARE_TYPED_TAG(OS_PATCHLEVEL);
+DECLARE_TYPED_TAG(OS_VERSION);
+DECLARE_TYPED_TAG(PADDING);
+DECLARE_TYPED_TAG(PURPOSE);
+DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION);
DECLARE_TYPED_TAG(ROLLBACK_RESISTANCE);
DECLARE_TYPED_TAG(ROOT_OF_TRUST);
-DECLARE_TYPED_TAG(ASSOCIATED_DATA);
-DECLARE_TYPED_TAG(NONCE);
-DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
-DECLARE_TYPED_TAG(OS_VERSION);
-DECLARE_TYPED_TAG(OS_PATCHLEVEL);
+DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT);
+DECLARE_TYPED_TAG(TRUSTED_CONFIRMATION_REQUIRED);
DECLARE_TYPED_TAG(UNIQUE_ID);
-DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
-DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID);
-DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION);
-
-DECLARE_TYPED_TAG(PURPOSE);
-DECLARE_TYPED_TAG(ALGORITHM);
-DECLARE_TYPED_TAG(BLOCK_MODE);
-DECLARE_TYPED_TAG(DIGEST);
-DECLARE_TYPED_TAG(PADDING);
-DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS);
-DECLARE_TYPED_TAG(ORIGIN);
+DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
DECLARE_TYPED_TAG(USER_AUTH_TYPE);
-DECLARE_TYPED_TAG(EC_CURVE);
+DECLARE_TYPED_TAG(USER_SECURE_ID);
template <typename... Elems>
struct MetaList {};
@@ -344,6 +345,7 @@
case Tag::ALLOW_WHILE_ON_BODY:
case Tag::ROLLBACK_RESISTANCE:
case Tag::RESET_SINCE_ID_ROTATION:
+ case Tag::TRUSTED_CONFIRMATION_REQUIRED:
case Tag::TRUSTED_USER_PRESENCE_REQUIRED:
return true;
@@ -388,6 +390,7 @@
case Tag::ATTESTATION_ID_MANUFACTURER:
case Tag::ATTESTATION_ID_MODEL:
case Tag::ASSOCIATED_DATA:
+ case Tag::CONFIRMATION_TOKEN:
case Tag::NONCE:
return a.blob == b.blob;
diff --git a/keymaster/4.0/types.hal b/keymaster/4.0/types.hal
index 5714c4d..91ec9bf 100644
--- a/keymaster/4.0/types.hal
+++ b/keymaster/4.0/types.hal
@@ -181,6 +181,16 @@
*/
TRUSTED_USER_PRESENCE_REQUIRED = TagType:BOOL | 507,
+ /** TRUSTED_CONFIRMATION_REQUIRED is only applicable to keys with KeyPurpose SIGN, and specifies
+ * that this key must not be usable unless the user provides confirmation of the data to be
+ * signed. Confirmation is proven to keymaster via an approval token. See CONFIRMATION_TOKEN,
+ * as well as the ConfirmatinUI HAL.
+ *
+ * If an attempt to use a key with this tag does not have a cryptographically valid
+ * CONFIRMATION_TOKEN provided to finish() or if the data provided to update()/finish() does not
+ * match the data described in the token, keymaster must return NO_USER_CONFIRMATION. */
+ TRUSTED_CONFIRMATION_REQUIRED = TagType:BOOL | 508,
+
/* Application access control */
APPLICATION_ID = TagType:BYTES | 601, /* Byte string identifying the authorized application. */
@@ -251,6 +261,13 @@
RESET_SINCE_ID_ROTATION = TagType:BOOL | 1004, /* Whether the device has beeen factory reset
* since the last unique ID rotation. Used for
* key attestation. */
+
+ /**
+ * CONFIRMATION_TOKEN is used to deliver a cryptographic token proving that the user confirmed a
+ * signing request. The content is a full-length HMAC-SHA256 value. See the ConfirmationUI HAL
+ * for details of token computation.
+ */
+ CONFIRMATION_TOKEN = TagType:BYTES | 1005,
};
/**
@@ -453,6 +470,7 @@
HARDWARE_TYPE_UNAVAILABLE = -68,
PROOF_OF_PRESENCE_REQUIRED = -69,
CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = -70,
+ NO_USER_CONFIRMATION = -71,
UNIMPLEMENTED = -100,
VERSION_MISMATCH = -101,
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 1d8dfdf..dbf5ece 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -712,6 +712,29 @@
}
/*
+ * SigningOperationsTest.NoUserConfirmation
+ *
+ * Verifies that keymaster rejects signing operations for keys with
+ * TRUSTED_CONFIRMATION_REQUIRED and no valid confirmation token
+ * presented.
+ */
+TEST_F(SigningOperationsTest, NoUserConfirmation) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(1024, 3)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_TRUSTED_CONFIRMATION_REQUIRED)));
+
+ const string message = "12345678901234567890123456789012";
+ EXPECT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::SIGN,
+ AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)));
+ string signature;
+ EXPECT_EQ(ErrorCode::NO_USER_CONFIRMATION, Finish(message, &signature));
+}
+
+/*
* SigningOperationsTest.RsaPkcs1Sha256Success
*
* Verifies that digested RSA-PKCS1 signature operations succeed.
diff --git a/radio/1.2/IRadio.hal b/radio/1.2/IRadio.hal
index babe86f..67ce56c 100644
--- a/radio/1.2/IRadio.hal
+++ b/radio/1.2/IRadio.hal
@@ -18,6 +18,8 @@
import @1.1::IRadio;
import @1.1::RadioAccessNetworks;
+import @1.0::DataProfileInfo;
+import @1.0::RadioTechnology;
/**
* This interface is used by telephony and telecom to talk to cellular radio.
@@ -106,4 +108,67 @@
oneway setLinkCapacityReportingCriteria(int32_t serial, int32_t hysteresisMs,
int32_t hysteresisDlKbps, int32_t hysteresisUlKbps, vec<int32_t> thresholdsDownlinkKbps,
vec<int32_t> thresholdsUplinkKbps, RadioAccessNetworks ran);
+
+ /**
+ * Setup a packet data connection. If DataCallResponse.status returns DataCallFailCause:NONE,
+ * the data connection must be added to data calls and a unsolDataCallListChanged() must be
+ * sent. The call remains until removed by subsequent unsolDataCallIstChanged(). It may be
+ * lost due to many factors, including deactivateDataCall() being issued, the radio powered
+ * off, reception lost or even transient factors like congestion. This data call list is
+ * returned by getDataCallList() and dataCallListChanged().
+ *
+ * The Radio is expected to:
+ * - Create one data call context.
+ * - Create and configure a dedicated interface for the context.
+ * - The interface must be point to point.
+ * - The interface is configured with one or more addresses and is capable of sending and
+ * receiving packets. The prefix length of the addresses must be /32 for IPv4 and /128
+ * for IPv6.
+ * - Must not modify routing configuration related to this interface; routing management is
+ * exclusively within the purview of the Android OS.
+ * - Support simultaneous data call contexts up to DataRegStateResult.maxDataCalls specified
+ * in the response of getDataRegistrationState.
+ *
+ * @param serial Serial number of request.
+ * @param accessNetwork The access network to setup the data call. If the data connection cannot
+ * be established on the specified access network, the setup request must be failed.
+ * @param dataProfileInfo Data profile info.
+ * @param modemCognitive Indicates that the requested profile has previously been provided via
+ * setDataProfile().
+ * @param roamingAllowed Indicates whether or not data roaming is allowed by the user.
+ * @param isRoaming Indicates whether or not the framework has requested this setupDataCall for
+ * a roaming network. The 'protocol' parameter in the old RIL API must be filled
+ * accordingly based on the roaming condition. Note this is for backward compatibility with
+ * the old radio modem. The modem must not use this param for any other reason.
+ * @param reason The request reason. Must be DataRequestReason.NORMAL or
+ * DataRequestReason.HANDOVER.
+ * @param addresses If the reason is DataRequestReason.HANDOVER, this indicates the list of link
+ * addresses of the existing data connection. The format is IP address with optional "/"
+ * prefix length (The format is defined in RFC-4291 section 2.3). For example, "192.0.1.3",
+ * "192.0.1.11/16", or "2001:db8::1/64". Typically one IPv4 or one IPv6 or one of each. If
+ * the prefix length is absent, then the addresses are assumed to be point to point with
+ * IPv4 with prefix length 32 or IPv6 with prefix length 128. This parameter must be ignored
+ * unless reason is DataRequestReason.HANDOVER.
+ * @param dnses If the reason is DataRequestReason.HANDOVER, this indicates the list of DNS
+ * addresses of the existing data connection. The format is defined in RFC-4291 section
+ * 2.2. For example, "192.0.1.3" or "2001:db8::1". This parameter must be ignored unless
+ * reason is DataRequestReason.HANDOVER.
+ *
+ * Response function is IRadioResponse.setupDataCallResponse()
+ */
+ oneway setupDataCall_1_2(int32_t serial, AccessNetwork accessNetwork,
+ DataProfileInfo dataProfileInfo, bool modemCognitive, bool roamingAllowed,
+ bool isRoaming, DataRequestReason reason, vec<string> addresses, vec<string> dnses);
+
+ /**
+ * Deactivate packet data connection and remove from the data call list. An
+ * unsolDataCallListChanged() must be sent when data connection is deactivated.
+ *
+ * @param serial Serial number of request.
+ * @param cid Data call id.
+ * @param reason The request reason. Must be normal, handover, or shutdown.
+ *
+ * Response function is IRadioResponse.deactivateDataCallResponse()
+ */
+ oneway deactivateDataCall_1_2(int32_t serial, int32_t cid, DataRequestReason reason);
};
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index 4515237..f2f0b69 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -335,3 +335,32 @@
*/
int32_t cellBandwidthDownlink;
};
+
+enum AccessNetwork : int32_t {
+ /** GSM EDGE Radio Access Network */
+ GERAN = 1,
+ /** Universal Terrestrial Radio Access Network */
+ UTRAN = 2,
+ /** Evolved Universal Terrestrial Radio Access Network */
+ EUTRAN = 3,
+ /** CDMA 2000 network */
+ CDMA2000 = 4,
+ /** Interworking Wireless LAN */
+ IWLAN = 5
+};
+
+enum DataRequestReason : int32_t {
+ /**
+ * The reason of the data request is normal
+ */
+ NORMAL = 0x01,
+ /**
+ * The reason of the data request is device shutdown
+ */
+ SHUTDOWN = 0x02,
+ /**
+ * The reason of the data request is IWLAN data handover to another transport
+ * (e.g. from cellular to wifi or vise versa)
+ */
+ HANDOVER = 0x03,
+};
diff --git a/renderscript/1.0/default/Android.bp b/renderscript/1.0/default/Android.bp
index b996969..d5d6d8d 100644
--- a/renderscript/1.0/default/Android.bp
+++ b/renderscript/1.0/default/Android.bp
@@ -12,7 +12,7 @@
],
shared_libs: [
"libdl",
- "liblog",
+ "libbase",
"libhidlbase",
"libhidltransport",
"libutils",
diff --git a/renderscript/1.0/default/Context.cpp b/renderscript/1.0/default/Context.cpp
index fbfc652..f5b70c9 100644
--- a/renderscript/1.0/default/Context.cpp
+++ b/renderscript/1.0/default/Context.cpp
@@ -1,5 +1,3 @@
-#define LOG_TAG "android.hardware.renderscript@1.0-impl"
-
#include "Context.h"
#include "Device.h"
diff --git a/renderscript/1.0/default/Device.cpp b/renderscript/1.0/default/Device.cpp
index a2b950d..8fda3ff 100644
--- a/renderscript/1.0/default/Device.cpp
+++ b/renderscript/1.0/default/Device.cpp
@@ -1,6 +1,7 @@
#include "Context.h"
#include "Device.h"
+#include <android-base/logging.h>
#include <android/dlext.h>
#include <dlfcn.h>
@@ -54,12 +55,18 @@
.flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = rsNamespace,
};
handle = android_dlopen_ext(filename, RTLD_LAZY | RTLD_LOCAL, &dlextinfo);
+ if (handle == nullptr) {
+ LOG(WARNING) << "android_dlopen_ext(" << filename << ") failed: " << dlerror();
+ }
}
}
if (handle == nullptr) {
// if there is no "rs" namespace (in case when this HAL impl is loaded
// into a vendor process), then use the plain dlopen.
handle = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
+ if (handle == nullptr) {
+ LOG(FATAL) << "dlopen(" << filename << ") failed: " << dlerror();
+ }
}
dispatchTable dispatchHal = {