mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
DO NOT MERGE: Merge Oreo MR1 into master
Exempt-From-Owner-Approval: Changes already landed internally Change-Id: I8318c8bcc6ce5e750326b3315710c96a37838f22
This commit is contained in:
@@ -56,4 +56,10 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/)
|
||||
$(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/hardware/interfaces/)
|
||||
$(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/hardware/interfaces/)
|
||||
$(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore*" -print0 | xargs -0 rm -f)
|
||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk-sp/android.hardware.graphics.allocator*)
|
||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/hw/android.hardware.automotive*)
|
||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/hw/android.hardware.automotive*)
|
||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/hw/android.hardware.automotive*)
|
||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/android.hardware.automotive*)
|
||||
$(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore\@1\.1*" -print0 | xargs -0 rm -f)
|
||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/android.hardware.tests*)
|
||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk/android.hardware.tests*)
|
||||
|
||||
@@ -365,10 +365,10 @@
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:complexType name="profile">
|
||||
<xs:attribute name="name" type="xs:token" use="required"/>
|
||||
<xs:attribute name="format" type="audioFormat" use="required"/>
|
||||
<xs:attribute name="samplingRates" type="samplingRates" use="required"/>
|
||||
<xs:attribute name="channelMasks" type="channelMask" use="required"/>
|
||||
<xs:attribute name="name" type="xs:token" use="optional"/>
|
||||
<xs:attribute name="format" type="audioFormat" use="optional"/>
|
||||
<xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
|
||||
<xs:attribute name="channelMasks" type="channelMask" use="optional"/>
|
||||
</xs:complexType>
|
||||
<xs:simpleType name="gainMode">
|
||||
<xs:restriction base="xs:string">
|
||||
|
||||
@@ -88,8 +88,4 @@ else
|
||||
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_USES_BCRADIO_FUTURE_FEATURES),true)
|
||||
LOCAL_CFLAGS += -DTARGET_USES_BCRADIO_FUTURE_FEATURES
|
||||
endif
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
@@ -49,6 +49,13 @@ using ::android::sp;
|
||||
struct Stream : public IStream, public ParametersUtil {
|
||||
explicit Stream(audio_stream_t* stream);
|
||||
|
||||
/** 1GiB is the maximum buffer size the HAL client is allowed to request.
|
||||
* This value has been chosen to be under SIZE_MAX and still big enough
|
||||
* for all audio use case.
|
||||
* Keep private for 2.0, put in .hal in 2.1
|
||||
*/
|
||||
static constexpr uint32_t MAX_BUFFER_SIZE = 2 << 30 /* == 1GiB */;
|
||||
|
||||
// Methods from ::android::hardware::audio::V2_0::IStream follow.
|
||||
Return<uint64_t> getFrameSize() override;
|
||||
Return<uint64_t> getFrameCount() override;
|
||||
|
||||
@@ -346,14 +346,10 @@ Return<void> StreamIn::prepareForReading(uint32_t frameSize,
|
||||
sendError(Result::INVALID_ARGUMENTS);
|
||||
return Void();
|
||||
}
|
||||
// A message queue asserts if it can not handle the requested buffer,
|
||||
// thus the client has to guess the maximum size it can handle
|
||||
// Choose an arbitrary margin for the overhead of a message queue
|
||||
size_t metadataOverhead = 100000;
|
||||
if (frameSize >
|
||||
(std::numeric_limits<size_t>::max() - metadataOverhead) / framesCount) {
|
||||
ALOGE("Buffer too big: %u*%u bytes can not fit in a message queue",
|
||||
frameSize, framesCount);
|
||||
|
||||
if (frameSize > Stream::MAX_BUFFER_SIZE / framesCount) {
|
||||
ALOGE("Buffer too big: %u*%u bytes > MAX_BUFFER_SIZE (%u)", frameSize, framesCount,
|
||||
Stream::MAX_BUFFER_SIZE);
|
||||
sendError(Result::INVALID_ARGUMENTS);
|
||||
return Void();
|
||||
}
|
||||
|
||||
@@ -323,14 +323,9 @@ Return<void> StreamOut::prepareForWriting(uint32_t frameSize,
|
||||
sendError(Result::INVALID_ARGUMENTS);
|
||||
return Void();
|
||||
}
|
||||
// A message queue asserts if it can not handle the requested buffer,
|
||||
// thus the client has to guess the maximum size it can handle
|
||||
size_t metadataOverhead =
|
||||
100000; // Arbitrary margin for the overhead of a message queue
|
||||
if (frameSize >
|
||||
(std::numeric_limits<size_t>::max() - metadataOverhead) / framesCount) {
|
||||
ALOGE("Buffer too big: %u*%u bytes can not fit in a message queue",
|
||||
frameSize, framesCount);
|
||||
if (frameSize > Stream::MAX_BUFFER_SIZE / framesCount) {
|
||||
ALOGE("Buffer too big: %u*%u bytes > MAX_BUFFER_SIZE (%u)", frameSize, framesCount,
|
||||
Stream::MAX_BUFFER_SIZE);
|
||||
sendError(Result::INVALID_ARGUMENTS);
|
||||
return Void();
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#include <android/hardware/audio/2.0/IDevicesFactory.h>
|
||||
#include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
|
||||
#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
|
||||
#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
|
||||
#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
|
||||
|
||||
using android::hardware::configureRpcThreadpool;
|
||||
using android::hardware::joinRpcThreadpool;
|
||||
@@ -32,13 +30,6 @@ using android::hardware::audio::effect::V2_0::IEffectsFactory;
|
||||
using android::hardware::audio::V2_0::IDevicesFactory;
|
||||
using android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
|
||||
using android::hardware::registerPassthroughServiceImplementation;
|
||||
namespace broadcastradio = android::hardware::broadcastradio;
|
||||
|
||||
#ifdef TARGET_USES_BCRADIO_FUTURE_FEATURES
|
||||
static const bool useBroadcastRadioFutureFeatures = true;
|
||||
#else
|
||||
static const bool useBroadcastRadioFutureFeatures = false;
|
||||
#endif
|
||||
|
||||
using android::OK;
|
||||
|
||||
@@ -49,17 +40,9 @@ int main(int /* argc */, char* /* argv */ []) {
|
||||
LOG_ALWAYS_FATAL_IF(status != OK, "Error while registering audio service: %d", status);
|
||||
status = registerPassthroughServiceImplementation<IEffectsFactory>();
|
||||
LOG_ALWAYS_FATAL_IF(status != OK, "Error while registering audio effects service: %d", status);
|
||||
// Soundtrigger and FM radio might be not present.
|
||||
// Soundtrigger might be not present.
|
||||
status = registerPassthroughServiceImplementation<ISoundTriggerHw>();
|
||||
ALOGE_IF(status != OK, "Error while registering soundtrigger service: %d", status);
|
||||
if (useBroadcastRadioFutureFeatures) {
|
||||
status = registerPassthroughServiceImplementation<
|
||||
broadcastradio::V1_1::IBroadcastRadioFactory>();
|
||||
} else {
|
||||
status = registerPassthroughServiceImplementation<
|
||||
broadcastradio::V1_0::IBroadcastRadioFactory>();
|
||||
}
|
||||
ALOGE_IF(status != OK, "Error while registering fm radio service: %d", status);
|
||||
joinRpcThreadpool();
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -16,29 +16,18 @@
|
||||
|
||||
cc_test {
|
||||
name: "VtsHalAudioV2_0TargetTest",
|
||||
defaults: ["hidl_defaults"],
|
||||
srcs: ["AudioPrimaryHidlHalTest.cpp",
|
||||
"ValidateAudioConfiguration.cpp"],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"liblog",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libutils",
|
||||
"libcutils",
|
||||
"libxml2",
|
||||
"android.hardware.audio@2.0",
|
||||
"android.hardware.audio.common@2.0",
|
||||
defaults: ["VtsHalTargetTestDefaults"],
|
||||
srcs: [
|
||||
"AudioPrimaryHidlHalTest.cpp",
|
||||
"ValidateAudioConfiguration.cpp"
|
||||
],
|
||||
static_libs: [
|
||||
"VtsHalHidlTargetTestBase",
|
||||
"android.hardware.audio.common.test.utility",
|
||||
"android.hardware.audio@2.0",
|
||||
"android.hardware.audio.common@2.0",
|
||||
"libxml2",
|
||||
],
|
||||
cflags: [
|
||||
"-O0",
|
||||
"-g",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
shared_libs: [
|
||||
"libicuuc",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -14,9 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "utility/ValidateXml.h"
|
||||
|
||||
TEST(CheckConfig, audioPolicyConfigurationValidation) {
|
||||
ASSERT_VALID_XML("/vendor/etc/audio_policy_configuration.xml",
|
||||
"/data/local/tmp/audio_policy_configuration.xsd");
|
||||
const char* configName = "audio_policy_configuration.xml";
|
||||
const char* possibleConfigLocations[] = {"/odm/etc", "/vendor/etc", "/system/etc"};
|
||||
const char* configSchemaPath = "/data/local/tmp/audio_policy_configuration.xsd";
|
||||
|
||||
for (std::string folder : possibleConfigLocations) {
|
||||
const auto configPath = folder + '/' + configName;
|
||||
if (access(configPath.c_str(), R_OK) == 0) {
|
||||
ASSERT_VALID_XML(configPath.c_str(), configSchemaPath);
|
||||
return; // The framework does not read past the first config file found
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ cc_library_shared {
|
||||
name: "android.hardware.audio.common@2.0-util",
|
||||
defaults: ["hidl_defaults"],
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
srcs: [
|
||||
"EffectMap.cpp",
|
||||
"HidlUtils.cpp",
|
||||
|
||||
@@ -16,24 +16,20 @@
|
||||
|
||||
cc_test {
|
||||
name: "VtsHalAudioEffectV2_0TargetTest",
|
||||
defaults: ["hidl_defaults"],
|
||||
srcs: ["VtsHalAudioEffectV2_0TargetTest.cpp"],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"liblog",
|
||||
"libcutils",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libnativehelper",
|
||||
"libutils",
|
||||
defaults: ["VtsHalTargetTestDefaults"],
|
||||
srcs: [
|
||||
"VtsHalAudioEffectV2_0TargetTest.cpp",
|
||||
"ValidateAudioEffectsConfiguration.cpp"
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.audio.common.test.utility",
|
||||
"android.hardware.audio.common@2.0",
|
||||
"android.hardware.audio.effect@2.0",
|
||||
"android.hidl.allocator@1.0",
|
||||
"android.hidl.memory@1.0",
|
||||
"libxml2",
|
||||
],
|
||||
static_libs: ["VtsHalHidlTargetTestBase"],
|
||||
cflags: [
|
||||
"-O0",
|
||||
"-g",
|
||||
shared_libs: [
|
||||
"libicuuc",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "utility/ValidateXml.h"
|
||||
|
||||
TEST(CheckConfig, audioEffectsConfigurationValidation) {
|
||||
RecordProperty("description",
|
||||
"Verify that the effects configuration file is valid according to the schema");
|
||||
const char* xmlConfigFile = "/vendor/etc/audio_effects.xml";
|
||||
// Not every device uses XML configuration, so only validate
|
||||
// if the XML configuration actually exists.
|
||||
if (access(xmlConfigFile, F_OK) == 0) {
|
||||
ASSERT_VALID_XML(xmlConfigFile, "/data/local/tmp/audio_effects_conf_V2_0.xsd");
|
||||
}
|
||||
}
|
||||
249
audio/effect/2.0/xml/audio_effects_conf_V2_0.xsd
Normal file
249
audio/effect/2.0/xml/audio_effects_conf_V2_0.xsd
Normal file
@@ -0,0 +1,249 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://schemas.android.com/audio/audio_effects_conf/v2_0"
|
||||
xmlns:aec="http://schemas.android.com/audio/audio_effects_conf/v2_0"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<!-- Simple types -->
|
||||
<xs:simpleType name="versionType">
|
||||
<xs:restriction base="xs:decimal">
|
||||
<xs:enumeration value="2.0"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="uuidType">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="streamInputType">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="mic"/>
|
||||
<xs:enumeration value="voice_uplink"/>
|
||||
<xs:enumeration value="voice_downlink"/>
|
||||
<xs:enumeration value="voice_call"/>
|
||||
<xs:enumeration value="camcorder"/>
|
||||
<xs:enumeration value="voice_recognition"/>
|
||||
<xs:enumeration value="voice_communication"/>
|
||||
<xs:enumeration value="unprocessed"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="streamOutputType">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="voice_call"/>
|
||||
<xs:enumeration value="system"/>
|
||||
<xs:enumeration value="ring"/>
|
||||
<xs:enumeration value="music"/>
|
||||
<xs:enumeration value="alarm"/>
|
||||
<xs:enumeration value="notification"/>
|
||||
<xs:enumeration value="bluetooth_sco"/>
|
||||
<xs:enumeration value="enforced_audible"/>
|
||||
<xs:enumeration value="dtmf"/>
|
||||
<xs:enumeration value="tts"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="relativePathType">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[^/].*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- Complex types -->
|
||||
<xs:complexType name="librariesType">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
List of effect libraries to load. Each library element must have "name" and
|
||||
"path" attributes. The latter is giving the path of the library .so file
|
||||
relative to the standard effect folders: /(vendor|odm|system)/lib(64)?/soundfx/
|
||||
|
||||
Example for a library in "/vendor/lib/soundfx/lib.so":
|
||||
<library name="name" path="lib.so"/>
|
||||
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:sequence>
|
||||
<xs:element name="library" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="name" type="xs:string" use="required"/>
|
||||
<xs:attribute name="path" type="aec:relativePathType" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="effectImplType">
|
||||
<xs:attribute name="library" type="xs:string" use="required"/>
|
||||
<xs:attribute name="uuid" type="aec:uuidType" use="required"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="effectType">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="aec:effectImplType">
|
||||
<xs:attribute name="name" type="xs:string" use="required"/>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="effectProxyType">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="aec:effectType">
|
||||
<xs:sequence>
|
||||
<xs:element name="libsw" type="aec:effectImplType"/>
|
||||
<xs:element name="libhw" type="aec:effectImplType"/>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="effectsType">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
List of effects to load. Each effect element must contain "name",
|
||||
"library", and "uuid" attrs. The value of the "library" attr must
|
||||
correspond to the name of a "library" element. The name of the effect
|
||||
element is indicative, only the value of the "uuid" element designates
|
||||
the effect for the audio framework. The uuid is the implementation
|
||||
specific UUID as specified by the effect vendor. This is not the generic
|
||||
effect type UUID.
|
||||
|
||||
For effect proxy implementations, SW and HW implemetations of the effect
|
||||
can be specified.
|
||||
|
||||
Example:
|
||||
|
||||
<effect name="name" library="lib" uuid="uuuu"/>
|
||||
<effectProxy name="proxied" library="proxy" uuid="xxxx">
|
||||
<libsw library="sw_bundle" uuid="yyyy"/>
|
||||
<libhw library="offload_bundle" uuid="zzzz"/>
|
||||
</effectProxy>
|
||||
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:choice maxOccurs="unbounded">
|
||||
<xs:element name="effect" type="aec:effectType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="effectProxy" type="aec:effectProxyType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="streamProcessingType">
|
||||
<xs:sequence>
|
||||
<xs:element name="apply" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="effect" type="xs:string" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="streamPreprocessType">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Audio preprocessing configuration. The processing configuration consists
|
||||
of a list of elements each describing processing settings for a given
|
||||
input stream. Valid input stream types are listed in "streamInputType".
|
||||
|
||||
Each stream element contains a list of "apply" elements. The value of the
|
||||
"effect" attr must correspond to the name of an "effect" element.
|
||||
|
||||
Example:
|
||||
|
||||
<stream type="voice_communication">
|
||||
<apply effect="effect1"/>
|
||||
<apply effect="effect2"/>
|
||||
</stream>
|
||||
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexContent>
|
||||
<xs:extension base="aec:streamProcessingType">
|
||||
<xs:attribute name="type" type="aec:streamInputType" use="required"/>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="streamPostprocessType">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Audio postprocessing configuration. The processing configuration consists
|
||||
of a list of elements each describing processing settings for a given
|
||||
output stream. Valid output stream types are listed in "streamOutputType".
|
||||
|
||||
Each stream element contains a list of "apply" elements. The value of the
|
||||
"effect" attr must correspond to the name of an "effect" element.
|
||||
|
||||
Example:
|
||||
|
||||
<stream type="music">
|
||||
<apply effect="effect1"/>
|
||||
</stream>
|
||||
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexContent>
|
||||
<xs:extension base="aec:streamProcessingType">
|
||||
<xs:attribute name="type" type="aec:streamOutputType" use="required"/>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- Root element -->
|
||||
<xs:element name="audio_effects_conf">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="libraries" type="aec:librariesType"/>
|
||||
<xs:element name="effects" type="aec:effectsType"/>
|
||||
<xs:element name="postprocess" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="stream" type="aec:streamPostprocessType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="preprocess" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="stream" type="aec:streamPreprocessType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="version" type="aec:versionType" use="required"/>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- Keys and references -->
|
||||
<xs:key name="libraryName">
|
||||
<xs:selector xpath="aec:libraries/aec:library"/>
|
||||
<xs:field xpath="@name"/>
|
||||
</xs:key>
|
||||
<xs:keyref name="libraryNameRef1" refer="aec:libraryName">
|
||||
<xs:selector xpath="aec:effects/aec:effect"/>
|
||||
<xs:field xpath="@library"/>
|
||||
</xs:keyref>
|
||||
<xs:keyref name="libraryNameRef2" refer="aec:libraryName">
|
||||
<xs:selector xpath="aec:effects/aec:effect/aec:libsw"/>
|
||||
<xs:field xpath="@library"/>
|
||||
</xs:keyref>
|
||||
<xs:keyref name="libraryNameRef3" refer="aec:libraryName">
|
||||
<xs:selector xpath="aec:effects/aec:effect/aec:libhw"/>
|
||||
<xs:field xpath="@library"/>
|
||||
</xs:keyref>
|
||||
<xs:key name="effectName">
|
||||
<xs:selector xpath="aec:effects/aec:effect"/>
|
||||
<xs:field xpath="@name"/>
|
||||
</xs:key>
|
||||
<xs:keyref name="effectNamePreRef" refer="aec:effectName">
|
||||
<xs:selector xpath="aec:preprocess/aec:stream/aec:apply"/>
|
||||
<xs:field xpath="@effect"/>
|
||||
</xs:keyref>
|
||||
<xs:keyref name="effectNamePostRef" refer="aec:effectName">
|
||||
<xs:selector xpath="aec:postprocess/aec:stream/aec:apply"/>
|
||||
<xs:field xpath="@effect"/>
|
||||
</xs:keyref>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -1,7 +1,11 @@
|
||||
// This file is autogenerated by hidl-gen. Do not edit manually.
|
||||
// This file is autogenerated by hidl-gen -Landroidbp.
|
||||
|
||||
filegroup {
|
||||
name: "android.hardware.automotive.evs@1.0_hal",
|
||||
hidl_interface {
|
||||
name: "android.hardware.automotive.evs@1.0",
|
||||
root: "android.hardware",
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
srcs: [
|
||||
"types.hal",
|
||||
"IEvsCamera.hal",
|
||||
@@ -9,160 +13,16 @@ filegroup {
|
||||
"IEvsDisplay.hal",
|
||||
"IEvsEnumerator.hal",
|
||||
],
|
||||
interfaces: [
|
||||
"android.hidl.base@1.0",
|
||||
],
|
||||
types: [
|
||||
"BufferDesc",
|
||||
"CameraDesc",
|
||||
"DisplayDesc",
|
||||
"DisplayState",
|
||||
"EvsResult",
|
||||
],
|
||||
gen_java: false,
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.automotive.evs@1.0_genc++",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.evs@1.0",
|
||||
srcs: [
|
||||
":android.hardware.automotive.evs@1.0_hal",
|
||||
],
|
||||
out: [
|
||||
"android/hardware/automotive/evs/1.0/types.cpp",
|
||||
"android/hardware/automotive/evs/1.0/EvsCameraAll.cpp",
|
||||
"android/hardware/automotive/evs/1.0/EvsCameraStreamAll.cpp",
|
||||
"android/hardware/automotive/evs/1.0/EvsDisplayAll.cpp",
|
||||
"android/hardware/automotive/evs/1.0/EvsEnumeratorAll.cpp",
|
||||
],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.automotive.evs@1.0_genc++_headers",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.evs@1.0",
|
||||
srcs: [
|
||||
":android.hardware.automotive.evs@1.0_hal",
|
||||
],
|
||||
out: [
|
||||
"android/hardware/automotive/evs/1.0/types.h",
|
||||
"android/hardware/automotive/evs/1.0/hwtypes.h",
|
||||
"android/hardware/automotive/evs/1.0/IEvsCamera.h",
|
||||
"android/hardware/automotive/evs/1.0/IHwEvsCamera.h",
|
||||
"android/hardware/automotive/evs/1.0/BnHwEvsCamera.h",
|
||||
"android/hardware/automotive/evs/1.0/BpHwEvsCamera.h",
|
||||
"android/hardware/automotive/evs/1.0/BsEvsCamera.h",
|
||||
"android/hardware/automotive/evs/1.0/IEvsCameraStream.h",
|
||||
"android/hardware/automotive/evs/1.0/IHwEvsCameraStream.h",
|
||||
"android/hardware/automotive/evs/1.0/BnHwEvsCameraStream.h",
|
||||
"android/hardware/automotive/evs/1.0/BpHwEvsCameraStream.h",
|
||||
"android/hardware/automotive/evs/1.0/BsEvsCameraStream.h",
|
||||
"android/hardware/automotive/evs/1.0/IEvsDisplay.h",
|
||||
"android/hardware/automotive/evs/1.0/IHwEvsDisplay.h",
|
||||
"android/hardware/automotive/evs/1.0/BnHwEvsDisplay.h",
|
||||
"android/hardware/automotive/evs/1.0/BpHwEvsDisplay.h",
|
||||
"android/hardware/automotive/evs/1.0/BsEvsDisplay.h",
|
||||
"android/hardware/automotive/evs/1.0/IEvsEnumerator.h",
|
||||
"android/hardware/automotive/evs/1.0/IHwEvsEnumerator.h",
|
||||
"android/hardware/automotive/evs/1.0/BnHwEvsEnumerator.h",
|
||||
"android/hardware/automotive/evs/1.0/BpHwEvsEnumerator.h",
|
||||
"android/hardware/automotive/evs/1.0/BsEvsEnumerator.h",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "android.hardware.automotive.evs@1.0",
|
||||
defaults: ["hidl-module-defaults"],
|
||||
generated_sources: ["android.hardware.automotive.evs@1.0_genc++"],
|
||||
generated_headers: ["android.hardware.automotive.evs@1.0_genc++_headers"],
|
||||
export_generated_headers: ["android.hardware.automotive.evs@1.0_genc++_headers"],
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"libcutils",
|
||||
],
|
||||
export_shared_lib_headers: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"libutils",
|
||||
],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.automotive.evs@1.0-adapter-helper_genc++",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.evs@1.0",
|
||||
srcs: [
|
||||
":android.hardware.automotive.evs@1.0_hal",
|
||||
],
|
||||
out: [
|
||||
"android/hardware/automotive/evs/1.0/AEvsCamera.cpp",
|
||||
"android/hardware/automotive/evs/1.0/AEvsCameraStream.cpp",
|
||||
"android/hardware/automotive/evs/1.0/AEvsDisplay.cpp",
|
||||
"android/hardware/automotive/evs/1.0/AEvsEnumerator.cpp",
|
||||
],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.automotive.evs@1.0-adapter-helper_genc++_headers",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.evs@1.0",
|
||||
srcs: [
|
||||
":android.hardware.automotive.evs@1.0_hal",
|
||||
],
|
||||
out: [
|
||||
"android/hardware/automotive/evs/1.0/AEvsCamera.h",
|
||||
"android/hardware/automotive/evs/1.0/AEvsCameraStream.h",
|
||||
"android/hardware/automotive/evs/1.0/AEvsDisplay.h",
|
||||
"android/hardware/automotive/evs/1.0/AEvsEnumerator.h",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
cc_library {
|
||||
name: "android.hardware.automotive.evs@1.0-adapter-helper",
|
||||
defaults: ["hidl-module-defaults"],
|
||||
generated_sources: ["android.hardware.automotive.evs@1.0-adapter-helper_genc++"],
|
||||
generated_headers: ["android.hardware.automotive.evs@1.0-adapter-helper_genc++_headers"],
|
||||
export_generated_headers: ["android.hardware.automotive.evs@1.0-adapter-helper_genc++_headers"],
|
||||
vendor_available: true,
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"libcutils",
|
||||
"libhidladapter",
|
||||
"android.hardware.automotive.evs@1.0",
|
||||
"android.hidl.base@1.0-adapter-helper",
|
||||
],
|
||||
export_shared_lib_headers: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"libutils",
|
||||
"libhidladapter",
|
||||
"android.hardware.automotive.evs@1.0",
|
||||
"android.hidl.base@1.0-adapter-helper",
|
||||
],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.automotive.evs@1.0-adapter_genc++",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-main -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.evs@1.0",
|
||||
out: ["main.cpp"]
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "android.hardware.automotive.evs@1.0-adapter",
|
||||
defaults: ["hidl-module-defaults"],
|
||||
shared_libs: [
|
||||
"libhidladapter",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libutils",
|
||||
"android.hardware.automotive.evs@1.0",
|
||||
"android.hardware.automotive.evs@1.0-adapter-helper",
|
||||
],
|
||||
generated_sources: ["android.hardware.automotive.evs@1.0-adapter_genc++"],
|
||||
}
|
||||
|
||||
31
automotive/evs/1.0/default/Android.bp
Normal file
31
automotive/evs/1.0/default/Android.bp
Normal file
@@ -0,0 +1,31 @@
|
||||
cc_binary {
|
||||
name: "android.hardware.automotive.evs@1.0-service",
|
||||
defaults: ["hidl_defaults"],
|
||||
proprietary: true,
|
||||
relative_install_path: "hw",
|
||||
srcs: [
|
||||
"service.cpp",
|
||||
"EvsCamera.cpp",
|
||||
"EvsEnumerator.cpp",
|
||||
"EvsDisplay.cpp"
|
||||
],
|
||||
init_rc: ["android.hardware.automotive.evs@1.0-service.rc"],
|
||||
|
||||
shared_libs: [
|
||||
"android.hardware.automotive.evs@1.0",
|
||||
"libui",
|
||||
"libbase",
|
||||
"libbinder",
|
||||
"libcutils",
|
||||
"libhardware",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"liblog",
|
||||
"libutils",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-O0",
|
||||
"-g",
|
||||
],
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
LOCAL_PATH:=$(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := android.hardware.automotive.evs@1.0-service
|
||||
LOCAL_INIT_RC := android.hardware.automotive.evs@1.0-service.rc
|
||||
LOCAL_MODULE_RELATIVE_PATH := hw
|
||||
LOCAL_VENDOR_MODULE := true
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
service.cpp \
|
||||
EvsCamera.cpp \
|
||||
EvsEnumerator.cpp \
|
||||
EvsDisplay.cpp \
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
android.hardware.automotive.evs@1.0 \
|
||||
libui \
|
||||
libbase \
|
||||
libbinder \
|
||||
libcutils \
|
||||
libhardware \
|
||||
libhidlbase \
|
||||
libhidltransport \
|
||||
liblog \
|
||||
libutils \
|
||||
|
||||
LOCAL_CFLAGS := -O0 -g -Wall -Werror
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
@@ -15,10 +15,10 @@
|
||||
//
|
||||
|
||||
cc_test {
|
||||
name: "VtsEvsV1_0Target",
|
||||
name: "VtsHalEvsV1_0Target",
|
||||
|
||||
srcs: [
|
||||
"VtsEvsV1_0TargetTest.cpp",
|
||||
"VtsHalEvsV1_0TargetTest.cpp",
|
||||
"FrameHandler.cpp",
|
||||
"FormatConvert.cpp"
|
||||
],
|
||||
@@ -43,4 +43,3 @@ cc_test {
|
||||
"-g",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,13 @@
|
||||
#define LOG_TAG "VtsHalEvsTest"
|
||||
|
||||
|
||||
// TODO: How should we configure these values to target appropriate hardware?
|
||||
const static char kEnumeratorName[] = "EvsEnumeratorHw-Mock";
|
||||
// Note: We have't got a great way to indicate which target
|
||||
// should be tested, so we'll leave the interface served by the
|
||||
// default (mock) EVS driver here for easy reference. All
|
||||
// actual EVS drivers should serve on the EvsEnumeratorHw name,
|
||||
// however, so the code is checked in that way.
|
||||
//const static char kEnumeratorName[] = "EvsEnumeratorHw-Mock";
|
||||
const static char kEnumeratorName[] = "EvsEnumeratorHw";
|
||||
|
||||
|
||||
// These values are called out in the EVS design doc (as of Mar 8, 2017)
|
||||
@@ -474,4 +479,4 @@ TEST_F(EvsHidlTest, CameraToDisplayRoundTrip) {
|
||||
|
||||
// Explicitly release the display
|
||||
pEnumerator->closeDisplay(pDisplay);
|
||||
}
|
||||
}
|
||||
@@ -1,150 +1,85 @@
|
||||
// This file is autogenerated by hidl-gen. Do not edit manually.
|
||||
// This file is autogenerated by hidl-gen -Landroidbp.
|
||||
|
||||
filegroup {
|
||||
name: "android.hardware.automotive.vehicle@2.0_hal",
|
||||
hidl_interface {
|
||||
name: "android.hardware.automotive.vehicle@2.0",
|
||||
root: "android.hardware",
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
srcs: [
|
||||
"types.hal",
|
||||
"IVehicle.hal",
|
||||
"IVehicleCallback.hal",
|
||||
],
|
||||
interfaces: [
|
||||
"android.hidl.base@1.0",
|
||||
],
|
||||
types: [
|
||||
"DiagnosticFloatSensorIndex",
|
||||
"DiagnosticIntegerSensorIndex",
|
||||
"Obd2CommonIgnitionMonitors",
|
||||
"Obd2CompressionIgnitionMonitors",
|
||||
"Obd2FuelSystemStatus",
|
||||
"Obd2FuelType",
|
||||
"Obd2IgnitionMonitorKind",
|
||||
"Obd2SecondaryAirStatus",
|
||||
"Obd2SparkIgnitionMonitors",
|
||||
"StatusCode",
|
||||
"SubscribeFlags",
|
||||
"SubscribeOptions",
|
||||
"VehicleApPowerBootupReason",
|
||||
"VehicleApPowerSetState",
|
||||
"VehicleApPowerState",
|
||||
"VehicleApPowerStateConfigFlag",
|
||||
"VehicleApPowerStateIndex",
|
||||
"VehicleApPowerStateShutdownParam",
|
||||
"VehicleArea",
|
||||
"VehicleAreaConfig",
|
||||
"VehicleAreaDoor",
|
||||
"VehicleAreaMirror",
|
||||
"VehicleAreaSeat",
|
||||
"VehicleAreaWindow",
|
||||
"VehicleAreaZone",
|
||||
"VehicleAudioContextFlag",
|
||||
"VehicleAudioExtFocusFlag",
|
||||
"VehicleAudioFocusIndex",
|
||||
"VehicleAudioFocusRequest",
|
||||
"VehicleAudioFocusState",
|
||||
"VehicleAudioHwVariantConfigFlag",
|
||||
"VehicleAudioRoutingPolicyIndex",
|
||||
"VehicleAudioStream",
|
||||
"VehicleAudioStreamFlag",
|
||||
"VehicleAudioVolumeCapabilityFlag",
|
||||
"VehicleAudioVolumeIndex",
|
||||
"VehicleAudioVolumeLimitIndex",
|
||||
"VehicleAudioVolumeState",
|
||||
"VehicleDisplay",
|
||||
"VehicleDrivingStatus",
|
||||
"VehicleGear",
|
||||
"VehicleHvacFanDirection",
|
||||
"VehicleHwKeyInputAction",
|
||||
"VehicleIgnitionState",
|
||||
"VehicleInstrumentClusterType",
|
||||
"VehiclePropConfig",
|
||||
"VehiclePropValue",
|
||||
"VehicleProperty",
|
||||
"VehiclePropertyAccess",
|
||||
"VehiclePropertyChangeMode",
|
||||
"VehiclePropertyGroup",
|
||||
"VehiclePropertyOperation",
|
||||
"VehiclePropertyType",
|
||||
"VehicleRadioConstants",
|
||||
"VehicleTurnSignal",
|
||||
"VehicleUnit",
|
||||
"VmsAvailabilityStateIntegerValuesIndex",
|
||||
"VmsBaseMessageIntegerValuesIndex",
|
||||
"VmsMessageType",
|
||||
"VmsMessageWithLayerAndPublisherIdIntegerValuesIndex",
|
||||
"VmsMessageWithLayerIntegerValuesIndex",
|
||||
"VmsOfferingMessageIntegerValuesIndex",
|
||||
"VmsSubscriptionsStateIntegerValuesIndex",
|
||||
"Wheel",
|
||||
],
|
||||
gen_java: true,
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.automotive.vehicle@2.0_genc++",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.0",
|
||||
srcs: [
|
||||
":android.hardware.automotive.vehicle@2.0_hal",
|
||||
],
|
||||
out: [
|
||||
"android/hardware/automotive/vehicle/2.0/types.cpp",
|
||||
"android/hardware/automotive/vehicle/2.0/VehicleAll.cpp",
|
||||
"android/hardware/automotive/vehicle/2.0/VehicleCallbackAll.cpp",
|
||||
],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.automotive.vehicle@2.0_genc++_headers",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.0",
|
||||
srcs: [
|
||||
":android.hardware.automotive.vehicle@2.0_hal",
|
||||
],
|
||||
out: [
|
||||
"android/hardware/automotive/vehicle/2.0/types.h",
|
||||
"android/hardware/automotive/vehicle/2.0/hwtypes.h",
|
||||
"android/hardware/automotive/vehicle/2.0/IVehicle.h",
|
||||
"android/hardware/automotive/vehicle/2.0/IHwVehicle.h",
|
||||
"android/hardware/automotive/vehicle/2.0/BnHwVehicle.h",
|
||||
"android/hardware/automotive/vehicle/2.0/BpHwVehicle.h",
|
||||
"android/hardware/automotive/vehicle/2.0/BsVehicle.h",
|
||||
"android/hardware/automotive/vehicle/2.0/IVehicleCallback.h",
|
||||
"android/hardware/automotive/vehicle/2.0/IHwVehicleCallback.h",
|
||||
"android/hardware/automotive/vehicle/2.0/BnHwVehicleCallback.h",
|
||||
"android/hardware/automotive/vehicle/2.0/BpHwVehicleCallback.h",
|
||||
"android/hardware/automotive/vehicle/2.0/BsVehicleCallback.h",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "android.hardware.automotive.vehicle@2.0",
|
||||
defaults: ["hidl-module-defaults"],
|
||||
generated_sources: ["android.hardware.automotive.vehicle@2.0_genc++"],
|
||||
generated_headers: ["android.hardware.automotive.vehicle@2.0_genc++_headers"],
|
||||
export_generated_headers: ["android.hardware.automotive.vehicle@2.0_genc++_headers"],
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"libcutils",
|
||||
],
|
||||
export_shared_lib_headers: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"libutils",
|
||||
],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.automotive.vehicle@2.0-adapter-helper_genc++",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.0",
|
||||
srcs: [
|
||||
":android.hardware.automotive.vehicle@2.0_hal",
|
||||
],
|
||||
out: [
|
||||
"android/hardware/automotive/vehicle/2.0/AVehicle.cpp",
|
||||
"android/hardware/automotive/vehicle/2.0/AVehicleCallback.cpp",
|
||||
],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.automotive.vehicle@2.0-adapter-helper_genc++_headers",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.0",
|
||||
srcs: [
|
||||
":android.hardware.automotive.vehicle@2.0_hal",
|
||||
],
|
||||
out: [
|
||||
"android/hardware/automotive/vehicle/2.0/AVehicle.h",
|
||||
"android/hardware/automotive/vehicle/2.0/AVehicleCallback.h",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
cc_library {
|
||||
name: "android.hardware.automotive.vehicle@2.0-adapter-helper",
|
||||
defaults: ["hidl-module-defaults"],
|
||||
generated_sources: ["android.hardware.automotive.vehicle@2.0-adapter-helper_genc++"],
|
||||
generated_headers: ["android.hardware.automotive.vehicle@2.0-adapter-helper_genc++_headers"],
|
||||
export_generated_headers: ["android.hardware.automotive.vehicle@2.0-adapter-helper_genc++_headers"],
|
||||
vendor_available: true,
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"libcutils",
|
||||
"libhidladapter",
|
||||
"android.hardware.automotive.vehicle@2.0",
|
||||
"android.hidl.base@1.0-adapter-helper",
|
||||
],
|
||||
export_shared_lib_headers: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"libutils",
|
||||
"libhidladapter",
|
||||
"android.hardware.automotive.vehicle@2.0",
|
||||
"android.hidl.base@1.0-adapter-helper",
|
||||
],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.automotive.vehicle@2.0-adapter_genc++",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-main -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.0",
|
||||
out: ["main.cpp"]
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "android.hardware.automotive.vehicle@2.0-adapter",
|
||||
defaults: ["hidl-module-defaults"],
|
||||
shared_libs: [
|
||||
"libhidladapter",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libutils",
|
||||
"android.hardware.automotive.vehicle@2.0",
|
||||
"android.hardware.automotive.vehicle@2.0-adapter-helper",
|
||||
],
|
||||
generated_sources: ["android.hardware.automotive.vehicle@2.0-adapter_genc++"],
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
117
automotive/vehicle/2.0/default/Android.bp
Normal file
117
automotive/vehicle/2.0/default/Android.bp
Normal file
@@ -0,0 +1,117 @@
|
||||
// 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.
|
||||
|
||||
cc_defaults {
|
||||
name: "vhal_v2_0_defaults",
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"android.hardware.automotive.vehicle@2.0",
|
||||
],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "vhal_v2_0_common_headers",
|
||||
vendor: true,
|
||||
export_include_dirs: ["common/include/vhal_v2_0"],
|
||||
}
|
||||
|
||||
// Vehicle reference implementation lib
|
||||
cc_library_static {
|
||||
name: "android.hardware.automotive.vehicle@2.0-manager-lib",
|
||||
vendor: true,
|
||||
defaults: ["vhal_v2_0_defaults"],
|
||||
srcs: [
|
||||
"common/src/Obd2SensorStore.cpp",
|
||||
"common/src/SubscriptionManager.cpp",
|
||||
"common/src/VehicleHalManager.cpp",
|
||||
"common/src/VehicleObjectPool.cpp",
|
||||
"common/src/VehiclePropertyStore.cpp",
|
||||
"common/src/VehicleUtils.cpp",
|
||||
],
|
||||
local_include_dirs: ["common/include/vhal_v2_0"],
|
||||
export_include_dirs: ["common/include"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "android.hardware.automotive.vehicle@2.0-manager-lib-shared",
|
||||
vendor: true,
|
||||
static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
|
||||
export_static_lib_headers: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
|
||||
}
|
||||
|
||||
// Vehicle default VehicleHAL implementation
|
||||
cc_library_static {
|
||||
name: "android.hardware.automotive.vehicle@2.0-default-impl-lib",
|
||||
vendor: true,
|
||||
defaults: ["vhal_v2_0_defaults"],
|
||||
srcs: [
|
||||
"impl/vhal_v2_0/EmulatedVehicleHal.cpp",
|
||||
"impl/vhal_v2_0/VehicleEmulator.cpp",
|
||||
"impl/vhal_v2_0/PipeComm.cpp",
|
||||
"impl/vhal_v2_0/SocketComm.cpp",
|
||||
],
|
||||
local_include_dirs: ["common/include/vhal_v2_0"],
|
||||
export_include_dirs: ["impl"],
|
||||
whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libprotobuf-cpp-lite",
|
||||
],
|
||||
static_libs: [
|
||||
"libqemu_pipe",
|
||||
"android.hardware.automotive.vehicle@2.0-libproto-native",
|
||||
],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "android.hardware.automotive.vehicle@2.0-manager-unit-tests",
|
||||
vendor: true,
|
||||
defaults: ["vhal_v2_0_defaults"],
|
||||
whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
|
||||
srcs: [
|
||||
"tests/RecurrentTimer_test.cpp",
|
||||
"tests/SubscriptionManager_test.cpp",
|
||||
"tests/VehicleHalManager_test.cpp",
|
||||
"tests/VehicleObjectPool_test.cpp",
|
||||
"tests/VehiclePropConfigIndex_test.cpp",
|
||||
],
|
||||
header_libs: ["libbase_headers"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.automotive.vehicle@2.0-service",
|
||||
defaults: ["vhal_v2_0_defaults"],
|
||||
init_rc: ["android.hardware.automotive.vehicle@2.0-service.rc"],
|
||||
vendor: true,
|
||||
relative_install_path: "hw",
|
||||
srcs: ["VehicleService.cpp"],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libprotobuf-cpp-lite",
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.automotive.vehicle@2.0-manager-lib",
|
||||
"android.hardware.automotive.vehicle@2.0-default-impl-lib",
|
||||
"android.hardware.automotive.vehicle@2.0-libproto-native",
|
||||
"libqemu_pipe",
|
||||
],
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
# Copyright (C) 2016 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
vhal_v2_0 = android.hardware.automotive.vehicle@2.0
|
||||
|
||||
###############################################################################
|
||||
# Vehicle reference implementation lib
|
||||
###############################################################################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := $(vhal_v2_0)-manager-lib
|
||||
LOCAL_SRC_FILES := \
|
||||
common/src/SubscriptionManager.cpp \
|
||||
common/src/VehicleHalManager.cpp \
|
||||
common/src/VehicleObjectPool.cpp \
|
||||
common/src/VehiclePropertyStore.cpp \
|
||||
common/src/VehicleUtils.cpp \
|
||||
|
||||
LOCAL_CFLAGS := -Wall -Werror
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/common/include/vhal_v2_0
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := \
|
||||
$(LOCAL_PATH)/common/include
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libhidlbase \
|
||||
libhidltransport \
|
||||
liblog \
|
||||
libutils \
|
||||
$(vhal_v2_0) \
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := $(vhal_v2_0)-manager-lib-shared
|
||||
LOCAL_SRC_FILES := \
|
||||
common/src/SubscriptionManager.cpp \
|
||||
common/src/VehicleHalManager.cpp \
|
||||
common/src/VehicleObjectPool.cpp \
|
||||
common/src/VehiclePropertyStore.cpp \
|
||||
common/src/VehicleUtils.cpp \
|
||||
|
||||
LOCAL_CFLAGS := -Wall -Werror
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/common/include/vhal_v2_0
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := \
|
||||
$(LOCAL_PATH)/common/include
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libhidlbase \
|
||||
libhidltransport \
|
||||
liblog \
|
||||
libutils \
|
||||
$(vhal_v2_0) \
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
###############################################################################
|
||||
# Vehicle HAL Protobuf library
|
||||
###############################################################################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(call all-proto-files-under, impl/vhal_v2_0/proto)
|
||||
|
||||
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
|
||||
|
||||
LOCAL_MODULE := $(vhal_v2_0)-libproto-native
|
||||
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_STRIP_MODULE := keep_symbols
|
||||
|
||||
generated_sources_dir := $(call local-generated-sources-dir)
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := \
|
||||
$(generated_sources_dir)/proto/$(LOCAL_PATH)/impl/vhal_v2_0/proto
|
||||
|
||||
LOCAL_CFLAGS += -Wall -Wextra -Werror
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Vehicle default VehicleHAL implementation
|
||||
###############################################################################
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE:= $(vhal_v2_0)-default-impl-lib
|
||||
LOCAL_SRC_FILES:= \
|
||||
impl/vhal_v2_0/EmulatedVehicleHal.cpp \
|
||||
impl/vhal_v2_0/VehicleEmulator.cpp \
|
||||
impl/vhal_v2_0/PipeComm.cpp \
|
||||
impl/vhal_v2_0/SocketComm.cpp \
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/impl/vhal_v2_0
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := \
|
||||
$(LOCAL_PATH)/impl
|
||||
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := \
|
||||
$(vhal_v2_0)-manager-lib \
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libbase \
|
||||
libhidlbase \
|
||||
libhidltransport \
|
||||
liblog \
|
||||
libprotobuf-cpp-lite \
|
||||
libutils \
|
||||
$(vhal_v2_0) \
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libqemu_pipe \
|
||||
$(vhal_v2_0)-libproto-native \
|
||||
|
||||
LOCAL_CFLAGS += -Wall -Wextra -Werror
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Vehicle reference implementation unit tests
|
||||
###############################################################################
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE:= $(vhal_v2_0)-manager-unit-tests
|
||||
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := \
|
||||
$(vhal_v2_0)-manager-lib \
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
tests/RecurrentTimer_test.cpp \
|
||||
tests/SubscriptionManager_test.cpp \
|
||||
tests/VehicleHalManager_test.cpp \
|
||||
tests/VehicleObjectPool_test.cpp \
|
||||
tests/VehiclePropConfigIndex_test.cpp \
|
||||
|
||||
LOCAL_HEADER_LIBRARIES := \
|
||||
libbase_headers
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libhidlbase \
|
||||
libhidltransport \
|
||||
liblog \
|
||||
libutils \
|
||||
$(vhal_v2_0) \
|
||||
|
||||
LOCAL_CFLAGS += -Wall -Wextra -Werror
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
include $(BUILD_NATIVE_TEST)
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Vehicle HAL service
|
||||
###############################################################################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := $(vhal_v2_0)-service
|
||||
LOCAL_INIT_RC := $(vhal_v2_0)-service.rc
|
||||
LOCAL_PROPRIETARY_MODULE := true
|
||||
LOCAL_MODULE_RELATIVE_PATH := hw
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
VehicleService.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libbase \
|
||||
libhidlbase \
|
||||
libhidltransport \
|
||||
liblog \
|
||||
libprotobuf-cpp-lite \
|
||||
libutils \
|
||||
$(vhal_v2_0) \
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
$(vhal_v2_0)-manager-lib \
|
||||
$(vhal_v2_0)-default-impl-lib \
|
||||
$(vhal_v2_0)-libproto-native \
|
||||
libqemu_pipe \
|
||||
|
||||
LOCAL_CFLAGS += -Wall -Wextra -Werror
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
@@ -14,38 +14,37 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef android_hardware_automotive_vehicle_V2_1_Obd2SensorStore_H_
|
||||
#define android_hardware_automotive_vehicle_V2_1_Obd2SensorStore_H_
|
||||
#ifndef android_hardware_automotive_vehicle_V2_0_Obd2SensorStore_H_
|
||||
#define android_hardware_automotive_vehicle_V2_0_Obd2SensorStore_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <android/hardware/automotive/vehicle/2.1/types.h>
|
||||
#include <android/hardware/automotive/vehicle/2.0/types.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
namespace V2_1 {
|
||||
namespace V2_0 {
|
||||
|
||||
// This class wraps all the logic required to create an OBD2 frame.
|
||||
// It allows storing sensor values, setting appropriate bitmasks as needed,
|
||||
// and returning appropriately laid out storage of sensor values suitable
|
||||
// for being returned via a VehicleHal implementation.
|
||||
class Obd2SensorStore {
|
||||
public:
|
||||
public:
|
||||
// Creates a sensor storage with a given number of vendor-specific sensors.
|
||||
Obd2SensorStore(size_t numVendorIntegerSensors,
|
||||
size_t numVendorFloatSensors);
|
||||
Obd2SensorStore(size_t numVendorIntegerSensors, size_t numVendorFloatSensors);
|
||||
|
||||
// Stores an integer-valued sensor.
|
||||
V2_0::StatusCode setIntegerSensor(Obd2IntegerSensorIndex index, int32_t value);
|
||||
StatusCode setIntegerSensor(DiagnosticIntegerSensorIndex index, int32_t value);
|
||||
// Stores an integer-valued sensor.
|
||||
V2_0::StatusCode setIntegerSensor(size_t index, int32_t value);
|
||||
StatusCode setIntegerSensor(size_t index, int32_t value);
|
||||
|
||||
// Stores a float-valued sensor.
|
||||
V2_0::StatusCode setFloatSensor(Obd2FloatSensorIndex index, float value);
|
||||
StatusCode setFloatSensor(DiagnosticFloatSensorIndex index, float value);
|
||||
// Stores a float-valued sensor.
|
||||
V2_0::StatusCode setFloatSensor(size_t index, float value);
|
||||
StatusCode setFloatSensor(size_t index, float value);
|
||||
|
||||
// Returns a vector that contains all integer sensors stored.
|
||||
const std::vector<int32_t>& getIntegerSensors() const;
|
||||
@@ -55,11 +54,11 @@ public:
|
||||
const std::vector<uint8_t>& getSensorsBitmask() const;
|
||||
|
||||
// Given a stringValue, fill in a VehiclePropValue
|
||||
void fillPropValue(const std::string& dtc, V2_0::VehiclePropValue *propValue) const;
|
||||
void fillPropValue(const std::string& dtc, VehiclePropValue* propValue) const;
|
||||
|
||||
private:
|
||||
private:
|
||||
class BitmaskInVector {
|
||||
public:
|
||||
public:
|
||||
BitmaskInVector(size_t numBits = 0);
|
||||
void resize(size_t numBits);
|
||||
bool get(size_t index) const;
|
||||
@@ -67,7 +66,7 @@ private:
|
||||
|
||||
const std::vector<uint8_t>& getBitmask() const;
|
||||
|
||||
private:
|
||||
private:
|
||||
std::vector<uint8_t> mStorage;
|
||||
};
|
||||
|
||||
@@ -76,7 +75,7 @@ private:
|
||||
BitmaskInVector mSensorsBitmask;
|
||||
};
|
||||
|
||||
} // namespace V2_1
|
||||
} // namespace V2_0
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
@@ -23,23 +23,21 @@ namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
namespace V2_1 {
|
||||
namespace V2_0 {
|
||||
|
||||
Obd2SensorStore::BitmaskInVector::BitmaskInVector(size_t numBits)
|
||||
{
|
||||
Obd2SensorStore::BitmaskInVector::BitmaskInVector(size_t numBits) {
|
||||
resize(numBits);
|
||||
}
|
||||
|
||||
void Obd2SensorStore::BitmaskInVector::resize(size_t numBits) {
|
||||
mStorage = std::vector<uint8_t>((numBits+7)/8, 0);
|
||||
mStorage = std::vector<uint8_t>((numBits + 7) / 8, 0);
|
||||
}
|
||||
|
||||
void Obd2SensorStore::BitmaskInVector::set(size_t index, bool value) {
|
||||
const size_t byteIndex = index / 8;
|
||||
const size_t bitIndex = index % 8;
|
||||
const uint8_t byte = mStorage[byteIndex];
|
||||
uint8_t newValue = value ? (byte | (1 << bitIndex)) :
|
||||
(byte & ~(1 << bitIndex));
|
||||
uint8_t newValue = value ? (byte | (1 << bitIndex)) : (byte & ~(1 << bitIndex));
|
||||
mStorage[byteIndex] = newValue;
|
||||
}
|
||||
|
||||
@@ -54,37 +52,33 @@ const std::vector<uint8_t>& Obd2SensorStore::BitmaskInVector::getBitmask() const
|
||||
return mStorage;
|
||||
}
|
||||
|
||||
Obd2SensorStore::Obd2SensorStore(size_t numVendorIntegerSensors,
|
||||
size_t numVendorFloatSensors) {
|
||||
// because the last index is valid *inclusive*
|
||||
const size_t numSystemIntegerSensors = V2_0::toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX)+1;
|
||||
const size_t numSystemFloatSensors = V2_0::toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX)+1;
|
||||
mIntegerSensors = std::vector<int32_t>(
|
||||
numSystemIntegerSensors+numVendorIntegerSensors, 0);
|
||||
mFloatSensors = std::vector<float>(
|
||||
numSystemFloatSensors+numVendorFloatSensors, 0);
|
||||
mSensorsBitmask.resize(mIntegerSensors.size()+mFloatSensors.size());
|
||||
Obd2SensorStore::Obd2SensorStore(size_t numVendorIntegerSensors, size_t numVendorFloatSensors) {
|
||||
// because the last index is valid *inclusive*
|
||||
const size_t numSystemIntegerSensors =
|
||||
toInt(DiagnosticIntegerSensorIndex::LAST_SYSTEM_INDEX) + 1;
|
||||
const size_t numSystemFloatSensors = toInt(DiagnosticFloatSensorIndex::LAST_SYSTEM_INDEX) + 1;
|
||||
mIntegerSensors = std::vector<int32_t>(numSystemIntegerSensors + numVendorIntegerSensors, 0);
|
||||
mFloatSensors = std::vector<float>(numSystemFloatSensors + numVendorFloatSensors, 0);
|
||||
mSensorsBitmask.resize(mIntegerSensors.size() + mFloatSensors.size());
|
||||
}
|
||||
|
||||
V2_0::StatusCode Obd2SensorStore::setIntegerSensor(Obd2IntegerSensorIndex index,
|
||||
int32_t value) {
|
||||
return setIntegerSensor(V2_0::toInt(index), value);
|
||||
StatusCode Obd2SensorStore::setIntegerSensor(DiagnosticIntegerSensorIndex index, int32_t value) {
|
||||
return setIntegerSensor(toInt(index), value);
|
||||
}
|
||||
V2_0::StatusCode Obd2SensorStore::setFloatSensor(Obd2FloatSensorIndex index,
|
||||
float value) {
|
||||
return setFloatSensor(V2_0::toInt(index), value);
|
||||
StatusCode Obd2SensorStore::setFloatSensor(DiagnosticFloatSensorIndex index, float value) {
|
||||
return setFloatSensor(toInt(index), value);
|
||||
}
|
||||
|
||||
V2_0::StatusCode Obd2SensorStore::setIntegerSensor(size_t index, int32_t value) {
|
||||
StatusCode Obd2SensorStore::setIntegerSensor(size_t index, int32_t value) {
|
||||
mIntegerSensors[index] = value;
|
||||
mSensorsBitmask.set(index, true);
|
||||
return V2_0::StatusCode::OK;
|
||||
return StatusCode::OK;
|
||||
}
|
||||
|
||||
V2_0::StatusCode Obd2SensorStore::setFloatSensor(size_t index, float value) {
|
||||
StatusCode Obd2SensorStore::setFloatSensor(size_t index, float value) {
|
||||
mFloatSensors[index] = value;
|
||||
mSensorsBitmask.set(index + mIntegerSensors.size(), true);
|
||||
return V2_0::StatusCode::OK;
|
||||
return StatusCode::OK;
|
||||
}
|
||||
|
||||
const std::vector<int32_t>& Obd2SensorStore::getIntegerSensors() const {
|
||||
@@ -99,8 +93,7 @@ const std::vector<uint8_t>& Obd2SensorStore::getSensorsBitmask() const {
|
||||
return mSensorsBitmask.getBitmask();
|
||||
}
|
||||
|
||||
void Obd2SensorStore::fillPropValue(const std::string& dtc,
|
||||
V2_0::VehiclePropValue *propValue) const {
|
||||
void Obd2SensorStore::fillPropValue(const std::string& dtc, VehiclePropValue* propValue) const {
|
||||
propValue->timestamp = elapsedRealtimeNano();
|
||||
propValue->value.int32Values = getIntegerSensors();
|
||||
propValue->value.floatValues = getFloatSensors();
|
||||
@@ -108,8 +101,6 @@ void Obd2SensorStore::fillPropValue(const std::string& dtc,
|
||||
propValue->value.stringValue = dtc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace V2_0
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
@@ -27,6 +27,18 @@ namespace vehicle {
|
||||
namespace V2_0 {
|
||||
|
||||
namespace impl {
|
||||
//
|
||||
// Some handy constants to avoid conversions from enum to int.
|
||||
constexpr int ABS_ACTIVE = (int)VehicleProperty::ABS_ACTIVE;
|
||||
constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME;
|
||||
constexpr int OBD2_FREEZE_FRAME = (int)VehicleProperty::OBD2_FREEZE_FRAME;
|
||||
constexpr int OBD2_FREEZE_FRAME_INFO = (int)VehicleProperty::OBD2_FREEZE_FRAME_INFO;
|
||||
constexpr int OBD2_FREEZE_FRAME_CLEAR = (int)VehicleProperty::OBD2_FREEZE_FRAME_CLEAR;
|
||||
constexpr int TRACTION_CONTROL_ACTIVE = (int)VehicleProperty::TRACTION_CONTROL_ACTIVE;
|
||||
constexpr int VEHICLE_MAP_SERVICE = (int)VehicleProperty::VEHICLE_MAP_SERVICE;
|
||||
constexpr int WHEEL_TICK = (int)VehicleProperty::WHEEL_TICK;
|
||||
constexpr int ALL_WHEELS =
|
||||
(int)(Wheel::LEFT_FRONT | Wheel::RIGHT_FRONT | Wheel::LEFT_REAR | Wheel::RIGHT_REAR);
|
||||
|
||||
/*
|
||||
* This property is used for test purpose to generate fake events.
|
||||
@@ -283,8 +295,68 @@ const ConfigDeclaration kVehicleProperties[]{
|
||||
.access = VehiclePropertyAccess::READ,
|
||||
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
|
||||
},
|
||||
.initialValue = {.int32Values = {1}}}
|
||||
.initialValue = {.int32Values = {1}}},
|
||||
|
||||
{
|
||||
.config =
|
||||
{
|
||||
.prop = WHEEL_TICK,
|
||||
.access = VehiclePropertyAccess::READ,
|
||||
.changeMode = VehiclePropertyChangeMode::CONTINUOUS,
|
||||
.configArray = {ALL_WHEELS, 50000, 50000, 50000, 50000},
|
||||
.minSampleRate = 1.0f,
|
||||
.maxSampleRate = 100.0f,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
.config =
|
||||
{
|
||||
.prop = ABS_ACTIVE,
|
||||
.access = VehiclePropertyAccess::READ,
|
||||
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
.config =
|
||||
{
|
||||
.prop = TRACTION_CONTROL_ACTIVE,
|
||||
.access = VehiclePropertyAccess::READ,
|
||||
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
.config = {.prop = OBD2_LIVE_FRAME,
|
||||
.access = VehiclePropertyAccess::READ,
|
||||
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
|
||||
.configArray = {0, 0}},
|
||||
},
|
||||
|
||||
{
|
||||
.config = {.prop = OBD2_FREEZE_FRAME,
|
||||
.access = VehiclePropertyAccess::READ,
|
||||
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
|
||||
.configArray = {0, 0}},
|
||||
},
|
||||
|
||||
{
|
||||
.config = {.prop = OBD2_FREEZE_FRAME_INFO,
|
||||
.access = VehiclePropertyAccess::READ,
|
||||
.changeMode = VehiclePropertyChangeMode::ON_CHANGE},
|
||||
},
|
||||
|
||||
{
|
||||
.config = {.prop = OBD2_FREEZE_FRAME_CLEAR,
|
||||
.access = VehiclePropertyAccess::WRITE,
|
||||
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
|
||||
.configArray = {1}},
|
||||
},
|
||||
|
||||
{.config = {.prop = VEHICLE_MAP_SERVICE,
|
||||
.access = VehiclePropertyAccess::READ_WRITE,
|
||||
.changeMode = VehiclePropertyChangeMode::ON_CHANGE}},
|
||||
};
|
||||
|
||||
} // impl
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <android-base/macros.h>
|
||||
|
||||
#include "EmulatedVehicleHal.h"
|
||||
#include "Obd2SensorStore.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -28,6 +29,62 @@ namespace V2_0 {
|
||||
|
||||
namespace impl {
|
||||
|
||||
static std::unique_ptr<Obd2SensorStore> fillDefaultObd2Frame(size_t numVendorIntegerSensors,
|
||||
size_t numVendorFloatSensors) {
|
||||
std::unique_ptr<Obd2SensorStore> sensorStore(
|
||||
new Obd2SensorStore(numVendorIntegerSensors, numVendorFloatSensors));
|
||||
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_SYSTEM_STATUS,
|
||||
toInt(Obd2FuelSystemStatus::CLOSED_LOOP));
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0);
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_MONITORS_SUPPORTED,
|
||||
toInt(Obd2IgnitionMonitorKind::SPARK));
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
|
||||
Obd2CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
|
||||
Obd2CommonIgnitionMonitors::MISFIRE_AVAILABLE |
|
||||
Obd2SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
|
||||
Obd2SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE);
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35);
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS,
|
||||
toInt(Obd2SecondaryAirStatus::FROM_OUTSIDE_OR_OFF));
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1);
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500);
|
||||
sensorStore->setIntegerSensor(
|
||||
DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0);
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51);
|
||||
sensorStore->setIntegerSensor(
|
||||
DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365);
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30);
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12);
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18);
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1);
|
||||
sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_TYPE,
|
||||
toInt(Obd2FuelType::GASOLINE));
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ENGINE_RPM, 1250.);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::VEHICLE_SPEED, 40.);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::TIMING_ADVANCE, 2.5);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::THROTTLE_POSITION, 19.75);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE,
|
||||
-0.373);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1,
|
||||
190.);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094);
|
||||
sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
|
||||
|
||||
return sensorStore;
|
||||
}
|
||||
|
||||
enum class FakeDataCommand : int32_t {
|
||||
Stop = 0,
|
||||
Start = 1,
|
||||
@@ -40,7 +97,7 @@ EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore)
|
||||
this, std::placeholders::_1)),
|
||||
mFakeValueGenerator(std::bind(&EmulatedVehicleHal::onFakeValueGenerated,
|
||||
this, std::placeholders::_1, std::placeholders::_2)) {
|
||||
|
||||
initStaticConfig();
|
||||
for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
|
||||
mPropStore->registerProperty(kVehicleProperties[i].config);
|
||||
}
|
||||
@@ -48,23 +105,39 @@ EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore)
|
||||
|
||||
VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
|
||||
const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
|
||||
auto propId = requestedPropValue.prop;
|
||||
auto& pool = *getValuePool();
|
||||
VehiclePropValuePtr v = nullptr;
|
||||
|
||||
auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
|
||||
if (internalPropValue != nullptr) {
|
||||
v = getValuePool()->obtain(*internalPropValue);
|
||||
switch (propId) {
|
||||
case OBD2_FREEZE_FRAME:
|
||||
v = pool.obtainComplex();
|
||||
*outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
|
||||
break;
|
||||
case OBD2_FREEZE_FRAME_INFO:
|
||||
v = pool.obtainComplex();
|
||||
*outStatus = fillObd2DtcInfo(v.get());
|
||||
break;
|
||||
default:
|
||||
auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
|
||||
if (internalPropValue != nullptr) {
|
||||
v = getValuePool()->obtain(*internalPropValue);
|
||||
}
|
||||
|
||||
*outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
|
||||
break;
|
||||
}
|
||||
|
||||
*outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
|
||||
return v;
|
||||
}
|
||||
|
||||
StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
|
||||
if (propValue.prop == kGenerateFakeDataControllingProperty) {
|
||||
return handleGenerateFakeDataRequest(propValue);
|
||||
};
|
||||
|
||||
if (mHvacPowerProps.count(propValue.prop)) {
|
||||
StatusCode status = handleGenerateFakeDataRequest(propValue);
|
||||
if (status != StatusCode::OK) {
|
||||
return status;
|
||||
}
|
||||
} else if (mHvacPowerProps.count(propValue.prop)) {
|
||||
auto hvacPowerOn = mPropStore->readValueOrNull(toInt(VehicleProperty::HVAC_POWER_ON),
|
||||
toInt(VehicleAreaZone::ROW_1));
|
||||
|
||||
@@ -72,6 +145,12 @@ StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
|
||||
&& hvacPowerOn->value.int32Values[0] == 0) {
|
||||
return StatusCode::NOT_AVAILABLE;
|
||||
}
|
||||
} else if (propValue.prop == OBD2_FREEZE_FRAME_CLEAR) {
|
||||
return clearObd2FreezeFrames(propValue);
|
||||
} else if (propValue.prop == VEHICLE_MAP_SERVICE) {
|
||||
// Placeholder for future implementation of VMS property in the default hal. For now, just
|
||||
// returns OK; otherwise, hal clients crash with property not supported.
|
||||
return StatusCode::OK;
|
||||
}
|
||||
|
||||
if (!mPropStore->writeValue(propValue)) {
|
||||
@@ -83,12 +162,29 @@ StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
|
||||
return StatusCode::OK;
|
||||
}
|
||||
|
||||
static bool isDiagnosticProperty(VehiclePropConfig propConfig) {
|
||||
switch (propConfig.prop) {
|
||||
case OBD2_LIVE_FRAME:
|
||||
case OBD2_FREEZE_FRAME:
|
||||
case OBD2_FREEZE_FRAME_CLEAR:
|
||||
case OBD2_FREEZE_FRAME_INFO:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse supported properties list and generate vector of property values to hold current values.
|
||||
void EmulatedVehicleHal::onCreate() {
|
||||
for (auto& it : kVehicleProperties) {
|
||||
VehiclePropConfig cfg = it.config;
|
||||
int32_t supportedAreas = cfg.supportedAreas;
|
||||
|
||||
if (isDiagnosticProperty(cfg)) {
|
||||
// do not write an initial empty value for the diagnostic properties
|
||||
// as we will initialize those separately.
|
||||
continue;
|
||||
}
|
||||
|
||||
// A global property will have supportedAreas = 0
|
||||
if (isGlobalProp(cfg.prop)) {
|
||||
supportedAreas = 0;
|
||||
@@ -120,6 +216,8 @@ void EmulatedVehicleHal::onCreate() {
|
||||
|
||||
} while (supportedAreas != 0);
|
||||
}
|
||||
initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
|
||||
initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
|
||||
}
|
||||
|
||||
std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties() {
|
||||
@@ -176,6 +274,13 @@ bool EmulatedVehicleHal::isContinuousProperty(int32_t propId) const {
|
||||
}
|
||||
|
||||
bool EmulatedVehicleHal::setPropertyFromVehicle(const VehiclePropValue& propValue) {
|
||||
if (propValue.prop == kGenerateFakeDataControllingProperty) {
|
||||
StatusCode status = handleGenerateFakeDataRequest(propValue);
|
||||
if (status != StatusCode::OK) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mPropStore->writeValue(propValue)) {
|
||||
doHalEvent(getValuePool()->obtain(propValue));
|
||||
return true;
|
||||
@@ -263,6 +368,100 @@ void EmulatedVehicleHal::onFakeValueGenerated(int32_t propId, float value) {
|
||||
}
|
||||
}
|
||||
|
||||
void EmulatedVehicleHal::initStaticConfig() {
|
||||
for (auto&& it = std::begin(kVehicleProperties); it != std::end(kVehicleProperties); ++it) {
|
||||
const auto& cfg = it->config;
|
||||
VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
|
||||
|
||||
switch (cfg.prop) {
|
||||
case OBD2_FREEZE_FRAME: {
|
||||
tokenFunction = [](const VehiclePropValue& propValue) {
|
||||
return propValue.timestamp;
|
||||
};
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mPropStore->registerProperty(cfg, tokenFunction);
|
||||
}
|
||||
}
|
||||
|
||||
void EmulatedVehicleHal::initObd2LiveFrame(const VehiclePropConfig& propConfig) {
|
||||
auto liveObd2Frame = createVehiclePropValue(VehiclePropertyType::COMPLEX, 0);
|
||||
auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
|
||||
static_cast<size_t>(propConfig.configArray[1]));
|
||||
sensorStore->fillPropValue("", liveObd2Frame.get());
|
||||
liveObd2Frame->prop = OBD2_LIVE_FRAME;
|
||||
|
||||
mPropStore->writeValue(*liveObd2Frame);
|
||||
}
|
||||
|
||||
void EmulatedVehicleHal::initObd2FreezeFrame(const VehiclePropConfig& propConfig) {
|
||||
auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
|
||||
static_cast<size_t>(propConfig.configArray[1]));
|
||||
|
||||
static std::vector<std::string> sampleDtcs = {"P0070",
|
||||
"P0102"
|
||||
"P0123"};
|
||||
for (auto&& dtc : sampleDtcs) {
|
||||
auto freezeFrame = createVehiclePropValue(VehiclePropertyType::COMPLEX, 0);
|
||||
sensorStore->fillPropValue(dtc, freezeFrame.get());
|
||||
freezeFrame->prop = OBD2_FREEZE_FRAME;
|
||||
|
||||
mPropStore->writeValue(*freezeFrame);
|
||||
}
|
||||
}
|
||||
|
||||
StatusCode EmulatedVehicleHal::fillObd2FreezeFrame(const VehiclePropValue& requestedPropValue,
|
||||
VehiclePropValue* outValue) {
|
||||
if (requestedPropValue.value.int64Values.size() != 1) {
|
||||
ALOGE("asked for OBD2_FREEZE_FRAME without valid timestamp");
|
||||
return StatusCode::INVALID_ARG;
|
||||
}
|
||||
auto timestamp = requestedPropValue.value.int64Values[0];
|
||||
auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
|
||||
if (freezeFrame == nullptr) {
|
||||
ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
|
||||
return StatusCode::INVALID_ARG;
|
||||
}
|
||||
outValue->prop = OBD2_FREEZE_FRAME;
|
||||
outValue->value.int32Values = freezeFrame->value.int32Values;
|
||||
outValue->value.floatValues = freezeFrame->value.floatValues;
|
||||
outValue->value.bytes = freezeFrame->value.bytes;
|
||||
outValue->value.stringValue = freezeFrame->value.stringValue;
|
||||
outValue->timestamp = freezeFrame->timestamp;
|
||||
return StatusCode::OK;
|
||||
}
|
||||
|
||||
StatusCode EmulatedVehicleHal::clearObd2FreezeFrames(const VehiclePropValue& propValue) {
|
||||
if (propValue.value.int64Values.size() == 0) {
|
||||
mPropStore->removeValuesForProperty(OBD2_FREEZE_FRAME);
|
||||
return StatusCode::OK;
|
||||
} else {
|
||||
for (int64_t timestamp : propValue.value.int64Values) {
|
||||
auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
|
||||
if (freezeFrame == nullptr) {
|
||||
ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
|
||||
return StatusCode::INVALID_ARG;
|
||||
}
|
||||
mPropStore->removeValue(*freezeFrame);
|
||||
}
|
||||
}
|
||||
return StatusCode::OK;
|
||||
}
|
||||
|
||||
StatusCode EmulatedVehicleHal::fillObd2DtcInfo(VehiclePropValue* outValue) {
|
||||
std::vector<int64_t> timestamps;
|
||||
for (const auto& freezeFrame : mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME)) {
|
||||
timestamps.push_back(freezeFrame.timestamp);
|
||||
}
|
||||
outValue->value.int64Values = timestamps;
|
||||
outValue->prop = OBD2_FREEZE_FRAME_INFO;
|
||||
return StatusCode::OK;
|
||||
}
|
||||
|
||||
} // impl
|
||||
|
||||
} // namespace V2_0
|
||||
|
||||
@@ -70,8 +70,15 @@ private:
|
||||
|
||||
void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
|
||||
bool isContinuousProperty(int32_t propId) const;
|
||||
void initStaticConfig();
|
||||
void initObd2LiveFrame(const VehiclePropConfig& propConfig);
|
||||
void initObd2FreezeFrame(const VehiclePropConfig& propConfig);
|
||||
StatusCode fillObd2FreezeFrame(const VehiclePropValue& requestedPropValue,
|
||||
VehiclePropValue* outValue);
|
||||
StatusCode fillObd2DtcInfo(VehiclePropValue* outValue);
|
||||
StatusCode clearObd2FreezeFrames(const VehiclePropValue& propValue);
|
||||
|
||||
private:
|
||||
/* Private members */
|
||||
VehiclePropertyStore* mPropStore;
|
||||
std::unordered_set<int32_t> mHvacPowerProps;
|
||||
RecurrentTimer mRecurrentTimer;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// 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.
|
||||
|
||||
// Vehicle HAL Protobuf library
|
||||
cc_library_static {
|
||||
name: "android.hardware.automotive.vehicle@2.0-libproto-native",
|
||||
vendor: true,
|
||||
proto: {
|
||||
export_proto_headers: true,
|
||||
type: "lite",
|
||||
},
|
||||
strip: {
|
||||
keep_symbols: true,
|
||||
},
|
||||
srcs: ["VehicleHalProto.proto"]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,68 +0,0 @@
|
||||
// This file is autogenerated by hidl-gen. Do not edit manually.
|
||||
|
||||
filegroup {
|
||||
name: "android.hardware.automotive.vehicle@2.1_hal",
|
||||
srcs: [
|
||||
"types.hal",
|
||||
"IVehicle.hal",
|
||||
],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.automotive.vehicle@2.1_genc++",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.1",
|
||||
srcs: [
|
||||
":android.hardware.automotive.vehicle@2.1_hal",
|
||||
],
|
||||
out: [
|
||||
"android/hardware/automotive/vehicle/2.1/types.cpp",
|
||||
"android/hardware/automotive/vehicle/2.1/VehicleAll.cpp",
|
||||
],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.automotive.vehicle@2.1_genc++_headers",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.1",
|
||||
srcs: [
|
||||
":android.hardware.automotive.vehicle@2.1_hal",
|
||||
],
|
||||
out: [
|
||||
"android/hardware/automotive/vehicle/2.1/types.h",
|
||||
"android/hardware/automotive/vehicle/2.1/hwtypes.h",
|
||||
"android/hardware/automotive/vehicle/2.1/IVehicle.h",
|
||||
"android/hardware/automotive/vehicle/2.1/IHwVehicle.h",
|
||||
"android/hardware/automotive/vehicle/2.1/BnHwVehicle.h",
|
||||
"android/hardware/automotive/vehicle/2.1/BpHwVehicle.h",
|
||||
"android/hardware/automotive/vehicle/2.1/BsVehicle.h",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "android.hardware.automotive.vehicle@2.1",
|
||||
defaults: ["hidl-module-defaults"],
|
||||
generated_sources: ["android.hardware.automotive.vehicle@2.1_genc++"],
|
||||
generated_headers: ["android.hardware.automotive.vehicle@2.1_genc++_headers"],
|
||||
export_generated_headers: ["android.hardware.automotive.vehicle@2.1_genc++_headers"],
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"libcutils",
|
||||
"android.hardware.automotive.vehicle@2.0",
|
||||
],
|
||||
export_shared_lib_headers: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"libutils",
|
||||
"android.hardware.automotive.vehicle@2.0",
|
||||
],
|
||||
}
|
||||
@@ -1,648 +0,0 @@
|
||||
# This file is autogenerated by hidl-gen. Do not edit manually.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
################################################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := android.hardware.automotive.vehicle-V2.1-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.automotive.vehicle-V2.0-java \
|
||||
android.hidl.base-V1.0-java \
|
||||
|
||||
|
||||
#
|
||||
# Build types.hal (CommonIgnitionMonitors)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CommonIgnitionMonitors.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.CommonIgnitionMonitors
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (CompressionIgnitionMonitors)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CompressionIgnitionMonitors.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.CompressionIgnitionMonitors
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (FuelSystemStatus)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelSystemStatus.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.FuelSystemStatus
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (FuelType)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelType.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.FuelType
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (IgnitionMonitorKind)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IgnitionMonitorKind.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.IgnitionMonitorKind
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (Obd2FloatSensorIndex)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2FloatSensorIndex.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.Obd2FloatSensorIndex
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (Obd2IntegerSensorIndex)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2IntegerSensorIndex.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.Obd2IntegerSensorIndex
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (SecondaryAirStatus)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SecondaryAirStatus.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.SecondaryAirStatus
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (SparkIgnitionMonitors)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SparkIgnitionMonitors.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.SparkIgnitionMonitors
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (VehicleProperty)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VehicleProperty.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.VehicleProperty
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (VmsBaseMessageIntegerValuesIndex)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsBaseMessageIntegerValuesIndex.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.VmsBaseMessageIntegerValuesIndex
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (VmsMessageType)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsMessageType.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.VmsMessageType
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (VmsOfferingMessageIntegerValuesIndex)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsOfferingMessageIntegerValuesIndex.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.VmsOfferingMessageIntegerValuesIndex
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (VmsSimpleMessageIntegerValuesIndex)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsSimpleMessageIntegerValuesIndex.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.VmsSimpleMessageIntegerValuesIndex
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (VmsSubscriptionResponseFormat)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsSubscriptionResponseFormat.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.VmsSubscriptionResponseFormat
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build IVehicle.hal
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IVehicle.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVehicle.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.automotive.vehicle@2.1::IVehicle
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/IVehicle.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
include $(BUILD_JAVA_LIBRARY)
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := android.hardware.automotive.vehicle-V2.1-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.automotive.vehicle-V2.0-java-static \
|
||||
android.hidl.base-V1.0-java-static \
|
||||
|
||||
|
||||
#
|
||||
# Build types.hal (CommonIgnitionMonitors)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CommonIgnitionMonitors.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.CommonIgnitionMonitors
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (CompressionIgnitionMonitors)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CompressionIgnitionMonitors.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.CompressionIgnitionMonitors
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (FuelSystemStatus)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelSystemStatus.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.FuelSystemStatus
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (FuelType)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelType.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.FuelType
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (IgnitionMonitorKind)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IgnitionMonitorKind.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.IgnitionMonitorKind
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (Obd2FloatSensorIndex)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2FloatSensorIndex.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.Obd2FloatSensorIndex
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (Obd2IntegerSensorIndex)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2IntegerSensorIndex.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.Obd2IntegerSensorIndex
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (SecondaryAirStatus)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SecondaryAirStatus.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.SecondaryAirStatus
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (SparkIgnitionMonitors)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SparkIgnitionMonitors.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.SparkIgnitionMonitors
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (VehicleProperty)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VehicleProperty.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.VehicleProperty
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (VmsBaseMessageIntegerValuesIndex)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsBaseMessageIntegerValuesIndex.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.VmsBaseMessageIntegerValuesIndex
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (VmsMessageType)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsMessageType.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.VmsMessageType
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (VmsOfferingMessageIntegerValuesIndex)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsOfferingMessageIntegerValuesIndex.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.VmsOfferingMessageIntegerValuesIndex
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (VmsSimpleMessageIntegerValuesIndex)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsSimpleMessageIntegerValuesIndex.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.VmsSimpleMessageIntegerValuesIndex
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build types.hal (VmsSubscriptionResponseFormat)
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsSubscriptionResponseFormat.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.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.automotive.vehicle@2.1::types.VmsSubscriptionResponseFormat
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/types.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
|
||||
#
|
||||
# Build IVehicle.hal
|
||||
#
|
||||
GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IVehicle.java
|
||||
$(GEN): $(HIDL)
|
||||
$(GEN): PRIVATE_HIDL := $(HIDL)
|
||||
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVehicle.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.automotive.vehicle@2.1::IVehicle
|
||||
|
||||
$(GEN): $(LOCAL_PATH)/IVehicle.hal
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
include $(BUILD_STATIC_JAVA_LIBRARY)
|
||||
|
||||
|
||||
|
||||
include $(call all-makefiles-under,$(LOCAL_PATH))
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.1 (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.1
|
||||
*
|
||||
* 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.automotive.vehicle@2.1;
|
||||
|
||||
import android.hardware.automotive.vehicle@2.0;
|
||||
|
||||
/**
|
||||
* New revision of IVehicle interface that supports properties defined in
|
||||
* VehicleProperty enum version 2.1.
|
||||
*
|
||||
* NOTE: this HAL interface is under development and shouldn't be used in
|
||||
* production.
|
||||
*
|
||||
* TODO(pavelm): update comment when this interface is ready for prod.
|
||||
*/
|
||||
interface IVehicle extends @2.0::IVehicle {
|
||||
};
|
||||
@@ -1,123 +0,0 @@
|
||||
# Copyright (C) 2016 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
vhal_v2_0 = android.hardware.automotive.vehicle@2.0
|
||||
vhal_v2_1 = android.hardware.automotive.vehicle@2.1
|
||||
|
||||
###############################################################################
|
||||
# Vehicle reference implementation lib
|
||||
###############################################################################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := $(vhal_v2_1)-manager-lib
|
||||
LOCAL_SRC_FILES := \
|
||||
common/src/Obd2SensorStore.cpp
|
||||
|
||||
LOCAL_CFLAGS := -Wall -Werror
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/common/include/vhal_v2_1 \
|
||||
$(LOCAL_PATH)/../../2.0/default/common/include/vhal_v2_0 \
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := \
|
||||
$(LOCAL_PATH)/common/include
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libhidlbase \
|
||||
libhidltransport \
|
||||
libhwbinder \
|
||||
liblog \
|
||||
libutils \
|
||||
$(vhal_v2_1) \
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
###############################################################################
|
||||
# Vehicle default VehicleHAL implementation
|
||||
###############################################################################
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE:= $(vhal_v2_1)-default-impl-lib
|
||||
LOCAL_SRC_FILES:= \
|
||||
impl/vhal_v2_1/EmulatedVehicleHal.cpp \
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/impl/vhal_v2_1 \
|
||||
$(LOCAL_PATH)/common/include
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := \
|
||||
$(LOCAL_PATH)/impl \
|
||||
$(LOCAL_PATH)/common/include
|
||||
|
||||
|
||||
# LOCAL_WHOLE_STATIC_LIBRARIES := \
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
$(vhal_v2_0)-default-impl-lib \
|
||||
$(vhal_v2_0)-manager-lib \
|
||||
libqemu_pipe \
|
||||
$(vhal_v2_1)-manager-lib \
|
||||
$(vhal_v2_0)-libproto-native
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libbase \
|
||||
libhidlbase \
|
||||
libhidltransport \
|
||||
libhwbinder \
|
||||
liblog \
|
||||
libutils \
|
||||
libprotobuf-cpp-lite \
|
||||
$(vhal_v2_0) \
|
||||
$(vhal_v2_1) \
|
||||
|
||||
LOCAL_CFLAGS += -Wall -Wextra -Werror
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
###############################################################################
|
||||
# Vehicle HAL service
|
||||
###############################################################################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := $(vhal_v2_1)-service
|
||||
LOCAL_INIT_RC := $(vhal_v2_1)-service.rc
|
||||
LOCAL_MODULE_RELATIVE_PATH := hw
|
||||
LOCAL_PROPRIETARY_MODULE := true
|
||||
LOCAL_SRC_FILES := \
|
||||
service.cpp
|
||||
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := \
|
||||
$(vhal_v2_0)-libproto-native \
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
$(vhal_v2_0)-manager-lib \
|
||||
$(vhal_v2_0)-default-impl-lib \
|
||||
$(vhal_v2_1)-default-impl-lib \
|
||||
libqemu_pipe \
|
||||
$(vhal_v2_1)-manager-lib \
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libbase \
|
||||
libhidlbase \
|
||||
libhidltransport \
|
||||
libhwbinder \
|
||||
liblog \
|
||||
libutils \
|
||||
libprotobuf-cpp-lite \
|
||||
$(vhal_v2_0) \
|
||||
$(vhal_v2_1) \
|
||||
|
||||
LOCAL_CFLAGS += -Wall -Wextra -Werror
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
@@ -1,4 +0,0 @@
|
||||
service vehicle-hal-2.1 /vendor/bin/hw/android.hardware.automotive.vehicle@2.1-service
|
||||
class hal
|
||||
user vehicle_network
|
||||
group system inet
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef android_hardware_automotive_vehicle_V2_1_impl_DefaultConfig_H_
|
||||
#define android_hardware_automotive_vehicle_V2_1_impl_DefaultConfig_H_
|
||||
|
||||
#include <android/hardware/automotive/vehicle/2.1/types.h>
|
||||
#include <vhal_v2_0/VehicleUtils.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
namespace V2_1 {
|
||||
|
||||
namespace impl {
|
||||
|
||||
// Some handy constants to avoid conversions from enum to int.
|
||||
constexpr int OBD2_LIVE_FRAME = (int) V2_1::VehicleProperty::OBD2_LIVE_FRAME;
|
||||
constexpr int OBD2_FREEZE_FRAME = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME;
|
||||
constexpr int OBD2_FREEZE_FRAME_INFO = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME_INFO;
|
||||
constexpr int OBD2_FREEZE_FRAME_CLEAR = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR;
|
||||
constexpr int VEHICLE_MAP_SERVICE = (int) V2_1::VehicleProperty::VEHICLE_MAP_SERVICE;
|
||||
constexpr int WHEEL_TICK = (int) V2_1::VehicleProperty::WHEEL_TICK;
|
||||
|
||||
|
||||
const V2_0::VehiclePropConfig kVehicleProperties[] = {
|
||||
{
|
||||
.prop = WHEEL_TICK,
|
||||
.access = V2_0::VehiclePropertyAccess::READ,
|
||||
.changeMode = V2_0::VehiclePropertyChangeMode::CONTINUOUS,
|
||||
.minSampleRate = 1.0f,
|
||||
.maxSampleRate = 100.0f,
|
||||
},
|
||||
|
||||
{
|
||||
.prop = OBD2_LIVE_FRAME,
|
||||
.access = V2_0::VehiclePropertyAccess::READ,
|
||||
.changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE,
|
||||
.configArray = {0,0}
|
||||
},
|
||||
|
||||
{
|
||||
.prop = OBD2_FREEZE_FRAME,
|
||||
.access = V2_0::VehiclePropertyAccess::READ,
|
||||
.changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE,
|
||||
.configArray = {0,0}
|
||||
},
|
||||
|
||||
{
|
||||
.prop = OBD2_FREEZE_FRAME_INFO,
|
||||
.access = V2_0::VehiclePropertyAccess::READ,
|
||||
.changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
|
||||
},
|
||||
|
||||
{
|
||||
.prop = OBD2_FREEZE_FRAME_CLEAR,
|
||||
.access = V2_0::VehiclePropertyAccess::WRITE,
|
||||
.changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
|
||||
},
|
||||
|
||||
{
|
||||
.prop = VEHICLE_MAP_SERVICE,
|
||||
.access = V2_0::VehiclePropertyAccess::READ_WRITE,
|
||||
.changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
|
||||
}
|
||||
};
|
||||
|
||||
} // impl
|
||||
|
||||
} // namespace V2_1
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // android_hardware_automotive_vehicle_V2_1_impl_DefaultConfig_H_
|
||||
@@ -1,263 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "DefaultVehicleHal_v2_1"
|
||||
#include <android/log.h>
|
||||
|
||||
#include <log/log.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "EmulatedVehicleHal.h"
|
||||
|
||||
#define DEBUG_SOCKET (33452)
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
namespace V2_1 {
|
||||
|
||||
namespace impl {
|
||||
|
||||
static std::unique_ptr<Obd2SensorStore> fillDefaultObd2Frame(
|
||||
size_t numVendorIntegerSensors,
|
||||
size_t numVendorFloatSensors) {
|
||||
std::unique_ptr<Obd2SensorStore> sensorStore(new Obd2SensorStore(
|
||||
numVendorIntegerSensors, numVendorFloatSensors));
|
||||
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS,
|
||||
V2_0::toInt(FuelSystemStatus::CLOSED_LOOP));
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0);
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::IGNITION_MONITORS_SUPPORTED,
|
||||
V2_0::toInt(IgnitionMonitorKind::SPARK));
|
||||
sensorStore->setIntegerSensor(Obd2IntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
|
||||
CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
|
||||
CommonIgnitionMonitors::MISFIRE_AVAILABLE |
|
||||
SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
|
||||
SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE);
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35);
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS,
|
||||
V2_0::toInt(SecondaryAirStatus::FROM_OUTSIDE_OR_OFF));
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1);
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500);
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0);
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51);
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365);
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30);
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12);
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18);
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1);
|
||||
sensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::FUEL_TYPE, V2_0::toInt(FuelType::GASOLINE));
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::ENGINE_RPM, 1250.);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::VEHICLE_SPEED, 40.);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::TIMING_ADVANCE, 2.5);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::THROTTLE_POSITION, 19.75);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE, -0.373);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1, 190.);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094);
|
||||
sensorStore->setFloatSensor(
|
||||
Obd2FloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
|
||||
|
||||
return sensorStore;
|
||||
}
|
||||
|
||||
void EmulatedVehicleHal::initObd2LiveFrame(const V2_0::VehiclePropConfig& propConfig) {
|
||||
auto liveObd2Frame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
|
||||
auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
|
||||
static_cast<size_t>(propConfig.configArray[1]));
|
||||
sensorStore->fillPropValue("", liveObd2Frame.get());
|
||||
liveObd2Frame->prop = OBD2_LIVE_FRAME;
|
||||
|
||||
mPropStore->writeValue(*liveObd2Frame);
|
||||
}
|
||||
|
||||
void EmulatedVehicleHal::initObd2FreezeFrame(const V2_0::VehiclePropConfig& propConfig) {
|
||||
auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
|
||||
static_cast<size_t>(propConfig.configArray[1]));
|
||||
|
||||
static std::vector<std::string> sampleDtcs = { "P0070", "P0102" "P0123" };
|
||||
for (auto&& dtc : sampleDtcs) {
|
||||
auto freezeFrame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
|
||||
sensorStore->fillPropValue(dtc, freezeFrame.get());
|
||||
freezeFrame->prop = OBD2_FREEZE_FRAME;
|
||||
|
||||
mPropStore->writeValue(*freezeFrame);
|
||||
}
|
||||
}
|
||||
|
||||
V2_0::StatusCode EmulatedVehicleHal::fillObd2FreezeFrame(
|
||||
const V2_0::VehiclePropValue& requestedPropValue,
|
||||
V2_0::VehiclePropValue* outValue) {
|
||||
if (requestedPropValue.value.int64Values.size() != 1) {
|
||||
ALOGE("asked for OBD2_FREEZE_FRAME without valid timestamp");
|
||||
return V2_0::StatusCode::INVALID_ARG;
|
||||
}
|
||||
auto timestamp = requestedPropValue.value.int64Values[0];
|
||||
auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
|
||||
if(freezeFrame == nullptr) {
|
||||
ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
|
||||
return V2_0::StatusCode::INVALID_ARG;
|
||||
}
|
||||
outValue->prop = OBD2_FREEZE_FRAME;
|
||||
outValue->value.int32Values = freezeFrame->value.int32Values;
|
||||
outValue->value.floatValues = freezeFrame->value.floatValues;
|
||||
outValue->value.bytes = freezeFrame->value.bytes;
|
||||
outValue->value.stringValue = freezeFrame->value.stringValue;
|
||||
outValue->timestamp = freezeFrame->timestamp;
|
||||
return V2_0::StatusCode::OK;
|
||||
}
|
||||
|
||||
V2_0::StatusCode EmulatedVehicleHal::clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue) {
|
||||
if (propValue.value.int64Values.size() == 0) {
|
||||
mPropStore->removeValuesForProperty(OBD2_FREEZE_FRAME);
|
||||
return V2_0::StatusCode::OK;
|
||||
} else {
|
||||
for(int64_t timestamp: propValue.value.int64Values) {
|
||||
auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
|
||||
if(freezeFrame == nullptr) {
|
||||
ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
|
||||
return V2_0::StatusCode::INVALID_ARG;
|
||||
}
|
||||
mPropStore->removeValue(*freezeFrame);
|
||||
}
|
||||
}
|
||||
return V2_0::StatusCode::OK;
|
||||
}
|
||||
|
||||
V2_0::StatusCode EmulatedVehicleHal::fillObd2DtcInfo(V2_0::VehiclePropValue* outValue) {
|
||||
std::vector<int64_t> timestamps;
|
||||
for(const auto& freezeFrame: mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME)) {
|
||||
timestamps.push_back(freezeFrame.timestamp);
|
||||
}
|
||||
outValue->value.int64Values = timestamps;
|
||||
return V2_0::StatusCode::OK;
|
||||
}
|
||||
|
||||
void EmulatedVehicleHal::onCreate() {
|
||||
V2_0::impl::EmulatedVehicleHal::onCreate();
|
||||
|
||||
initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
|
||||
initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
|
||||
}
|
||||
|
||||
void EmulatedVehicleHal::initStaticConfig() {
|
||||
for (auto&& cfg = std::begin(kVehicleProperties); cfg != std::end(kVehicleProperties); ++cfg) {
|
||||
V2_0::VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
|
||||
|
||||
switch (cfg->prop) {
|
||||
case OBD2_FREEZE_FRAME: {
|
||||
tokenFunction = [] (const V2_0::VehiclePropValue& propValue) {
|
||||
return propValue.timestamp;
|
||||
};
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mPropStore->registerProperty(*cfg, tokenFunction);
|
||||
}
|
||||
}
|
||||
|
||||
EmulatedVehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
|
||||
const V2_0::VehiclePropValue& requestedPropValue,
|
||||
V2_0::StatusCode* outStatus) {
|
||||
|
||||
auto propId = requestedPropValue.prop;
|
||||
VehiclePropValuePtr v = nullptr;
|
||||
auto& pool = *getValuePool();
|
||||
|
||||
switch (propId) {
|
||||
case OBD2_FREEZE_FRAME:
|
||||
v = pool.obtainComplex();
|
||||
*outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
|
||||
return v;
|
||||
case OBD2_FREEZE_FRAME_INFO:
|
||||
v = pool.obtainComplex();
|
||||
*outStatus = fillObd2DtcInfo(v.get());
|
||||
return v;
|
||||
default:
|
||||
return V2_0::impl::EmulatedVehicleHal::get(requestedPropValue, outStatus);
|
||||
}
|
||||
}
|
||||
|
||||
V2_0::StatusCode EmulatedVehicleHal::set(const V2_0::VehiclePropValue& propValue) {
|
||||
auto propId = propValue.prop;
|
||||
switch (propId) {
|
||||
case OBD2_FREEZE_FRAME_CLEAR:
|
||||
return clearObd2FreezeFrames(propValue);
|
||||
case VEHICLE_MAP_SERVICE:
|
||||
// Placeholder for future implementation of VMS property in the default hal. For now, just
|
||||
// returns OK; otherwise, hal clients crash with property not supported.
|
||||
return V2_0::StatusCode::OK;
|
||||
default:
|
||||
return V2_0::impl::EmulatedVehicleHal::set(propValue);
|
||||
}
|
||||
}
|
||||
|
||||
} // impl
|
||||
|
||||
} // namespace V2_1
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef android_hardware_automotive_vehicle_V2_1_impl_EmulatedVehicleHal_H_
|
||||
#define android_hardware_automotive_vehicle_V2_1_impl_EmulatedVehicleHal_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <utils/SystemClock.h>
|
||||
|
||||
#include <vhal_v2_0/EmulatedVehicleHal.h>
|
||||
#include <vhal_v2_0/VehicleHal.h>
|
||||
#include <vhal_v2_0/VehiclePropertyStore.h>
|
||||
#include <vhal_v2_1/Obd2SensorStore.h>
|
||||
|
||||
#include "DefaultConfig.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
namespace V2_1 {
|
||||
|
||||
namespace impl {
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
class EmulatedVehicleHal : public V2_0::impl::EmulatedVehicleHal {
|
||||
public:
|
||||
EmulatedVehicleHal(V2_0::VehiclePropertyStore* propStore)
|
||||
: V2_0::impl::EmulatedVehicleHal(propStore), mPropStore(propStore) {
|
||||
initStaticConfig();
|
||||
}
|
||||
|
||||
VehiclePropValuePtr get(const V2_0::VehiclePropValue& requestedPropValue,
|
||||
V2_0::StatusCode* outStatus) override;
|
||||
|
||||
V2_0::StatusCode set(const V2_0::VehiclePropValue& propValue) override;
|
||||
|
||||
void onCreate() override;
|
||||
|
||||
private:
|
||||
void initStaticConfig();
|
||||
void initObd2LiveFrame(const V2_0::VehiclePropConfig& propConfig);
|
||||
void initObd2FreezeFrame(const V2_0::VehiclePropConfig& propConfig);
|
||||
V2_0::StatusCode fillObd2FreezeFrame(const V2_0::VehiclePropValue& requestedPropValue,
|
||||
V2_0::VehiclePropValue* outValue);
|
||||
V2_0::StatusCode fillObd2DtcInfo(V2_0::VehiclePropValue *outValue);
|
||||
V2_0::StatusCode clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue);
|
||||
|
||||
private:
|
||||
V2_0::VehiclePropertyStore* mPropStore;
|
||||
};
|
||||
|
||||
} // impl
|
||||
|
||||
} // namespace V2_1
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
|
||||
#endif // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "automotive.vehicle@2.1-service"
|
||||
#include <android/log.h>
|
||||
#include <hidl/HidlTransportSupport.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <android/hardware/automotive/vehicle/2.1/IVehicle.h>
|
||||
|
||||
#include <vhal_v2_0/VehicleHalManager.h>
|
||||
#include <vhal_v2_0/VehiclePropertyStore.h>
|
||||
#include <vhal_v2_0/EmulatedVehicleHal.h>
|
||||
|
||||
#include <vhal_v2_1/EmulatedVehicleHal.h>
|
||||
|
||||
using namespace android;
|
||||
using namespace android::hardware;
|
||||
|
||||
namespace V2_1 = ::android::hardware::automotive::vehicle::V2_1;
|
||||
namespace V2_0 = ::android::hardware::automotive::vehicle::V2_0;
|
||||
|
||||
using StatusCode = V2_0::StatusCode;
|
||||
using VehiclePropValue = V2_0::VehiclePropValue;
|
||||
|
||||
/* Just wrapper that passes all calls to the provided V2_0::IVehicle object */
|
||||
struct Vehicle_V2_1 : public V2_1::IVehicle {
|
||||
|
||||
Vehicle_V2_1(V2_0::IVehicle* vehicle20) : mVehicle20(vehicle20) {}
|
||||
|
||||
// Methods derived from IVehicle
|
||||
Return<void> getAllPropConfigs(getAllPropConfigs_cb _hidl_cb) override {
|
||||
return mVehicle20->getAllPropConfigs(_hidl_cb);
|
||||
}
|
||||
|
||||
Return<void> getPropConfigs(const hidl_vec<int32_t>& properties,
|
||||
getPropConfigs_cb _hidl_cb) override {
|
||||
return mVehicle20->getPropConfigs(properties, _hidl_cb);
|
||||
}
|
||||
|
||||
Return<void> get(const V2_0::VehiclePropValue& requestedPropValue,
|
||||
get_cb _hidl_cb) override {
|
||||
return mVehicle20->get(requestedPropValue, _hidl_cb);
|
||||
}
|
||||
|
||||
Return<StatusCode> set(const VehiclePropValue& value) override {
|
||||
return mVehicle20->set(value);
|
||||
}
|
||||
|
||||
Return<StatusCode> subscribe(const sp<V2_0::IVehicleCallback>& callback,
|
||||
const hidl_vec<V2_0::SubscribeOptions>&
|
||||
options) override {
|
||||
return mVehicle20->subscribe(callback, options);
|
||||
}
|
||||
|
||||
Return<StatusCode> unsubscribe(const sp<V2_0::IVehicleCallback>& callback,
|
||||
int32_t propId) override {
|
||||
return mVehicle20->unsubscribe(callback, propId);
|
||||
}
|
||||
|
||||
Return<void> debugDump(debugDump_cb _hidl_cb = nullptr) override {
|
||||
return mVehicle20->debugDump(_hidl_cb);
|
||||
}
|
||||
|
||||
private:
|
||||
V2_0::IVehicle* mVehicle20;
|
||||
};
|
||||
|
||||
int main(int /* argc */, char* /* argv */ []) {
|
||||
auto store = std::make_unique<V2_0::VehiclePropertyStore>();
|
||||
auto hal = std::make_unique<V2_1::impl::EmulatedVehicleHal>(store.get());
|
||||
auto emulator = std::make_unique<V2_0::impl::VehicleEmulator>(hal.get());
|
||||
auto vehicleManager = std::make_unique<V2_0::VehicleHalManager>(hal.get());
|
||||
|
||||
Vehicle_V2_1 vehicle21(vehicleManager.get());
|
||||
|
||||
configureRpcThreadpool(1, true /* callerWillJoin */);
|
||||
|
||||
ALOGI("Registering as service...");
|
||||
status_t status = vehicle21.registerAsService();
|
||||
|
||||
if (status != OK) {
|
||||
ALOGE("Unable to register vehicle service (%d).", status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ALOGI("Ready");
|
||||
joinRpcThreadpool();
|
||||
return 1;
|
||||
}
|
||||
@@ -1,285 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "vhal_v2_0/Obd2SensorStore.h"
|
||||
#include "vhal_v2_0/VehicleUtils.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
namespace V2_0 {
|
||||
|
||||
namespace {
|
||||
|
||||
static constexpr size_t getNumVendorIntegerSensors() {
|
||||
return 5;
|
||||
}
|
||||
static constexpr size_t getNumVendorFloatSensors() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
// this struct holds information necessary for a test to be able to validate
|
||||
// that the sensor bitmask contains the right data:
|
||||
// - the index of the byte at which the bit for a given sensor lives
|
||||
// - the expected value of that byte given that a certain sensor is present
|
||||
class BitmaskIndexingInfo {
|
||||
public:
|
||||
size_t mByteIndex;
|
||||
uint8_t mExpectedByteValue;
|
||||
|
||||
// Returns the information required to validate the bitmask for an
|
||||
// integer-valued sensor.
|
||||
static BitmaskIndexingInfo getForIntegerSensor(size_t index) {
|
||||
const size_t indexInBitstream = index;
|
||||
return getForBitstreamIndex(indexInBitstream);
|
||||
}
|
||||
|
||||
// Returns the information required to validate the bitmask for a
|
||||
// float-valued sensor.
|
||||
static BitmaskIndexingInfo getForFloatSensor(size_t index) {
|
||||
const size_t indexInBitstream = toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX) +
|
||||
1 + getNumVendorIntegerSensors() + index;
|
||||
return getForBitstreamIndex(indexInBitstream);
|
||||
}
|
||||
|
||||
private:
|
||||
static BitmaskIndexingInfo getForBitstreamIndex(size_t indexInBitstream) {
|
||||
BitmaskIndexingInfo indexingInfo;
|
||||
indexingInfo.mByteIndex = indexInBitstream / 8;
|
||||
indexingInfo.mExpectedByteValue = 1 << (indexInBitstream % 8);
|
||||
return indexingInfo;
|
||||
}
|
||||
};
|
||||
|
||||
static Obd2SensorStore getSensorStore() {
|
||||
return Obd2SensorStore(getNumVendorIntegerSensors(),
|
||||
getNumVendorFloatSensors());
|
||||
}
|
||||
|
||||
// Test that one can set and retrieve a value for the first integer sensor.
|
||||
TEST(Obd2SensorStoreTest, setFirstIntegerSensor) {
|
||||
Obd2SensorStore sensorStore(getSensorStore());
|
||||
sensorStore.setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS,
|
||||
toInt(FuelSystemStatus::CLOSED_LOOP));
|
||||
const auto& integerSensors(sensorStore.getIntegerSensors());
|
||||
const auto& sensorBitmask(sensorStore.getSensorsBitmask());
|
||||
ASSERT_EQ(
|
||||
toInt(FuelSystemStatus::CLOSED_LOOP),
|
||||
integerSensors[toInt(Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS)]);
|
||||
const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
|
||||
toInt(Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS)));
|
||||
ASSERT_EQ(
|
||||
indexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[indexingInfo.mByteIndex]);
|
||||
}
|
||||
|
||||
// Test that one can set and retrieve a value for the first float sensor.
|
||||
TEST(Obd2SensorStoreTest, setFirstFloatSensor) {
|
||||
Obd2SensorStore sensorStore(getSensorStore());
|
||||
sensorStore.setFloatSensor(
|
||||
Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD,
|
||||
1.25f);
|
||||
const auto& floatSensors(sensorStore.getFloatSensors());
|
||||
const auto& sensorBitmask(sensorStore.getSensorsBitmask());
|
||||
ASSERT_EQ(
|
||||
1.25f,
|
||||
floatSensors[toInt(Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD)]);
|
||||
const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
|
||||
toInt(Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD)));
|
||||
ASSERT_EQ(
|
||||
indexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[indexingInfo.mByteIndex]);
|
||||
}
|
||||
|
||||
// Test that one can set and retrieve a value for an integer sensor.
|
||||
TEST(Obd2SensorStoreTest, setAnyIntegerSensor) {
|
||||
Obd2SensorStore sensorStore(getSensorStore());
|
||||
sensorStore.setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE,
|
||||
4000);
|
||||
const auto& integerSensors(sensorStore.getIntegerSensors());
|
||||
const auto& sensorBitmask(sensorStore.getSensorsBitmask());
|
||||
ASSERT_EQ(4000,
|
||||
integerSensors[toInt(Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE)]);
|
||||
const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
|
||||
toInt(Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE)));
|
||||
ASSERT_EQ(
|
||||
indexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[indexingInfo.mByteIndex]);
|
||||
}
|
||||
|
||||
// Test that one can set and retrieve a value for a float sensor.
|
||||
TEST(Obd2SensorStoreTest, setAnyFloatSensor) {
|
||||
Obd2SensorStore sensorStore(getSensorStore());
|
||||
sensorStore.setFloatSensor(
|
||||
Obd2FloatSensorIndex::OXYGEN_SENSOR3_VOLTAGE,
|
||||
2.5f);
|
||||
const auto& floatSensors(sensorStore.getFloatSensors());
|
||||
const auto& sensorBitmask(sensorStore.getSensorsBitmask());
|
||||
ASSERT_EQ(2.5f,
|
||||
floatSensors[toInt(Obd2FloatSensorIndex::OXYGEN_SENSOR3_VOLTAGE)]);
|
||||
const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
|
||||
toInt(Obd2FloatSensorIndex::OXYGEN_SENSOR3_VOLTAGE)));
|
||||
ASSERT_EQ(
|
||||
indexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[indexingInfo.mByteIndex]);
|
||||
}
|
||||
|
||||
// Test that one can set and retrieve a value for the last system integer sensor.
|
||||
TEST(Obd2SensorStoreTest, setLastSystemIntegerSensor) {
|
||||
Obd2SensorStore sensorStore(getSensorStore());
|
||||
sensorStore.setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX,
|
||||
30);
|
||||
const auto& integerSensors(sensorStore.getIntegerSensors());
|
||||
const auto& sensorBitmask(sensorStore.getSensorsBitmask());
|
||||
ASSERT_EQ(30,
|
||||
integerSensors[toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX)]);
|
||||
const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
|
||||
toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX)));
|
||||
ASSERT_EQ(
|
||||
indexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[indexingInfo.mByteIndex]);
|
||||
}
|
||||
|
||||
// Test that one can set and retrieve a value for the last system float sensor.
|
||||
TEST(Obd2SensorStoreTest, setLastSystemFloatSensor) {
|
||||
Obd2SensorStore sensorStore(getSensorStore());
|
||||
sensorStore.setFloatSensor(
|
||||
Obd2FloatSensorIndex::LAST_SYSTEM_INDEX,
|
||||
2.5f);
|
||||
const auto& floatSensors(sensorStore.getFloatSensors());
|
||||
const auto& sensorBitmask(sensorStore.getSensorsBitmask());
|
||||
ASSERT_EQ(2.5f,
|
||||
floatSensors[toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX)]);
|
||||
const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
|
||||
toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX)));
|
||||
ASSERT_EQ(
|
||||
indexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[indexingInfo.mByteIndex]);
|
||||
}
|
||||
|
||||
// Test that one can set and retrieve a value for two integer sensors at once.
|
||||
TEST(Obd2SensorStoreTest, setTwoIntegerSensors) {
|
||||
Obd2SensorStore sensorStore(getSensorStore());
|
||||
sensorStore.setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE,
|
||||
6);
|
||||
sensorStore.setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::TIME_SINCE_TROUBLE_CODES_CLEARED,
|
||||
1245);
|
||||
const auto& integerSensors(sensorStore.getIntegerSensors());
|
||||
const auto& sensorBitmask(sensorStore.getSensorsBitmask());
|
||||
ASSERT_EQ(6,
|
||||
integerSensors[toInt(Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE)]);
|
||||
ASSERT_EQ(1245,
|
||||
integerSensors[toInt(Obd2IntegerSensorIndex::TIME_SINCE_TROUBLE_CODES_CLEARED)]);
|
||||
const BitmaskIndexingInfo voltageIndexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
|
||||
toInt(Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE)));
|
||||
const BitmaskIndexingInfo timeIndexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
|
||||
toInt(Obd2IntegerSensorIndex::TIME_SINCE_TROUBLE_CODES_CLEARED)));
|
||||
if (voltageIndexingInfo.mByteIndex == timeIndexingInfo.mByteIndex) {
|
||||
ASSERT_EQ(
|
||||
voltageIndexingInfo.mExpectedByteValue |
|
||||
timeIndexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[timeIndexingInfo.mByteIndex]);
|
||||
}
|
||||
else {
|
||||
ASSERT_EQ(
|
||||
timeIndexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[timeIndexingInfo.mByteIndex]);
|
||||
ASSERT_EQ(
|
||||
voltageIndexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[voltageIndexingInfo.mByteIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that one can set and retrieve a value for two float sensors at once.
|
||||
TEST(Obd2SensorStoreTest, setTwoFloatSensors) {
|
||||
Obd2SensorStore sensorStore(getSensorStore());
|
||||
sensorStore.setFloatSensor(
|
||||
Obd2FloatSensorIndex::VEHICLE_SPEED,
|
||||
1.25f);
|
||||
sensorStore.setFloatSensor(
|
||||
Obd2FloatSensorIndex::MAF_AIR_FLOW_RATE,
|
||||
2.5f);
|
||||
const auto& floatSensors(sensorStore.getFloatSensors());
|
||||
const auto& sensorBitmask(sensorStore.getSensorsBitmask());
|
||||
ASSERT_EQ(1.25f,
|
||||
floatSensors[toInt(Obd2FloatSensorIndex::VEHICLE_SPEED)]);
|
||||
ASSERT_EQ(2.5f,
|
||||
floatSensors[toInt(Obd2FloatSensorIndex::MAF_AIR_FLOW_RATE)]);
|
||||
const BitmaskIndexingInfo speedIndexingInfo(BitmaskIndexingInfo::getForFloatSensor(
|
||||
toInt(Obd2FloatSensorIndex::VEHICLE_SPEED)));
|
||||
const BitmaskIndexingInfo airflowIndexingInfo(BitmaskIndexingInfo::getForFloatSensor(
|
||||
toInt(Obd2FloatSensorIndex::MAF_AIR_FLOW_RATE)));
|
||||
if (speedIndexingInfo.mByteIndex == airflowIndexingInfo.mByteIndex) {
|
||||
ASSERT_EQ(
|
||||
speedIndexingInfo.mExpectedByteValue |
|
||||
airflowIndexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[airflowIndexingInfo.mByteIndex]);
|
||||
}
|
||||
else {
|
||||
ASSERT_EQ(
|
||||
speedIndexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[speedIndexingInfo.mByteIndex]);
|
||||
ASSERT_EQ(
|
||||
airflowIndexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[airflowIndexingInfo.mByteIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that one can set and retrieve a value for a vendor integer sensor.
|
||||
TEST(Obd2SensorStoreTest, setVendorIntegerSensor) {
|
||||
const size_t sensorIndex = toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX) + 2;
|
||||
Obd2SensorStore sensorStore(getSensorStore());
|
||||
sensorStore.setIntegerSensor(sensorIndex, 22);
|
||||
const auto& integerSensors(sensorStore.getIntegerSensors());
|
||||
const auto& sensorBitmask(sensorStore.getSensorsBitmask());
|
||||
ASSERT_EQ(22, integerSensors[sensorIndex]);
|
||||
const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
|
||||
sensorIndex));
|
||||
ASSERT_EQ(
|
||||
indexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[indexingInfo.mByteIndex]);
|
||||
}
|
||||
|
||||
// Test that one can set and retrieve a value for a vendor float sensor.
|
||||
TEST(Obd2SensorStoreTest, setVendorFloatSensor) {
|
||||
const size_t sensorIndex = toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX) + 2;
|
||||
Obd2SensorStore sensorStore(getSensorStore());
|
||||
sensorStore.setFloatSensor(sensorIndex, 1.25f);
|
||||
const auto& floatSensors(sensorStore.getFloatSensors());
|
||||
const auto& sensorBitmask(sensorStore.getSensorsBitmask());
|
||||
ASSERT_EQ(1.25f, floatSensors[sensorIndex]);
|
||||
const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
|
||||
sensorIndex));
|
||||
ASSERT_EQ(
|
||||
indexingInfo.mExpectedByteValue,
|
||||
sensorBitmask[indexingInfo.mByteIndex]);
|
||||
}
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
} // namespace V2_0
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
@@ -1,653 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.1 (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.1
|
||||
*
|
||||
* 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.automotive.vehicle@2.1;
|
||||
|
||||
import android.hardware.automotive.vehicle@2.0;
|
||||
|
||||
/**
|
||||
* Extension of VehicleProperty enum declared in Vehicle HAL 2.0
|
||||
*/
|
||||
enum VehicleProperty: @2.0::VehicleProperty {
|
||||
/**
|
||||
* Reports wheel rotational distance in meters since last wheel tick
|
||||
* event
|
||||
*
|
||||
* The value is a vector each element represents distance for individual
|
||||
* wheel in the following order: left front, right front, left rear,
|
||||
* right rear. VehiclePropValue.timestamp must be correctly filled in.
|
||||
*
|
||||
* Vendors must specify wheels that support this sensor in
|
||||
* VehiclePropConfig.configFlags. The format of this field is a bitset of
|
||||
* values from Wheel enum.
|
||||
*
|
||||
* @change_mode VehiclePropertyChangeMode:ON_CHANGE |VehiclePropertyChangeMode:CONTINUOUS
|
||||
* @access VehiclePropertyAccess:READ
|
||||
* @unit VehicleUnit:METER
|
||||
*/
|
||||
WHEEL_TICK = (
|
||||
0x0306
|
||||
| VehiclePropertyGroup:SYSTEM
|
||||
| VehiclePropertyType:FLOAT_VEC
|
||||
| VehicleArea:GLOBAL),
|
||||
|
||||
/**
|
||||
* OBD2 Live Sensor Data
|
||||
*
|
||||
* This property uses COMPLEX data to send a snapshot of the current (live)
|
||||
* values of the OBD2 sensors provided by the vehicle.
|
||||
*
|
||||
* VehiclePropConfig
|
||||
* configArray[0] : number of vendor-specific integer-valued sensors
|
||||
* that can be returned in a frame.
|
||||
* configArray[1] : number of vendor-specific float-valued sensors
|
||||
* that can be returned in a frame.
|
||||
*
|
||||
* The values are to be interpreted as follows:
|
||||
* the indices defined in Obd2IntegerSensorIndex are to be used to
|
||||
* read from int32Values;
|
||||
* the indices defined in Obd2FloatSensorIndex are to be used to
|
||||
* read from floatValues.
|
||||
* the elements of bytes are to be interpreted as a bitmask, such that
|
||||
* the bits 0 thru the integer value of
|
||||
* Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[0]
|
||||
* are 1 if the corresponding index is a valid sensor index whose value can
|
||||
* be read in the returned int32Values vector, 0 otherwise.
|
||||
* the bits Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX+1 thru
|
||||
* Obd2FloatingSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[1]
|
||||
* are 1 if the corresponding index is a valid sensor index whose value
|
||||
* can be read in the returned floatValues vector, 0 otherwise.
|
||||
*
|
||||
* For example, int32Values[0] corresponds to FUEL_SYSTEM_STATUS, and
|
||||
* floatValues[0] corresponds to CALCULATED_ENGINE_LOAD, but that mapping
|
||||
* is only valid if the corresponding bits in the bytes vector are set to 1.
|
||||
*
|
||||
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
|
||||
* @access VehiclePropertyAccess:READ
|
||||
*/
|
||||
OBD2_LIVE_FRAME = (
|
||||
0x0D00
|
||||
| VehiclePropertyGroup:SYSTEM
|
||||
| VehiclePropertyType:COMPLEX
|
||||
| VehicleArea:GLOBAL),
|
||||
|
||||
/**
|
||||
* OBD2 Freeze Frame Sensor Data
|
||||
*
|
||||
* This property uses COMPLEX data to send a snapshot of the values of the
|
||||
* OBD2 sensors provided by the vehicle at the time that a diagnostic
|
||||
* troubleshooting code (DTC) was recorded by the vehicle.
|
||||
*
|
||||
* VehiclePropConfig
|
||||
* configArray[0] : number of vendor-specific integer-valued sensors
|
||||
* that can be returned in a frame.
|
||||
* configArray[1] : number of vendor-specific float-valued sensors
|
||||
* that can be returned in a frame.
|
||||
*
|
||||
* A get of this property must take the following form:
|
||||
* int64Values[0]: timestamp of the freeze frame to retrieve.
|
||||
* Valid timestamps are given by OBD2_DTC_INFO.
|
||||
*
|
||||
* The values are to be interpreted as follows:
|
||||
* the indices defined in Obd2IntegerSensorIndex are to be used to
|
||||
* read from int32Values;
|
||||
* the indices defined in Obd2FloatSensorIndex are to be used to
|
||||
* read from floatValues;
|
||||
* the elements of bytes are to be interpreted as a bitmask, such that
|
||||
* the bits 0 thru the integer value of
|
||||
* Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[0]
|
||||
* are 1 if the corresponding index is a valid sensor index whose value can
|
||||
* be read in the returned int32Values vector, 0 otherwise.
|
||||
* the bits Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX+1 thru
|
||||
* Obd2FloatingSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[1]
|
||||
* are 1 if the corresponding index is a valid sensor index whose value
|
||||
* can be read in the returned floatValues vector, 0 otherwise.
|
||||
* stringValue is the DTC that caused this freeze frame to be recorded.
|
||||
*
|
||||
* For example, int32Values[0] corresponds to FUEL_SYSTEM_STATUS, and
|
||||
* floatValues[0] corresponds to CALCULATED_ENGINE_LOAD, but that mapping
|
||||
* is only valid if the corresponding bits in the bytes vector are set to 1,
|
||||
* and a possible valid stringValue is "P0176" to indicate a malfunction
|
||||
* of the fuel composition sensor circuit.
|
||||
*
|
||||
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
|
||||
* @access VehiclePropertyAccess:READ
|
||||
*/
|
||||
OBD2_FREEZE_FRAME = (
|
||||
0x0D01
|
||||
| VehiclePropertyGroup:SYSTEM
|
||||
| VehiclePropertyType:COMPLEX
|
||||
| VehicleArea:GLOBAL),
|
||||
|
||||
/**
|
||||
* OBD2 Freeze Frame Information
|
||||
*
|
||||
* This property describes the current freeze frames stored in vehicle
|
||||
* memory and available for retrieval via OBD2_FREEZE_FRAME.
|
||||
*
|
||||
* The values are to be interpreted as follows:
|
||||
* each element of int64Values is the timestamp at which a a fault code
|
||||
* has been detected and the corresponding freeze frame stored, and each
|
||||
* such element can be used as the key to OBD2_FREEZE_FRAME to retrieve
|
||||
* the corresponding freeze frame.
|
||||
*
|
||||
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
|
||||
* @access VehiclePropertyAccess:READ
|
||||
*/
|
||||
OBD2_FREEZE_FRAME_INFO = (
|
||||
0x0D02
|
||||
| VehiclePropertyGroup:SYSTEM
|
||||
| VehiclePropertyType:COMPLEX
|
||||
| VehicleArea:GLOBAL),
|
||||
|
||||
/**
|
||||
* OBD2 Freeze Frame Clear
|
||||
*
|
||||
* This property allows deletion of any of the freeze frames stored in
|
||||
* vehicle memory, as described by OBD2_DTC_INFO.
|
||||
*
|
||||
* A set of this property is to be interpreted as follows:
|
||||
* if int64Values contains no elements, then all DTCs stored will be cleared;
|
||||
* if int64Values contains one or more elements, then DTCs at the timestamps
|
||||
* stored in int64Values will be cleared, and the others not cleared, except
|
||||
* the memory will be compacted so that all remaining DTCs are stored
|
||||
* contiguously.
|
||||
*
|
||||
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
|
||||
* @access VehiclePropertyAccess:WRITE
|
||||
*/
|
||||
OBD2_FREEZE_FRAME_CLEAR = (
|
||||
0x0D03
|
||||
| VehiclePropertyGroup:SYSTEM
|
||||
| VehiclePropertyType:COMPLEX
|
||||
| VehicleArea:GLOBAL),
|
||||
|
||||
/**
|
||||
* Vehicle Maps Service (VMS) message
|
||||
*
|
||||
* This property uses COMPLEX data to communicate vms messages.
|
||||
*
|
||||
* Its contents are to be interpreted as follows:
|
||||
* the indices defined in VmsMessageIntegerValuesIndex are to be used to
|
||||
* read from int32Values;
|
||||
* bytes is a serialized VMS message as defined in the vms protocol
|
||||
* which is opaque to the framework;
|
||||
*
|
||||
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
|
||||
* @access VehiclePropertyAccess:READ_WRITE
|
||||
*/
|
||||
VEHICLE_MAP_SERVICE = (
|
||||
0x0C00
|
||||
| VehiclePropertyGroup:SYSTEM
|
||||
| VehiclePropertyType:COMPLEX
|
||||
| VehicleArea:GLOBAL),
|
||||
};
|
||||
|
||||
/** The status of a fuel system as described by the OBD2 specification. */
|
||||
enum FuelSystemStatus : int32_t {
|
||||
OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 1,
|
||||
|
||||
CLOSED_LOOP = 2,
|
||||
|
||||
OPEN_ENGINE_LOAD_OR_DECELERATION = 4,
|
||||
|
||||
OPEN_SYSTEM_FAILURE = 8,
|
||||
|
||||
CLOSED_LOOP_BUT_FEEDBACK_FAULT = 16,
|
||||
};
|
||||
|
||||
/** Defines which ignition monitors are available to be read. */
|
||||
enum IgnitionMonitorKind : int32_t {
|
||||
SPARK = 0,
|
||||
|
||||
COMPRESSION = 1,
|
||||
};
|
||||
|
||||
/** These ignition monitors are common to both SPARK and COMPRESSION. */
|
||||
enum CommonIgnitionMonitors : int32_t {
|
||||
COMPONENTS_AVAILABLE = 0x1 << 0,
|
||||
COMPONENTS_INCOMPLETE = 0x1 << 1,
|
||||
|
||||
FUEL_SYSTEM_AVAILABLE = 0x1 << 2,
|
||||
FUEL_SYSTEM_INCOMPLETE = 0x1 << 3,
|
||||
|
||||
MISFIRE_AVAILABLE = 0x1 << 4,
|
||||
MISFIRE_INCOMPLETE = 0x1 << 5,
|
||||
};
|
||||
|
||||
/** Ignition monitors available for SPARK vehicles. */
|
||||
enum SparkIgnitionMonitors : CommonIgnitionMonitors {
|
||||
EGR_AVAILABLE = 0x1 << 6,
|
||||
EGR_INCOMPLETE = 0x1 << 7,
|
||||
|
||||
OXYGEN_SENSOR_HEATER_AVAILABLE = 0x1 << 8,
|
||||
OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x1 << 9,
|
||||
|
||||
OXYGEN_SENSOR_AVAILABLE = 0x1 << 10,
|
||||
OXYGEN_SENSOR_INCOMPLETE = 0x1 << 11,
|
||||
|
||||
AC_REFRIGERANT_AVAILABLE = 0x1 << 12,
|
||||
AC_REFRIGERANT_INCOMPLETE = 0x1 << 13,
|
||||
|
||||
SECONDARY_AIR_SYSTEM_AVAILABLE = 0x1 << 14,
|
||||
SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x1 << 15,
|
||||
|
||||
EVAPORATIVE_SYSTEM_AVAILABLE = 0x1 << 16,
|
||||
EVAPORATIVE_SYSTEM_INCOMPLETE = 0x1 << 17,
|
||||
|
||||
HEATED_CATALYST_AVAILABLE = 0x1 << 18,
|
||||
HEATED_CATALYST_INCOMPLETE = 0x1 << 19,
|
||||
|
||||
CATALYST_AVAILABLE = 0x1 << 20,
|
||||
CATALYST_INCOMPLETE = 0x1 << 21,
|
||||
};
|
||||
|
||||
/** Ignition monitors only available for COMPRESSION vehicles. */
|
||||
enum CompressionIgnitionMonitors : CommonIgnitionMonitors {
|
||||
EGR_OR_VVT_AVAILABLE = 0x1 << 6,
|
||||
EGR_OR_VVT_INCOMPLETE = 0x1 << 7,
|
||||
|
||||
PM_FILTER_AVAILABLE = 0x1 << 8,
|
||||
PM_FILTER_INCOMPLETE = 0x1 << 9,
|
||||
|
||||
EXHAUST_GAS_SENSOR_AVAILABLE = 0x1 << 10,
|
||||
EXHAUST_GAS_SENSOR_INCOMPLETE = 0x1 << 11,
|
||||
|
||||
BOOST_PRESSURE_AVAILABLE = 0x1 << 12,
|
||||
BOOST_PRESSURE_INCOMPLETE = 0x1 << 13,
|
||||
|
||||
NOx_SCR__AVAILABLE = 0x1 << 14,
|
||||
NOx_SCR_INCOMPLETE = 0x1 << 15,
|
||||
|
||||
NMHC_CATALYST_AVAILABLE = 0x1 << 16,
|
||||
NMHC_CATALYST_INCOMPLETE = 0x1 << 17,
|
||||
};
|
||||
|
||||
enum SecondaryAirStatus : int32_t {
|
||||
UPSTREAM = 1,
|
||||
|
||||
DOWNSTREAM_OF_CATALYCIC_CONVERTER = 2,
|
||||
|
||||
FROM_OUTSIDE_OR_OFF = 4,
|
||||
|
||||
PUMP_ON_FOR_DIAGNOSTICS = 8,
|
||||
};
|
||||
|
||||
enum FuelType : int32_t {
|
||||
NOT_AVAILABLE = 0,
|
||||
|
||||
GASOLINE = 1,
|
||||
|
||||
METHANOL = 2,
|
||||
|
||||
ETHANOL = 3,
|
||||
|
||||
DIESEL = 4,
|
||||
|
||||
LPG = 5,
|
||||
|
||||
CNG = 6,
|
||||
|
||||
PROPANE = 7,
|
||||
|
||||
ELECTRIC = 8,
|
||||
|
||||
BIFUEL_RUNNING_GASOLINE = 9,
|
||||
|
||||
BIFUEL_RUNNING_METHANOL = 10,
|
||||
|
||||
BIFUEL_RUNNING_ETHANOL = 11,
|
||||
|
||||
BIFUEL_RUNNING_LPG = 12,
|
||||
|
||||
BIFUEL_RUNNING_CNG = 13,
|
||||
|
||||
BIFUEL_RUNNING_PROPANE = 14,
|
||||
|
||||
BIFUEL_RUNNING_ELECTRIC = 15,
|
||||
|
||||
BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 16,
|
||||
|
||||
HYBRID_GASOLINE = 17,
|
||||
|
||||
HYBRID_ETHANOL = 18,
|
||||
|
||||
HYBRID_DIESEL = 19,
|
||||
|
||||
HYBRID_ELECTRIC = 20,
|
||||
|
||||
HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 21,
|
||||
|
||||
HYBRID_REGENERATIVE = 22,
|
||||
|
||||
BIFUEL_RUNNING_DIESEL = 23,
|
||||
};
|
||||
|
||||
/**
|
||||
* This enum provides the canonical mapping for sensor properties that have an integer value.
|
||||
* The ordering of the values is taken from the OBD2 specification.
|
||||
* Some of the properties are represented as an integer mapping to another enum. In those cases
|
||||
* expect a comment by the property definition describing the enum to look at for the mapping.
|
||||
* Any value greater than the last reserved index is available to vendors to map their extensions.
|
||||
*/
|
||||
enum Obd2IntegerSensorIndex : int32_t {
|
||||
/** refer to FuelSystemStatus for a description of this value. */
|
||||
FUEL_SYSTEM_STATUS = 0,
|
||||
|
||||
MALFUNCTION_INDICATOR_LIGHT_ON = 1,
|
||||
|
||||
/** refer to IgnitionMonitorKind for a description of this value. */
|
||||
IGNITION_MONITORS_SUPPORTED = 2,
|
||||
|
||||
/**
|
||||
* The value of this sensor is a bitmask that specifies whether ignition-specific
|
||||
* tests are available and whether they are complete. The semantics of the individual
|
||||
* bits in this value are given by, respectively, SparkIgnitionMonitors and
|
||||
* CompressionIgnitionMonitors depending on the value of IGNITION_MONITORS_SUPPORTED.
|
||||
*/
|
||||
IGNITION_SPECIFIC_MONITORS = 3,
|
||||
|
||||
INTAKE_AIR_TEMPERATURE = 4,
|
||||
|
||||
/** refer to SecondaryAirStatus for a description of this value. */
|
||||
COMMANDED_SECONDARY_AIR_STATUS = 5,
|
||||
|
||||
NUM_OXYGEN_SENSORS_PRESENT = 6,
|
||||
|
||||
RUNTIME_SINCE_ENGINE_START = 7,
|
||||
|
||||
DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 8,
|
||||
|
||||
WARMUPS_SINCE_CODES_CLEARED = 9,
|
||||
|
||||
DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 10,
|
||||
|
||||
ABSOLUTE_BAROMETRIC_PRESSURE = 11,
|
||||
|
||||
CONTROL_MODULE_VOLTAGE = 12,
|
||||
|
||||
AMBIENT_AIR_TEMPERATURE = 13,
|
||||
|
||||
TIME_WITH_MALFUNCTION_LIGHT_ON = 14,
|
||||
|
||||
TIME_SINCE_TROUBLE_CODES_CLEARED = 15,
|
||||
|
||||
MAX_FUEL_AIR_EQUIVALENCE_RATIO = 16,
|
||||
|
||||
MAX_OXYGEN_SENSOR_VOLTAGE = 17,
|
||||
|
||||
MAX_OXYGEN_SENSOR_CURRENT = 18,
|
||||
|
||||
MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 19,
|
||||
|
||||
MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 20,
|
||||
|
||||
/** refer to FuelType for a description of this value. */
|
||||
FUEL_TYPE = 21,
|
||||
|
||||
FUEL_RAIL_ABSOLUTE_PRESSURE = 22,
|
||||
|
||||
ENGINE_OIL_TEMPERATURE = 23,
|
||||
|
||||
DRIVER_DEMAND_PERCENT_TORQUE = 24,
|
||||
|
||||
ENGINE_ACTUAL_PERCENT_TORQUE = 25,
|
||||
|
||||
ENGINE_REFERENCE_PERCENT_TORQUE = 26,
|
||||
|
||||
ENGINE_PERCENT_TORQUE_DATA_IDLE = 27,
|
||||
|
||||
ENGINE_PERCENT_TORQUE_DATA_POINT1 = 28,
|
||||
|
||||
ENGINE_PERCENT_TORQUE_DATA_POINT2 = 29,
|
||||
|
||||
ENGINE_PERCENT_TORQUE_DATA_POINT3 = 30,
|
||||
|
||||
ENGINE_PERCENT_TORQUE_DATA_POINT4 = 31,
|
||||
|
||||
LAST_SYSTEM_INDEX = ENGINE_PERCENT_TORQUE_DATA_POINT4,
|
||||
};
|
||||
|
||||
/**
|
||||
* This enum provides the canonical mapping for sensor properties that have a floating-point value.
|
||||
* The ordering of the values is taken from the OBD2 specification.
|
||||
* Any value greater than the last reserved index is available to vendors to map their extensions.
|
||||
*/
|
||||
enum Obd2FloatSensorIndex : int32_t {
|
||||
CALCULATED_ENGINE_LOAD = 0,
|
||||
|
||||
ENGINE_COOLANT_TEMPERATURE = 1,
|
||||
|
||||
SHORT_TERM_FUEL_TRIM_BANK1 = 2,
|
||||
|
||||
LONG_TERM_FUEL_TRIM_BANK1 = 3,
|
||||
|
||||
SHORT_TERM_FUEL_TRIM_BANK2 = 4,
|
||||
|
||||
LONG_TERM_FUEL_TRIM_BANK2 = 5,
|
||||
|
||||
FUEL_PRESSURE = 6,
|
||||
|
||||
INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 7,
|
||||
|
||||
ENGINE_RPM = 8,
|
||||
|
||||
VEHICLE_SPEED = 9,
|
||||
|
||||
TIMING_ADVANCE = 10,
|
||||
|
||||
MAF_AIR_FLOW_RATE = 11,
|
||||
|
||||
THROTTLE_POSITION = 12,
|
||||
|
||||
OXYGEN_SENSOR1_VOLTAGE = 13,
|
||||
|
||||
OXYGEN_SENSOR1_SHORT_TERM_FUEL_TRIM = 14,
|
||||
|
||||
OXYGEN_SENSOR1_FUEL_AIR_EQUIVALENCE_RATIO = 15,
|
||||
|
||||
OXYGEN_SENSOR2_VOLTAGE = 16,
|
||||
|
||||
OXYGEN_SENSOR2_SHORT_TERM_FUEL_TRIM = 17,
|
||||
|
||||
OXYGEN_SENSOR2_FUEL_AIR_EQUIVALENCE_RATIO = 18,
|
||||
|
||||
OXYGEN_SENSOR3_VOLTAGE = 19,
|
||||
|
||||
OXYGEN_SENSOR3_SHORT_TERM_FUEL_TRIM = 20,
|
||||
|
||||
OXYGEN_SENSOR3_FUEL_AIR_EQUIVALENCE_RATIO = 21,
|
||||
|
||||
OXYGEN_SENSOR4_VOLTAGE = 22,
|
||||
|
||||
OXYGEN_SENSOR4_SHORT_TERM_FUEL_TRIM = 23,
|
||||
|
||||
OXYGEN_SENSOR4_FUEL_AIR_EQUIVALENCE_RATIO = 24,
|
||||
|
||||
OXYGEN_SENSOR5_VOLTAGE = 25,
|
||||
|
||||
OXYGEN_SENSOR5_SHORT_TERM_FUEL_TRIM = 26,
|
||||
|
||||
OXYGEN_SENSOR5_FUEL_AIR_EQUIVALENCE_RATIO = 27,
|
||||
|
||||
OXYGEN_SENSOR6_VOLTAGE = 28,
|
||||
|
||||
OXYGEN_SENSOR6_SHORT_TERM_FUEL_TRIM = 29,
|
||||
|
||||
OXYGEN_SENSOR6_FUEL_AIR_EQUIVALENCE_RATIO = 30,
|
||||
|
||||
OXYGEN_SENSOR7_VOLTAGE = 31,
|
||||
|
||||
OXYGEN_SENSOR7_SHORT_TERM_FUEL_TRIM = 32,
|
||||
|
||||
OXYGEN_SENSOR7_FUEL_AIR_EQUIVALENCE_RATIO = 33,
|
||||
|
||||
OXYGEN_SENSOR8_VOLTAGE = 34,
|
||||
|
||||
OXYGEN_SENSOR8_SHORT_TERM_FUEL_TRIM = 35,
|
||||
|
||||
OXYGEN_SENSOR8_FUEL_AIR_EQUIVALENCE_RATIO = 36,
|
||||
|
||||
FUEL_RAIL_PRESSURE = 37,
|
||||
|
||||
FUEL_RAIL_GAUGE_PRESSURE = 38,
|
||||
|
||||
COMMANDED_EXHAUST_GAS_RECIRCULATION = 39,
|
||||
|
||||
EXHAUST_GAS_RECIRCULATION_ERROR = 40,
|
||||
|
||||
COMMANDED_EVAPORATIVE_PURGE = 41,
|
||||
|
||||
FUEL_TANK_LEVEL_INPUT = 42,
|
||||
|
||||
EVAPORATION_SYSTEM_VAPOR_PRESSURE = 43,
|
||||
|
||||
CATALYST_TEMPERATURE_BANK1_SENSOR1 = 44,
|
||||
|
||||
CATALYST_TEMPERATURE_BANK2_SENSOR1 = 45,
|
||||
|
||||
CATALYST_TEMPERATURE_BANK1_SENSOR2 = 46,
|
||||
|
||||
CATALYST_TEMPERATURE_BANK2_SENSOR2 = 47,
|
||||
|
||||
ABSOLUTE_LOAD_VALUE = 48,
|
||||
|
||||
FUEL_AIR_COMMANDED_EQUIVALENCE_RATIO = 49,
|
||||
|
||||
RELATIVE_THROTTLE_POSITION = 50,
|
||||
|
||||
ABSOLUTE_THROTTLE_POSITION_B = 51,
|
||||
|
||||
ABSOLUTE_THROTTLE_POSITION_C = 52,
|
||||
|
||||
ACCELERATOR_PEDAL_POSITION_D = 53,
|
||||
|
||||
ACCELERATOR_PEDAL_POSITION_E = 54,
|
||||
|
||||
ACCELERATOR_PEDAL_POSITION_F = 55,
|
||||
|
||||
COMMANDED_THROTTLE_ACTUATOR = 56,
|
||||
|
||||
ETHANOL_FUEL_PERCENTAGE = 57,
|
||||
|
||||
ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE = 58,
|
||||
|
||||
SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 59,
|
||||
|
||||
SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 60,
|
||||
|
||||
SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61,
|
||||
|
||||
SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 62,
|
||||
|
||||
LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 63,
|
||||
|
||||
LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 64,
|
||||
|
||||
LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 65,
|
||||
|
||||
LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 66,
|
||||
|
||||
RELATIVE_ACCELERATOR_PEDAL_POSITION = 67,
|
||||
|
||||
HYBRID_BATTERY_PACK_REMAINING_LIFE = 68,
|
||||
|
||||
FUEL_INJECTION_TIMING = 69,
|
||||
|
||||
ENGINE_FUEL_RATE = 70,
|
||||
|
||||
LAST_SYSTEM_INDEX = ENGINE_FUEL_RATE,
|
||||
};
|
||||
|
||||
/**
|
||||
* This enum lists the types of supported VMS messages.
|
||||
*/
|
||||
enum VmsMessageType : int32_t {
|
||||
/** A client subscribes to a layer. */
|
||||
SUBSCRIBE = 1,
|
||||
|
||||
/** A client unsubscribes from a layer. */
|
||||
UNSUBSCRIBE = 2,
|
||||
|
||||
/** A client publishes a data packet. */
|
||||
DATA = 3,
|
||||
|
||||
/* A client declaring layers offering. */
|
||||
OFFERING = 4,
|
||||
|
||||
/* Requesting the list of available layers. */
|
||||
AVAILABILITY_REQUEST = 5,
|
||||
|
||||
/* Returning the list of available layers. */
|
||||
AVAILABILITY_RESPONSE = 6,
|
||||
|
||||
/** Requesting layers that have subscribers. */
|
||||
SUBSCRIPTION_REQUEST = 7,
|
||||
|
||||
/** Returning layers that have subscribers. */
|
||||
SUBSCRIPTION_RESPONSE = 8,
|
||||
};
|
||||
|
||||
/**
|
||||
* This enum provides the canonical mapping for VMS properties that have an
|
||||
* integer value.
|
||||
*/
|
||||
enum VmsBaseMessageIntegerValuesIndex : int32_t {
|
||||
/* The message type as enumerated by VmsMessageType enum. */
|
||||
VMS_MESSAGE_TYPE = 0,
|
||||
};
|
||||
|
||||
/*
|
||||
* This enum provides the canonical mapping for VMS SUBMIT, UNSUBMIT and DATA
|
||||
* messages integer value properties.
|
||||
*/
|
||||
enum VmsSimpleMessageIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
|
||||
/* The layer ID as defined in the vms protocol. */
|
||||
VMS_LAYER_ID = 1,
|
||||
|
||||
/* The version of the VMS layer. */
|
||||
VMS_LAYER_VERSION = 2,
|
||||
};
|
||||
|
||||
/*
|
||||
* This enum provides the canonical mapping for VMS offering messages integer
|
||||
* value properties
|
||||
*/
|
||||
enum VmsOfferingMessageIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
|
||||
/* The number of VMS layer dependencies. */
|
||||
VMS_NUMBER_OF_LAYERS_DEPENDENCIES = 1,
|
||||
|
||||
/* The first index that contain dependencies */
|
||||
FIRST_DEPENDENCIES_INDEX = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* A VMS subscription request only contains its message type. The format of a VMS subscription
|
||||
* response is described below.
|
||||
*/
|
||||
enum VmsSubscriptionResponseFormat : VmsBaseMessageIntegerValuesIndex {
|
||||
/**
|
||||
* Recipients should ignore any packet with a sequence number that is less than the highest
|
||||
* sequence number they have seen thus far.
|
||||
*/
|
||||
SEQUENCE_NUMBER = 1,
|
||||
|
||||
/** The number of VMS layers. Each layer has two integers: type and version. */
|
||||
NUMBER_OF_LAYERS = 2,
|
||||
|
||||
/** The first index that contains a layer. */
|
||||
FIRST_LAYER = 3,
|
||||
};
|
||||
@@ -145,6 +145,7 @@ FingerprintAcquiredInfo BiometricsFingerprint::VendorAcquiredFilter(
|
||||
|
||||
Return<uint64_t> BiometricsFingerprint::setNotify(
|
||||
const sp<IBiometricsFingerprintClientCallback>& clientCallback) {
|
||||
std::lock_guard<std::mutex> lock(mClientCallbackMutex);
|
||||
mClientCallback = clientCallback;
|
||||
// This is here because HAL 2.1 doesn't have a way to propagate a
|
||||
// unique token for its driver. Subsequent versions should send a unique
|
||||
@@ -259,6 +260,7 @@ fingerprint_device_t* BiometricsFingerprint::openHal() {
|
||||
void BiometricsFingerprint::notify(const fingerprint_msg_t *msg) {
|
||||
BiometricsFingerprint* thisPtr = static_cast<BiometricsFingerprint*>(
|
||||
BiometricsFingerprint::getInstance());
|
||||
std::lock_guard<std::mutex> lock(thisPtr->mClientCallbackMutex);
|
||||
if (thisPtr == nullptr || thisPtr->mClientCallback == nullptr) {
|
||||
ALOGE("Receiving callbacks before the client callback is registered.");
|
||||
return;
|
||||
|
||||
@@ -69,6 +69,7 @@ private:
|
||||
static FingerprintAcquiredInfo VendorAcquiredFilter(int32_t error, int32_t* vendorCode);
|
||||
static BiometricsFingerprint* sInstance;
|
||||
|
||||
std::mutex mClientCallbackMutex;
|
||||
sp<IBiometricsFingerprintClientCallback> mClientCallback;
|
||||
fingerprint_device_t *mDevice;
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <utils/Log.h>
|
||||
#include <log/log.h>
|
||||
#include <vector>
|
||||
#include "fcntl.h"
|
||||
#include "sys/select.h"
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <cutils/properties.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <log/log.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <log/log.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
@@ -146,8 +146,11 @@ enum MetadataType : int32_t {
|
||||
/** String */
|
||||
TEXT = 1,
|
||||
/**
|
||||
* Raw binary data (icon or art)
|
||||
This data must be transparent to the android framework */
|
||||
* Raw binary data (icon or art).
|
||||
*
|
||||
* The data should be a valid PNG, JPEG, GIF or BMP file.
|
||||
* Invalid format must be handled gracefully as if the field was missing.
|
||||
*/
|
||||
RAW = 2,
|
||||
/** clock data, see MetaDataClock */
|
||||
CLOCK = 3,
|
||||
@@ -155,7 +158,7 @@ enum MetadataType : int32_t {
|
||||
|
||||
enum MetadataKey : int32_t {
|
||||
INVALID = -1,
|
||||
/** RDS PI - string */
|
||||
/** RDS PI - int32_t */
|
||||
RDS_PI = 0,
|
||||
/** RDS PS - string */
|
||||
RDS_PS = 1,
|
||||
@@ -173,9 +176,9 @@ enum MetadataKey : int32_t {
|
||||
ALBUM = 7,
|
||||
/** Musical genre - string */
|
||||
GENRE = 8,
|
||||
/** Station icon - raw */
|
||||
/** Station icon - raw (int32_t for HAL 1.1) */
|
||||
ICON = 9,
|
||||
/** Album art - raw */
|
||||
/** Album art - raw (int32_t for HAL 1.1) */
|
||||
ART = 10,
|
||||
/** Clock - MetaDataClock */
|
||||
CLOCK = 11,
|
||||
@@ -208,10 +211,24 @@ struct MetaData {
|
||||
struct ProgramInfo {
|
||||
uint32_t channel; /** current channel. (e.g kHz for band type AM_FM) */
|
||||
uint32_t subChannel; /** current sub channel. (FM_HD) */
|
||||
bool tuned; /** tuned to a program or not */
|
||||
|
||||
/**
|
||||
* Tuned to a program (not a noise). It's the same condition that would
|
||||
* stop scan operation.
|
||||
*/
|
||||
bool tuned;
|
||||
|
||||
bool stereo; /** program is stereo or not */
|
||||
bool digital; /** digital program or not (e.g HD Radio program) */
|
||||
uint32_t signalStrength; /** signal strength from 0 to 100 */
|
||||
vec<MetaData> metadata; /** non empty if meta data are present (e.g PTY, song title ...) */
|
||||
|
||||
/**
|
||||
* Signal quality measured in 0% to 100% range.
|
||||
*
|
||||
* Despite the name, this is not a signal strength.
|
||||
* The purpose of this field is primarily informative.
|
||||
*/
|
||||
uint32_t signalStrength;
|
||||
|
||||
vec<MetaData> metadata; /** Metadata: PTY, song title etc. */
|
||||
};
|
||||
|
||||
|
||||
@@ -27,4 +27,38 @@ interface IBroadcastRadio extends @1.0::IBroadcastRadio {
|
||||
*/
|
||||
getProperties_1_1() generates (Properties properties);
|
||||
|
||||
/**
|
||||
* Fetch image from radio module.
|
||||
*
|
||||
* This call is meant to make V1_0::MetaData lightweight - instead of
|
||||
* passing an image data blob in the MetadataType.RAW field, the HAL
|
||||
* implementation only passes the identifier, so the client may cache images
|
||||
* or even not fetch them.
|
||||
*
|
||||
* The identifier may be any arbitrary number - sequential, sha256 prefix,
|
||||
* or any other unique value selected by the vendor.
|
||||
*
|
||||
* The data should be a valid PNG, JPEG, GIF or BMP file.
|
||||
* Image data with an invalid format must be handled gracefully in the same
|
||||
* way as a missing image.
|
||||
*
|
||||
* The image identifier may become invalid after some time from passing it
|
||||
* with metadata struct (due to resource cleanup at the HAL implementation).
|
||||
* However, it must remain valid for a currently tuned program at least
|
||||
* until currentProgramInfoChanged or programListChanged is called and
|
||||
* metadata changes for the current program.
|
||||
*
|
||||
* There is still a race condition possible (if the HAL deletes the old
|
||||
* image immediately after notifying about the new one) between
|
||||
* currentProgramInfoChanged callback propagating through the framework and
|
||||
* the HAL implementation removing previous image. In such case, client
|
||||
* application may expect the new currentProgramInfoChanged callback with
|
||||
* updated image identifier.
|
||||
*
|
||||
* @param id Identifier of an image;
|
||||
* value of 0 is reserved and should be treated as invalid image.
|
||||
* @return image A binary blob with image data
|
||||
* or a zero-length vector if identifier doesn't exist.
|
||||
*/
|
||||
getImage(int32_t id) generates (vec<uint8_t> image);
|
||||
};
|
||||
|
||||
@@ -19,8 +19,10 @@ package android.hardware.broadcastradio@1.1;
|
||||
import @1.0::IBroadcastRadioFactory;
|
||||
|
||||
/**
|
||||
* To use 1.1 features you must cast specific interfaces after being returned from 1.0 HAL,
|
||||
* for example V1_1::ITuner::castFrom() after retrieving it from IBroadcastRadio::openTuner().
|
||||
* To use 1.1 features you must cast specific interfaces returned from the
|
||||
* 1.0 HAL. For example V1_0::IBroadcastRadio::openTuner() returns V1_0::ITuner,
|
||||
* which can be cast with V1_1::ITuner::castFrom() call.
|
||||
*
|
||||
* The 1.1 server must always return the 1.1 version of specific interface.
|
||||
*/
|
||||
interface IBroadcastRadioFactory extends @1.0::IBroadcastRadioFactory {
|
||||
|
||||
@@ -20,6 +20,45 @@ import @1.0::ITuner;
|
||||
|
||||
interface ITuner extends @1.0::ITuner {
|
||||
|
||||
/**
|
||||
* Tune to a specified program.
|
||||
*
|
||||
* For AM/FM, it must be called when a valid configuration has been applied.
|
||||
* Automatically cancels pending scan, step or tune.
|
||||
*
|
||||
* If method returns OK, ITunerCallback.tuneComplete_1_1() MUST be called:
|
||||
* - once successfully tuned;
|
||||
* - after a time out;
|
||||
* - after a full band scan, if no station found.
|
||||
*
|
||||
* The tuned field of ProgramInfo should indicate if tuned to a valid
|
||||
* station or not.
|
||||
*
|
||||
* @param program Program to tune to.
|
||||
* @return result OK if successfully started tunning.
|
||||
* INVALID_ARGUMENTS if invalid arguments are passed.
|
||||
* NOT_INITIALIZED if another error occurs.
|
||||
*/
|
||||
tuneByProgramSelector(ProgramSelector program) generates (Result result);
|
||||
|
||||
/**
|
||||
* Cancels announcement.
|
||||
*
|
||||
* If it was traffic announcement, trafficAnnouncement(false) callback
|
||||
* should be called (just like it was ended in a normal way). Similarly for
|
||||
* emergency announcement. If there was no announcement, then no action
|
||||
* should be taken.
|
||||
*
|
||||
* There is a race condition between calling cancelAnnouncement and the
|
||||
* actual announcement being finished, so trafficAnnouncement /
|
||||
* emergencyAnnouncement callback should be tracked with proper locking.
|
||||
*
|
||||
* @return result OK if successfully cancelled announcement or there was
|
||||
* no announcement.
|
||||
* NOT_INITIALIZED if another error occurs.
|
||||
*/
|
||||
cancelAnnouncement() generates (Result result);
|
||||
|
||||
/**
|
||||
* Retrieve current station information.
|
||||
* @return result OK if scan successfully started
|
||||
@@ -45,6 +84,13 @@ interface ITuner extends @1.0::ITuner {
|
||||
* subsequent calls to startBackgroundScan, issuing a single
|
||||
* backgroundScanComplete callback.
|
||||
*
|
||||
* If a device supports continuous background scanning, it may succeed
|
||||
* (return OK and call backgroundScanComplete) without any additional
|
||||
* operation performed.
|
||||
*
|
||||
* Foreground scanning may be implemented in the front end app with
|
||||
* @1.0::ITuner scan operation.
|
||||
*
|
||||
* @return result OK if the scan was properly scheduled (this does not mean
|
||||
* it successfully finished).
|
||||
* UNAVAILABLE if the background scan is unavailable,
|
||||
@@ -60,10 +106,8 @@ interface ITuner extends @1.0::ITuner {
|
||||
* This call does not trigger actual scan, but operates on the list cached
|
||||
* internally at the driver level.
|
||||
*
|
||||
* @param filter vendor-specific filter for the stations to be retrieved.
|
||||
* An empty string MUST result in full list.
|
||||
* Client application MUST verify vendor/product name
|
||||
* before setting this parameter to anything else.
|
||||
* @param vendorFilter vendor-specific filter for the stations to be retrieved.
|
||||
* An empty vector MUST result in full list for a given tuner.
|
||||
* @return result OK if the list was successfully retrieved.
|
||||
* INVALID_ARGUMENTS if invalid arguments are passed
|
||||
* NOT_READY if the scan is in progress.
|
||||
@@ -72,22 +116,9 @@ interface ITuner extends @1.0::ITuner {
|
||||
* NOT_INITIALIZED if any other error occurs.
|
||||
* @return programList List of stations available for user.
|
||||
*/
|
||||
getProgramList(string filter)
|
||||
getProgramList(vec<VendorKeyValue> vendorFilter)
|
||||
generates (ProgramListResult result, vec<ProgramInfo> programList);
|
||||
|
||||
/**
|
||||
* Checks, if the analog playback is forced, see setAnalogForced.
|
||||
*
|
||||
* The isForced value is only valid if result was OK.
|
||||
*
|
||||
* @return result OK if the call succeeded and isForced is valid.
|
||||
* INVALID_STATE if the switch is not supported at current
|
||||
* configuration.
|
||||
* NOT_INITIALIZED if any other error occurs.
|
||||
* @return isForced true if analog is forced, false otherwise.
|
||||
*/
|
||||
isAnalogForced() generates (Result result, bool isForced);
|
||||
|
||||
/**
|
||||
* Forces the analog playback for the supporting radio technology.
|
||||
*
|
||||
@@ -104,4 +135,17 @@ interface ITuner extends @1.0::ITuner {
|
||||
* NOT_INITIALIZED if any other error occurs.
|
||||
*/
|
||||
setAnalogForced(bool isForced) generates (Result result);
|
||||
|
||||
/**
|
||||
* Checks, if the analog playback is forced, see setAnalogForced.
|
||||
*
|
||||
* The isForced value is only valid if result was OK.
|
||||
*
|
||||
* @return result OK if the call succeeded and isForced is valid.
|
||||
* INVALID_STATE if the switch is not supported at current
|
||||
* configuration.
|
||||
* NOT_INITIALIZED if any other error occurs.
|
||||
* @return isForced true if analog is forced, false otherwise.
|
||||
*/
|
||||
isAnalogForced() generates (Result result, bool isForced);
|
||||
};
|
||||
|
||||
@@ -28,16 +28,19 @@ interface ITunerCallback extends @1.0::ITunerCallback {
|
||||
/**
|
||||
* Method called by the HAL when a tuning operation completes
|
||||
* following a step(), scan() or tune() command.
|
||||
*
|
||||
* This callback supersedes V1_0::tuneComplete.
|
||||
* The 1.0 callback must not be called when HAL implementation detects
|
||||
* 1.1 client (by casting V1_0::ITunerCallback to V1_1::ITunerCallback).
|
||||
*
|
||||
* In case of success, currentProgramInfoChanged must be called too.
|
||||
* It means the success case may (or may not) be handled by the client in
|
||||
* currentProgramInfoChanged, instead of here.
|
||||
*
|
||||
* @param result OK if tune succeeded or TIMEOUT in case of time out.
|
||||
* @param info A ProgramInfo structure describing the tuned station.
|
||||
* @param selector A ProgramSelector structure describing the tuned station.
|
||||
*/
|
||||
oneway tuneComplete_1_1(Result result, ProgramInfo info);
|
||||
|
||||
/**
|
||||
* Method called by the HAL when a frequency switch occurs.
|
||||
* @param info A ProgramInfo structure describing the new tuned station.
|
||||
*/
|
||||
oneway afSwitch_1_1(ProgramInfo info);
|
||||
oneway tuneComplete_1_1(Result result, ProgramSelector selector);
|
||||
|
||||
/**
|
||||
* Called by the HAL when background scan feature becomes available or not.
|
||||
@@ -63,10 +66,31 @@ interface ITunerCallback extends @1.0::ITunerCallback {
|
||||
* call it immediately, ie. it may wait for a short time to accumulate
|
||||
* multiple list change notifications into a single event.
|
||||
*
|
||||
* This callback is only for notifying about insertions and deletions,
|
||||
* not about metadata changes.
|
||||
*
|
||||
* It may be triggered either by an explicitly issued background scan,
|
||||
* or a scan issued by the device internally.
|
||||
*
|
||||
* Client may retrieve the actual list with ITuner::getProgramList.
|
||||
*/
|
||||
oneway programListChanged();
|
||||
|
||||
/**
|
||||
* Method called by the HAL when current program information (including
|
||||
* metadata) is updated.
|
||||
*
|
||||
* Client may retrieve the actual program info with
|
||||
* ITuner::getProgramInformation_1_1.
|
||||
*
|
||||
* This may be called together with tuneComplete_1_1 or afSwitch_1_1.
|
||||
*
|
||||
* This callback supersedes V1_0::newMetadata and V1_0::afSwitch;
|
||||
* partly V1_0::tuneComplete.
|
||||
* 1.0 callbacks must not be called when HAL implementation detects
|
||||
* 1.1 client (by casting V1_0::ITunerCallback to V1_1::ITunerCallback).
|
||||
*
|
||||
* @param info current program information
|
||||
*/
|
||||
oneway currentProgramInfoChanged(ProgramInfo info);
|
||||
};
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
This is experimental interface, do not use it yet.
|
||||
@@ -14,8 +14,9 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
cc_library_shared {
|
||||
name: "android.hardware.broadcastradio@1.1-impl",
|
||||
cc_binary {
|
||||
name: "android.hardware.broadcastradio@1.1-service",
|
||||
init_rc: ["android.hardware.broadcastradio@1.1-service.rc"],
|
||||
vendor: true,
|
||||
relative_install_path: "hw",
|
||||
cflags: [
|
||||
@@ -27,16 +28,20 @@ cc_library_shared {
|
||||
"BroadcastRadio.cpp",
|
||||
"BroadcastRadioFactory.cpp",
|
||||
"Tuner.cpp",
|
||||
"Utils.cpp",
|
||||
"VirtualProgram.cpp",
|
||||
"VirtualRadio.cpp",
|
||||
"service.cpp"
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.broadcastradio@1.1-utils-lib",
|
||||
],
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libutils",
|
||||
"liblog",
|
||||
"libhardware",
|
||||
"android.hardware.broadcastradio@1.0",
|
||||
"android.hardware.broadcastradio@1.1",
|
||||
"libradio_metadata",
|
||||
"libbase",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"liblog",
|
||||
"libutils",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#define LOG_TAG "BroadcastRadio"
|
||||
//#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "BroadcastRadioDefault.module"
|
||||
#define LOG_NDEBUG 0
|
||||
|
||||
#include "BroadcastRadio.h"
|
||||
|
||||
#include <log/log.h>
|
||||
|
||||
#include "BroadcastRadio.h"
|
||||
#include "Tuner.h"
|
||||
#include "Utils.h"
|
||||
#include "resources.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -28,117 +28,163 @@ namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::sp;
|
||||
using V1_0::Band;
|
||||
using V1_0::BandConfig;
|
||||
using V1_0::Class;
|
||||
using V1_0::Deemphasis;
|
||||
using V1_0::Rds;
|
||||
|
||||
using std::lock_guard;
|
||||
using std::map;
|
||||
using std::mutex;
|
||||
using std::vector;
|
||||
|
||||
// clang-format off
|
||||
static const map<Class, ModuleConfig> gModuleConfigs{
|
||||
{Class::AM_FM, ModuleConfig({
|
||||
"Digital radio mock",
|
||||
{ // amFmBands
|
||||
AmFmBandConfig({
|
||||
Band::AM,
|
||||
153, // lowerLimit
|
||||
26100, // upperLimit
|
||||
{5, 9, 10}, // spacings
|
||||
}),
|
||||
AmFmBandConfig({
|
||||
Band::FM,
|
||||
65800, // lowerLimit
|
||||
108000, // upperLimit
|
||||
{10, 100, 200}, // spacings
|
||||
}),
|
||||
AmFmBandConfig({
|
||||
Band::AM_HD,
|
||||
153, // lowerLimit
|
||||
26100, // upperLimit
|
||||
{5, 9, 10}, // spacings
|
||||
}),
|
||||
AmFmBandConfig({
|
||||
Band::FM_HD,
|
||||
87700, // lowerLimit
|
||||
107900, // upperLimit
|
||||
{200}, // spacings
|
||||
}),
|
||||
},
|
||||
})},
|
||||
|
||||
{Class::SAT, ModuleConfig({
|
||||
"Satellite radio mock",
|
||||
{}, // amFmBands
|
||||
})},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
BroadcastRadio::BroadcastRadio(Class classId)
|
||||
: mStatus(Result::NOT_INITIALIZED), mClassId(classId), mHwDevice(NULL)
|
||||
{
|
||||
: mClassId(classId), mConfig(gModuleConfigs.at(classId)) {}
|
||||
|
||||
bool BroadcastRadio::isSupported(Class classId) {
|
||||
return gModuleConfigs.find(classId) != gModuleConfigs.end();
|
||||
}
|
||||
|
||||
BroadcastRadio::~BroadcastRadio()
|
||||
{
|
||||
if (mHwDevice != NULL) {
|
||||
radio_hw_device_close(mHwDevice);
|
||||
}
|
||||
Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) {
|
||||
ALOGV("%s", __func__);
|
||||
return getProperties_1_1(
|
||||
[&](const Properties& properties) { _hidl_cb(Result::OK, properties.base); });
|
||||
}
|
||||
|
||||
void BroadcastRadio::onFirstRef()
|
||||
{
|
||||
const hw_module_t *mod;
|
||||
int rc;
|
||||
ALOGI("%s mClassId %d", __FUNCTION__, mClassId);
|
||||
Return<void> BroadcastRadio::getProperties_1_1(getProperties_1_1_cb _hidl_cb) {
|
||||
ALOGV("%s", __func__);
|
||||
Properties prop11 = {};
|
||||
auto& prop10 = prop11.base;
|
||||
|
||||
mHwDevice = NULL;
|
||||
const char *classString = Utils::getClassString(mClassId);
|
||||
if (classString == NULL) {
|
||||
ALOGE("invalid class ID %d", mClassId);
|
||||
mStatus = Result::INVALID_ARGUMENTS;
|
||||
return;
|
||||
prop10.classId = mClassId;
|
||||
prop10.implementor = "Google";
|
||||
prop10.product = mConfig.productName;
|
||||
prop10.numTuners = 1;
|
||||
prop10.numAudioSources = 1;
|
||||
prop10.supportsCapture = false;
|
||||
prop11.supportsBackgroundScanning = false;
|
||||
prop11.supportedProgramTypes = hidl_vec<uint32_t>({
|
||||
static_cast<uint32_t>(ProgramType::AM), static_cast<uint32_t>(ProgramType::FM),
|
||||
static_cast<uint32_t>(ProgramType::AM_HD), static_cast<uint32_t>(ProgramType::FM_HD),
|
||||
});
|
||||
prop11.supportedIdentifierTypes = hidl_vec<uint32_t>({
|
||||
static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY),
|
||||
static_cast<uint32_t>(IdentifierType::RDS_PI),
|
||||
static_cast<uint32_t>(IdentifierType::HD_STATION_ID_EXT),
|
||||
static_cast<uint32_t>(IdentifierType::HD_SUBCHANNEL),
|
||||
});
|
||||
prop11.vendorInfo = hidl_vec<VendorKeyValue>({
|
||||
{"com.google.dummy", "dummy"},
|
||||
});
|
||||
|
||||
prop10.bands.resize(mConfig.amFmBands.size());
|
||||
for (size_t i = 0; i < mConfig.amFmBands.size(); i++) {
|
||||
auto& src = mConfig.amFmBands[i];
|
||||
auto& dst = prop10.bands[i];
|
||||
|
||||
dst.type = src.type;
|
||||
dst.antennaConnected = true;
|
||||
dst.lowerLimit = src.lowerLimit;
|
||||
dst.upperLimit = src.upperLimit;
|
||||
dst.spacings = src.spacings;
|
||||
|
||||
if (utils::isAm(src.type)) {
|
||||
dst.ext.am.stereo = true;
|
||||
} else if (utils::isFm(src.type)) {
|
||||
dst.ext.fm.deemphasis = static_cast<Deemphasis>(Deemphasis::D50 | Deemphasis::D75);
|
||||
dst.ext.fm.stereo = true;
|
||||
dst.ext.fm.rds = static_cast<Rds>(Rds::WORLD | Rds::US);
|
||||
dst.ext.fm.ta = true;
|
||||
dst.ext.fm.af = true;
|
||||
dst.ext.fm.ea = true;
|
||||
}
|
||||
}
|
||||
|
||||
ALOGI("%s RADIO_HARDWARE_MODULE_ID %s %s",
|
||||
__FUNCTION__, RADIO_HARDWARE_MODULE_ID, classString);
|
||||
|
||||
rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, classString, &mod);
|
||||
if (rc != 0) {
|
||||
ALOGE("couldn't load radio module %s.%s (%s)",
|
||||
RADIO_HARDWARE_MODULE_ID, classString, strerror(-rc));
|
||||
return;
|
||||
}
|
||||
rc = radio_hw_device_open(mod, &mHwDevice);
|
||||
if (rc != 0) {
|
||||
ALOGE("couldn't open radio hw device in %s.%s (%s)",
|
||||
RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
|
||||
mHwDevice = NULL;
|
||||
return;
|
||||
}
|
||||
if (mHwDevice->common.version != RADIO_DEVICE_API_VERSION_CURRENT) {
|
||||
ALOGE("wrong radio hw device version %04x", mHwDevice->common.version);
|
||||
radio_hw_device_close(mHwDevice);
|
||||
mHwDevice = NULL;
|
||||
} else {
|
||||
mStatus = Result::OK;
|
||||
}
|
||||
}
|
||||
|
||||
int BroadcastRadio::closeHalTuner(const struct radio_tuner *halTuner)
|
||||
{
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
if (mHwDevice == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
if (halTuner == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return mHwDevice->close_tuner(mHwDevice, halTuner);
|
||||
}
|
||||
|
||||
|
||||
// Methods from ::android::hardware::broadcastradio::V1_1::IBroadcastRadio follow.
|
||||
Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb)
|
||||
{
|
||||
int rc;
|
||||
radio_hal_properties_t halProperties;
|
||||
Properties properties;
|
||||
|
||||
if (mHwDevice == NULL) {
|
||||
rc = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
rc = mHwDevice->get_properties(mHwDevice, &halProperties);
|
||||
if (rc == 0) {
|
||||
Utils::convertPropertiesFromHal(&properties, &halProperties);
|
||||
}
|
||||
|
||||
exit:
|
||||
_hidl_cb(Utils::convertHalResult(rc), properties);
|
||||
_hidl_cb(prop11);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> BroadcastRadio::getProperties_1_1(getProperties_1_1_cb _hidl_cb __unused)
|
||||
{
|
||||
return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio __unused,
|
||||
const sp<V1_0::ITunerCallback>& callback,
|
||||
openTuner_cb _hidl_cb) {
|
||||
ALOGV("%s(%s)", __func__, toString(config.type).c_str());
|
||||
lock_guard<mutex> lk(mMut);
|
||||
|
||||
Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio,
|
||||
const sp<V1_0::ITunerCallback>& callback, openTuner_cb _hidl_cb)
|
||||
{
|
||||
sp<Tuner> tunerImpl = new Tuner(callback, this);
|
||||
|
||||
radio_hal_band_config_t halConfig;
|
||||
const struct radio_tuner *halTuner;
|
||||
Utils::convertBandConfigToHal(&halConfig, &config);
|
||||
int rc = mHwDevice->open_tuner(mHwDevice, &halConfig, audio, Tuner::callback,
|
||||
tunerImpl.get(), &halTuner);
|
||||
if (rc == 0) {
|
||||
tunerImpl->setHalTuner(halTuner);
|
||||
auto oldTuner = mTuner.promote();
|
||||
if (oldTuner != nullptr) {
|
||||
ALOGI("Force-closing previously opened tuner");
|
||||
oldTuner->forceClose();
|
||||
mTuner = nullptr;
|
||||
}
|
||||
|
||||
_hidl_cb(Utils::convertHalResult(rc), tunerImpl);
|
||||
sp<Tuner> newTuner = new Tuner(mClassId, callback);
|
||||
mTuner = newTuner;
|
||||
if (mClassId == Class::AM_FM) {
|
||||
auto ret = newTuner->setConfiguration(config);
|
||||
if (ret != Result::OK) {
|
||||
_hidl_cb(Result::INVALID_ARGUMENTS, {});
|
||||
return Void();
|
||||
}
|
||||
}
|
||||
|
||||
_hidl_cb(Result::OK, newTuner);
|
||||
return Void();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
Return<void> BroadcastRadio::getImage(int32_t id, getImage_cb _hidl_cb) {
|
||||
ALOGV("%s(%x)", __func__, id);
|
||||
|
||||
if (id == resources::demoPngId) {
|
||||
_hidl_cb(std::vector<uint8_t>(resources::demoPng, std::end(resources::demoPng)));
|
||||
return {};
|
||||
}
|
||||
|
||||
ALOGI("Image %x doesn't exists", id);
|
||||
_hidl_cb({});
|
||||
return Void();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_1
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIO_H
|
||||
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIO_H
|
||||
|
||||
#include "Tuner.h"
|
||||
|
||||
#include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
|
||||
#include <android/hardware/broadcastradio/1.1/types.h>
|
||||
#include <hardware/radio.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -26,42 +27,49 @@ namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace implementation {
|
||||
|
||||
using V1_0::Class;
|
||||
using V1_0::BandConfig;
|
||||
using V1_0::Properties;
|
||||
struct AmFmBandConfig {
|
||||
V1_0::Band type;
|
||||
uint32_t lowerLimit; // kHz
|
||||
uint32_t upperLimit; // kHz
|
||||
std::vector<uint32_t> spacings; // kHz
|
||||
};
|
||||
|
||||
struct ModuleConfig {
|
||||
std::string productName;
|
||||
std::vector<AmFmBandConfig> amFmBands;
|
||||
};
|
||||
|
||||
struct BroadcastRadio : public V1_1::IBroadcastRadio {
|
||||
/**
|
||||
* Constructs new broadcast radio module.
|
||||
*
|
||||
* Before calling a constructor with a given classId, it must be checked with isSupported
|
||||
* method first. Otherwise it results in undefined behaviour.
|
||||
*
|
||||
* @param classId type of a radio.
|
||||
*/
|
||||
BroadcastRadio(V1_0::Class classId);
|
||||
|
||||
BroadcastRadio(Class classId);
|
||||
/**
|
||||
* Checks, if a given radio type is supported.
|
||||
*
|
||||
* @param classId type of a radio.
|
||||
*/
|
||||
static bool isSupported(V1_0::Class classId);
|
||||
|
||||
// Methods from ::android::hardware::broadcastradio::V1_1::IBroadcastRadio follow.
|
||||
// V1_1::IBroadcastRadio methods
|
||||
Return<void> getProperties(getProperties_cb _hidl_cb) override;
|
||||
Return<void> getProperties_1_1(getProperties_1_1_cb _hidl_cb) override;
|
||||
Return<void> openTuner(const BandConfig& config, bool audio,
|
||||
const sp<V1_0::ITunerCallback>& callback, openTuner_cb _hidl_cb) override;
|
||||
Return<void> openTuner(const V1_0::BandConfig& config, bool audio,
|
||||
const sp<V1_0::ITunerCallback>& callback,
|
||||
openTuner_cb _hidl_cb) override;
|
||||
Return<void> getImage(int32_t id, getImage_cb _hidl_cb);
|
||||
|
||||
// RefBase
|
||||
virtual void onFirstRef() override;
|
||||
|
||||
Result initCheck() { return mStatus; }
|
||||
int closeHalTuner(const struct radio_tuner *halTuner);
|
||||
|
||||
private:
|
||||
virtual ~BroadcastRadio();
|
||||
|
||||
static const char * sClassModuleNames[];
|
||||
|
||||
Result convertHalResult(int rc);
|
||||
void convertBandConfigFromHal(BandConfig *config,
|
||||
const radio_hal_band_config_t *halConfig);
|
||||
void convertPropertiesFromHal(Properties *properties,
|
||||
const radio_hal_properties_t *halProperties);
|
||||
void convertBandConfigToHal(radio_hal_band_config_t *halConfig,
|
||||
const BandConfig *config);
|
||||
|
||||
Result mStatus;
|
||||
Class mClassId;
|
||||
struct radio_hw_device *mHwDevice;
|
||||
private:
|
||||
std::mutex mMut;
|
||||
V1_0::Class mClassId;
|
||||
ModuleConfig mConfig;
|
||||
wp<Tuner> mTuner;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
@@ -13,29 +13,51 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#define LOG_TAG "BroadcastRadioDefault.factory"
|
||||
#define LOG_NDEBUG 0
|
||||
|
||||
#include "BroadcastRadioFactory.h"
|
||||
|
||||
#include "BroadcastRadio.h"
|
||||
|
||||
#include <log/log.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace implementation {
|
||||
|
||||
// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow.
|
||||
Return<void> BroadcastRadioFactory::connectModule(Class classId, connectModule_cb _hidl_cb) {
|
||||
sp<BroadcastRadio> impl = new BroadcastRadio(classId);
|
||||
Result retval = Result::NOT_INITIALIZED;
|
||||
if (impl != 0) {
|
||||
retval = impl->initCheck();
|
||||
}
|
||||
_hidl_cb(retval, impl);
|
||||
return Void();
|
||||
using V1_0::Class;
|
||||
|
||||
using std::vector;
|
||||
|
||||
static const vector<Class> gAllClasses = {
|
||||
Class::AM_FM, Class::SAT, Class::DT,
|
||||
};
|
||||
|
||||
IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name __unused) {
|
||||
return new BroadcastRadioFactory();
|
||||
}
|
||||
|
||||
BroadcastRadioFactory::BroadcastRadioFactory() {
|
||||
for (auto&& classId : gAllClasses) {
|
||||
if (!BroadcastRadio::isSupported(classId)) continue;
|
||||
mRadioModules[classId] = new BroadcastRadio(classId);
|
||||
}
|
||||
}
|
||||
|
||||
IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* /* name */) {
|
||||
return new BroadcastRadioFactory();
|
||||
Return<void> BroadcastRadioFactory::connectModule(Class classId, connectModule_cb _hidl_cb) {
|
||||
ALOGV("%s(%s)", __func__, toString(classId).c_str());
|
||||
|
||||
auto moduleIt = mRadioModules.find(classId);
|
||||
if (moduleIt == mRadioModules.end()) {
|
||||
_hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
|
||||
} else {
|
||||
_hidl_cb(Result::OK, moduleIt->second);
|
||||
}
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIOFACTORY_H
|
||||
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIOFACTORY_H
|
||||
|
||||
#include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
|
||||
#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
|
||||
#include <android/hardware/broadcastradio/1.1/types.h>
|
||||
|
||||
@@ -25,14 +26,17 @@ namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace implementation {
|
||||
|
||||
using V1_0::Class;
|
||||
extern "C" IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name);
|
||||
|
||||
struct BroadcastRadioFactory : public IBroadcastRadioFactory {
|
||||
// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow.
|
||||
Return<void> connectModule(Class classId, connectModule_cb _hidl_cb) override;
|
||||
};
|
||||
BroadcastRadioFactory();
|
||||
|
||||
extern "C" IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name);
|
||||
// V1_0::IBroadcastRadioFactory methods
|
||||
Return<void> connectModule(V1_0::Class classId, connectModule_cb _hidl_cb) override;
|
||||
|
||||
private:
|
||||
std::map<V1_0::Class, sp<IBroadcastRadio>> mRadioModules;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_1
|
||||
|
||||
4
broadcastradio/1.1/default/OWNERS
Normal file
4
broadcastradio/1.1/default/OWNERS
Normal file
@@ -0,0 +1,4 @@
|
||||
# Automotive team
|
||||
egranata@google.com
|
||||
keunyoung@google.com
|
||||
twasilczyk@google.com
|
||||
@@ -14,15 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "Tuner"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <log/log.h>
|
||||
#define LOG_TAG "BroadcastRadioDefault.tuner"
|
||||
#define LOG_NDEBUG 0
|
||||
|
||||
#include "BroadcastRadio.h"
|
||||
#include "Tuner.h"
|
||||
#include "Utils.h"
|
||||
#include <system/RadioMetadataWrapper.h>
|
||||
|
||||
#include <broadcastradio-utils/Utils.h>
|
||||
#include <log/log.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -30,199 +29,351 @@ namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace implementation {
|
||||
|
||||
void Tuner::onCallback(radio_hal_event_t *halEvent)
|
||||
{
|
||||
BandConfig config;
|
||||
ProgramInfo info;
|
||||
hidl_vec<MetaData> metadata;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
if (mCallback != 0) {
|
||||
switch(halEvent->type) {
|
||||
case RADIO_EVENT_CONFIG:
|
||||
Utils::convertBandConfigFromHal(&config, &halEvent->config);
|
||||
mCallback->configChange(Utils::convertHalResult(halEvent->status), config);
|
||||
break;
|
||||
case RADIO_EVENT_ANTENNA:
|
||||
mCallback->antennaStateChange(halEvent->on);
|
||||
break;
|
||||
case RADIO_EVENT_TUNED:
|
||||
Utils::convertProgramInfoFromHal(&info, &halEvent->info);
|
||||
if (mCallback1_1 != nullptr) {
|
||||
mCallback1_1->tuneComplete_1_1(Utils::convertHalResult(halEvent->status), info);
|
||||
using V1_0::Band;
|
||||
using V1_0::BandConfig;
|
||||
using V1_0::Class;
|
||||
using V1_0::Direction;
|
||||
using utils::HalRevision;
|
||||
|
||||
using std::chrono::milliseconds;
|
||||
using std::lock_guard;
|
||||
using std::move;
|
||||
using std::mutex;
|
||||
using std::sort;
|
||||
using std::vector;
|
||||
|
||||
const struct {
|
||||
milliseconds config = 50ms;
|
||||
milliseconds scan = 200ms;
|
||||
milliseconds step = 100ms;
|
||||
milliseconds tune = 150ms;
|
||||
} gDefaultDelay;
|
||||
|
||||
Tuner::Tuner(V1_0::Class classId, const sp<V1_0::ITunerCallback>& callback)
|
||||
: mClassId(classId),
|
||||
mCallback(callback),
|
||||
mCallback1_1(ITunerCallback::castFrom(callback).withDefault(nullptr)),
|
||||
mVirtualRadio(getRadio(classId)),
|
||||
mIsAnalogForced(false) {}
|
||||
|
||||
void Tuner::forceClose() {
|
||||
lock_guard<mutex> lk(mMut);
|
||||
mIsClosed = true;
|
||||
mThread.cancelAll();
|
||||
}
|
||||
|
||||
Return<Result> Tuner::setConfiguration(const BandConfig& config) {
|
||||
ALOGV("%s", __func__);
|
||||
lock_guard<mutex> lk(mMut);
|
||||
if (mIsClosed) return Result::NOT_INITIALIZED;
|
||||
if (mClassId != Class::AM_FM) {
|
||||
ALOGE("Can't set AM/FM configuration on SAT/DT radio tuner");
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
|
||||
if (config.lowerLimit >= config.upperLimit) return Result::INVALID_ARGUMENTS;
|
||||
|
||||
auto task = [this, config]() {
|
||||
ALOGI("Setting AM/FM config");
|
||||
lock_guard<mutex> lk(mMut);
|
||||
|
||||
mAmfmConfig = move(config);
|
||||
mAmfmConfig.antennaConnected = true;
|
||||
mCurrentProgram = utils::make_selector(mAmfmConfig.type, mAmfmConfig.lowerLimit);
|
||||
|
||||
if (utils::isFm(mAmfmConfig.type)) {
|
||||
mVirtualRadio = std::ref(getFmRadio());
|
||||
} else {
|
||||
mVirtualRadio = std::ref(getAmRadio());
|
||||
}
|
||||
|
||||
mIsAmfmConfigSet = true;
|
||||
mCallback->configChange(Result::OK, mAmfmConfig);
|
||||
};
|
||||
mThread.schedule(task, gDefaultDelay.config);
|
||||
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
Return<void> Tuner::getConfiguration(getConfiguration_cb _hidl_cb) {
|
||||
ALOGV("%s", __func__);
|
||||
lock_guard<mutex> lk(mMut);
|
||||
|
||||
if (!mIsClosed && mIsAmfmConfigSet) {
|
||||
_hidl_cb(Result::OK, mAmfmConfig);
|
||||
} else {
|
||||
_hidl_cb(Result::NOT_INITIALIZED, {});
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// makes ProgramInfo that points to no program
|
||||
static ProgramInfo makeDummyProgramInfo(const ProgramSelector& selector) {
|
||||
ProgramInfo info11 = {};
|
||||
auto& info10 = info11.base;
|
||||
|
||||
utils::getLegacyChannel(selector, &info10.channel, &info10.subChannel);
|
||||
info11.selector = selector;
|
||||
info11.flags |= ProgramInfoFlags::MUTED;
|
||||
|
||||
return info11;
|
||||
}
|
||||
|
||||
HalRevision Tuner::getHalRev() const {
|
||||
if (mCallback1_1 != nullptr) {
|
||||
return HalRevision::V1_1;
|
||||
} else {
|
||||
return HalRevision::V1_0;
|
||||
}
|
||||
}
|
||||
|
||||
void Tuner::tuneInternalLocked(const ProgramSelector& sel) {
|
||||
VirtualProgram virtualProgram;
|
||||
if (mVirtualRadio.get().getProgram(sel, virtualProgram)) {
|
||||
mCurrentProgram = virtualProgram.selector;
|
||||
mCurrentProgramInfo = virtualProgram.getProgramInfo(getHalRev());
|
||||
} else {
|
||||
mCurrentProgram = sel;
|
||||
mCurrentProgramInfo = makeDummyProgramInfo(sel);
|
||||
}
|
||||
mIsTuneCompleted = true;
|
||||
|
||||
if (mCallback1_1 == nullptr) {
|
||||
mCallback->tuneComplete(Result::OK, mCurrentProgramInfo.base);
|
||||
} else {
|
||||
mCallback1_1->tuneComplete_1_1(Result::OK, mCurrentProgramInfo.selector);
|
||||
mCallback1_1->currentProgramInfoChanged(mCurrentProgramInfo);
|
||||
}
|
||||
}
|
||||
|
||||
Return<Result> Tuner::scan(Direction direction, bool skipSubChannel __unused) {
|
||||
ALOGV("%s", __func__);
|
||||
lock_guard<mutex> lk(mMut);
|
||||
if (mIsClosed) return Result::NOT_INITIALIZED;
|
||||
|
||||
auto list = mVirtualRadio.get().getProgramList();
|
||||
|
||||
if (list.empty()) {
|
||||
mIsTuneCompleted = false;
|
||||
auto task = [this, direction]() {
|
||||
ALOGI("Performing failed scan %s", toString(direction).c_str());
|
||||
|
||||
if (mCallback1_1 == nullptr) {
|
||||
mCallback->tuneComplete(Result::TIMEOUT, {});
|
||||
} else {
|
||||
mCallback1_1->tuneComplete_1_1(Result::TIMEOUT, {});
|
||||
}
|
||||
mCallback->tuneComplete(Utils::convertHalResult(halEvent->status), info.base);
|
||||
break;
|
||||
case RADIO_EVENT_METADATA: {
|
||||
uint32_t channel;
|
||||
uint32_t sub_channel;
|
||||
if (radio_metadata_get_channel(halEvent->metadata, &channel, &sub_channel) == 0) {
|
||||
Utils::convertMetaDataFromHal(metadata, halEvent->metadata);
|
||||
mCallback->newMetadata(channel, sub_channel, metadata);
|
||||
}
|
||||
} break;
|
||||
case RADIO_EVENT_TA:
|
||||
mCallback->trafficAnnouncement(halEvent->on);
|
||||
break;
|
||||
case RADIO_EVENT_AF_SWITCH:
|
||||
Utils::convertProgramInfoFromHal(&info, &halEvent->info);
|
||||
if (mCallback1_1 != nullptr) {
|
||||
mCallback1_1->afSwitch_1_1(info);
|
||||
}
|
||||
mCallback->afSwitch(info.base);
|
||||
break;
|
||||
case RADIO_EVENT_EA:
|
||||
mCallback->emergencyAnnouncement(halEvent->on);
|
||||
break;
|
||||
case RADIO_EVENT_HW_FAILURE:
|
||||
default:
|
||||
mCallback->hardwareFailure();
|
||||
break;
|
||||
};
|
||||
mThread.schedule(task, gDefaultDelay.scan);
|
||||
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
// Not optimal (O(sort) instead of O(n)), but not a big deal here;
|
||||
// also, it's likely that list is already sorted (so O(n) anyway).
|
||||
sort(list.begin(), list.end());
|
||||
auto current = mCurrentProgram;
|
||||
auto found = lower_bound(list.begin(), list.end(), VirtualProgram({current}));
|
||||
if (direction == Direction::UP) {
|
||||
if (found < list.end() - 1) {
|
||||
if (utils::tunesTo(current, found->selector)) found++;
|
||||
} else {
|
||||
found = list.begin();
|
||||
}
|
||||
} else {
|
||||
if (found > list.begin() && found != list.end()) {
|
||||
found--;
|
||||
} else {
|
||||
found = list.end() - 1;
|
||||
}
|
||||
}
|
||||
auto tuneTo = found->selector;
|
||||
|
||||
mIsTuneCompleted = false;
|
||||
auto task = [this, tuneTo, direction]() {
|
||||
ALOGI("Performing scan %s", toString(direction).c_str());
|
||||
|
||||
lock_guard<mutex> lk(mMut);
|
||||
tuneInternalLocked(tuneTo);
|
||||
};
|
||||
mThread.schedule(task, gDefaultDelay.scan);
|
||||
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
//static
|
||||
void Tuner::callback(radio_hal_event_t *halEvent, void *cookie)
|
||||
{
|
||||
wp<Tuner> weak(reinterpret_cast<Tuner*>(cookie));
|
||||
sp<Tuner> tuner = weak.promote();
|
||||
if (tuner == 0) return;
|
||||
tuner->onCallback(halEvent);
|
||||
}
|
||||
Return<Result> Tuner::step(Direction direction, bool skipSubChannel) {
|
||||
ALOGV("%s", __func__);
|
||||
lock_guard<mutex> lk(mMut);
|
||||
if (mIsClosed) return Result::NOT_INITIALIZED;
|
||||
|
||||
Tuner::Tuner(const sp<V1_0::ITunerCallback>& callback, const wp<BroadcastRadio>& parentDevice)
|
||||
: mHalTuner(NULL), mCallback(callback), mCallback1_1(ITunerCallback::castFrom(callback)),
|
||||
mParentDevice(parentDevice)
|
||||
{
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
}
|
||||
ALOGW_IF(!skipSubChannel, "can't step to next frequency without ignoring subChannel");
|
||||
|
||||
|
||||
Tuner::~Tuner()
|
||||
{
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
const sp<BroadcastRadio> parentDevice = mParentDevice.promote();
|
||||
if (parentDevice != 0) {
|
||||
parentDevice->closeHalTuner(mHalTuner);
|
||||
}
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::broadcastradio::V1_1::ITuner follow.
|
||||
Return<Result> Tuner::setConfiguration(const BandConfig& config) {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
if (mHalTuner == NULL) {
|
||||
return Utils::convertHalResult(-ENODEV);
|
||||
}
|
||||
radio_hal_band_config_t halConfig;
|
||||
Utils::convertBandConfigToHal(&halConfig, &config);
|
||||
int rc = mHalTuner->set_configuration(mHalTuner, &halConfig);
|
||||
return Utils::convertHalResult(rc);
|
||||
}
|
||||
|
||||
Return<void> Tuner::getConfiguration(getConfiguration_cb _hidl_cb) {
|
||||
int rc;
|
||||
radio_hal_band_config_t halConfig;
|
||||
BandConfig config;
|
||||
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
if (mHalTuner == NULL) {
|
||||
rc = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
rc = mHalTuner->get_configuration(mHalTuner, &halConfig);
|
||||
if (rc == 0) {
|
||||
Utils::convertBandConfigFromHal(&config, &halConfig);
|
||||
if (!utils::isAmFm(utils::getType(mCurrentProgram))) {
|
||||
ALOGE("Can't step in anything else than AM/FM");
|
||||
return Result::NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
exit:
|
||||
_hidl_cb(Utils::convertHalResult(rc), config);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<Result> Tuner::scan(Direction direction, bool skipSubChannel) {
|
||||
if (mHalTuner == NULL) {
|
||||
return Utils::convertHalResult(-ENODEV);
|
||||
if (!mIsAmfmConfigSet) {
|
||||
ALOGW("AM/FM config not set");
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
int rc = mHalTuner->scan(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
|
||||
return Utils::convertHalResult(rc);
|
||||
mIsTuneCompleted = false;
|
||||
|
||||
auto task = [this, direction]() {
|
||||
ALOGI("Performing step %s", toString(direction).c_str());
|
||||
|
||||
lock_guard<mutex> lk(mMut);
|
||||
|
||||
auto current = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY, 0);
|
||||
|
||||
if (direction == Direction::UP) {
|
||||
current += mAmfmConfig.spacings[0];
|
||||
} else {
|
||||
current -= mAmfmConfig.spacings[0];
|
||||
}
|
||||
|
||||
if (current > mAmfmConfig.upperLimit) current = mAmfmConfig.lowerLimit;
|
||||
if (current < mAmfmConfig.lowerLimit) current = mAmfmConfig.upperLimit;
|
||||
|
||||
tuneInternalLocked(utils::make_selector(mAmfmConfig.type, current));
|
||||
};
|
||||
mThread.schedule(task, gDefaultDelay.step);
|
||||
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
Return<Result> Tuner::step(Direction direction, bool skipSubChannel) {
|
||||
if (mHalTuner == NULL) {
|
||||
return Utils::convertHalResult(-ENODEV);
|
||||
Return<Result> Tuner::tune(uint32_t channel, uint32_t subChannel) {
|
||||
ALOGV("%s(%d, %d)", __func__, channel, subChannel);
|
||||
Band band;
|
||||
{
|
||||
lock_guard<mutex> lk(mMut);
|
||||
band = mAmfmConfig.type;
|
||||
}
|
||||
int rc = mHalTuner->step(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
|
||||
return Utils::convertHalResult(rc);
|
||||
return tuneByProgramSelector(utils::make_selector(band, channel, subChannel));
|
||||
}
|
||||
|
||||
Return<Result> Tuner::tune(uint32_t channel, uint32_t subChannel) {
|
||||
if (mHalTuner == NULL) {
|
||||
return Utils::convertHalResult(-ENODEV);
|
||||
Return<Result> Tuner::tuneByProgramSelector(const ProgramSelector& sel) {
|
||||
ALOGV("%s(%s)", __func__, toString(sel).c_str());
|
||||
lock_guard<mutex> lk(mMut);
|
||||
if (mIsClosed) return Result::NOT_INITIALIZED;
|
||||
|
||||
// checking if ProgramSelector is valid
|
||||
auto programType = utils::getType(sel);
|
||||
if (utils::isAmFm(programType)) {
|
||||
if (!mIsAmfmConfigSet) {
|
||||
ALOGW("AM/FM config not set");
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
|
||||
auto freq = utils::getId(sel, IdentifierType::AMFM_FREQUENCY);
|
||||
if (freq < mAmfmConfig.lowerLimit || freq > mAmfmConfig.upperLimit) {
|
||||
return Result::INVALID_ARGUMENTS;
|
||||
}
|
||||
} else if (programType == ProgramType::DAB) {
|
||||
if (!utils::hasId(sel, IdentifierType::DAB_SIDECC)) return Result::INVALID_ARGUMENTS;
|
||||
} else if (programType == ProgramType::DRMO) {
|
||||
if (!utils::hasId(sel, IdentifierType::DRMO_SERVICE_ID)) return Result::INVALID_ARGUMENTS;
|
||||
} else if (programType == ProgramType::SXM) {
|
||||
if (!utils::hasId(sel, IdentifierType::SXM_SERVICE_ID)) return Result::INVALID_ARGUMENTS;
|
||||
} else {
|
||||
return Result::INVALID_ARGUMENTS;
|
||||
}
|
||||
int rc = mHalTuner->tune(mHalTuner, channel, subChannel);
|
||||
return Utils::convertHalResult(rc);
|
||||
|
||||
mIsTuneCompleted = false;
|
||||
auto task = [this, sel]() {
|
||||
lock_guard<mutex> lk(mMut);
|
||||
tuneInternalLocked(sel);
|
||||
};
|
||||
mThread.schedule(task, gDefaultDelay.tune);
|
||||
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
Return<Result> Tuner::cancel() {
|
||||
if (mHalTuner == NULL) {
|
||||
return Utils::convertHalResult(-ENODEV);
|
||||
}
|
||||
int rc = mHalTuner->cancel(mHalTuner);
|
||||
return Utils::convertHalResult(rc);
|
||||
Return<Result> Tuner::cancel() {
|
||||
ALOGV("%s", __func__);
|
||||
lock_guard<mutex> lk(mMut);
|
||||
if (mIsClosed) return Result::NOT_INITIALIZED;
|
||||
|
||||
mThread.cancelAll();
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
Return<void> Tuner::getProgramInformation(getProgramInformation_cb _hidl_cb) {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
Return<Result> Tuner::cancelAnnouncement() {
|
||||
ALOGV("%s", __func__);
|
||||
lock_guard<mutex> lk(mMut);
|
||||
if (mIsClosed) return Result::NOT_INITIALIZED;
|
||||
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
Return<void> Tuner::getProgramInformation(getProgramInformation_cb _hidl_cb) {
|
||||
ALOGV("%s", __func__);
|
||||
return getProgramInformation_1_1([&](Result result, const ProgramInfo& info) {
|
||||
_hidl_cb(result, info.base);
|
||||
});
|
||||
}
|
||||
|
||||
Return<void> Tuner::getProgramInformation_1_1(getProgramInformation_1_1_cb _hidl_cb) {
|
||||
int rc;
|
||||
radio_program_info_t halInfo;
|
||||
RadioMetadataWrapper metadataWrapper(&halInfo.metadata);
|
||||
ProgramInfo info;
|
||||
Return<void> Tuner::getProgramInformation_1_1(getProgramInformation_1_1_cb _hidl_cb) {
|
||||
ALOGV("%s", __func__);
|
||||
lock_guard<mutex> lk(mMut);
|
||||
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
if (mHalTuner == NULL) {
|
||||
rc = -ENODEV;
|
||||
goto exit;
|
||||
if (mIsClosed) {
|
||||
_hidl_cb(Result::NOT_INITIALIZED, {});
|
||||
} else if (mIsTuneCompleted) {
|
||||
_hidl_cb(Result::OK, mCurrentProgramInfo);
|
||||
} else {
|
||||
_hidl_cb(Result::NOT_INITIALIZED, makeDummyProgramInfo(mCurrentProgram));
|
||||
}
|
||||
|
||||
rc = mHalTuner->get_program_information(mHalTuner, &halInfo);
|
||||
if (rc == 0) {
|
||||
Utils::convertProgramInfoFromHal(&info, &halInfo);
|
||||
}
|
||||
|
||||
exit:
|
||||
_hidl_cb(Utils::convertHalResult(rc), info);
|
||||
return Void();
|
||||
return {};
|
||||
}
|
||||
|
||||
Return<ProgramListResult> Tuner::startBackgroundScan() {
|
||||
ALOGV("%s", __func__);
|
||||
lock_guard<mutex> lk(mMut);
|
||||
if (mIsClosed) return ProgramListResult::NOT_INITIALIZED;
|
||||
|
||||
return ProgramListResult::UNAVAILABLE;
|
||||
}
|
||||
|
||||
Return<void> Tuner::getProgramList(const hidl_string& filter __unused, getProgramList_cb _hidl_cb) {
|
||||
hidl_vec<ProgramInfo> pList;
|
||||
// TODO(b/34054813): do the actual implementation.
|
||||
_hidl_cb(ProgramListResult::NOT_STARTED, pList);
|
||||
return Void();
|
||||
Return<void> Tuner::getProgramList(const hidl_vec<VendorKeyValue>& vendorFilter,
|
||||
getProgramList_cb _hidl_cb) {
|
||||
ALOGV("%s(%s)", __func__, toString(vendorFilter).substr(0, 100).c_str());
|
||||
lock_guard<mutex> lk(mMut);
|
||||
if (mIsClosed) {
|
||||
_hidl_cb(ProgramListResult::NOT_INITIALIZED, {});
|
||||
return {};
|
||||
}
|
||||
|
||||
auto list = mVirtualRadio.get().getProgramList();
|
||||
ALOGD("returning a list of %zu programs", list.size());
|
||||
_hidl_cb(ProgramListResult::OK, getProgramInfoVector(list, getHalRev()));
|
||||
return {};
|
||||
}
|
||||
|
||||
Return<Result> Tuner::setAnalogForced(bool isForced) {
|
||||
ALOGV("%s", __func__);
|
||||
lock_guard<mutex> lk(mMut);
|
||||
if (mIsClosed) return Result::NOT_INITIALIZED;
|
||||
|
||||
mIsAnalogForced = isForced;
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
Return<void> Tuner::isAnalogForced(isAnalogForced_cb _hidl_cb) {
|
||||
// TODO(b/34348946): do the actual implementation.
|
||||
_hidl_cb(Result::INVALID_STATE, false);
|
||||
return Void();
|
||||
ALOGV("%s", __func__);
|
||||
lock_guard<mutex> lk(mMut);
|
||||
|
||||
if (mIsClosed) {
|
||||
_hidl_cb(Result::NOT_INITIALIZED, false);
|
||||
} else {
|
||||
_hidl_cb(Result::OK, mIsAnalogForced);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Return<Result> Tuner::setAnalogForced(bool isForced __unused) {
|
||||
// TODO(b/34348946): do the actual implementation.
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace implementation
|
||||
} // namespace V1_1
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_TUNER_H
|
||||
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_TUNER_H
|
||||
|
||||
#include "VirtualRadio.h"
|
||||
|
||||
#include <android/hardware/broadcastradio/1.1/ITuner.h>
|
||||
#include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
|
||||
#include <broadcastradio-utils/WorkerThread.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -25,43 +28,48 @@ namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace implementation {
|
||||
|
||||
using V1_0::Direction;
|
||||
|
||||
struct BroadcastRadio;
|
||||
|
||||
struct Tuner : public ITuner {
|
||||
Tuner(V1_0::Class classId, const sp<V1_0::ITunerCallback>& callback);
|
||||
|
||||
Tuner(const sp<V1_0::ITunerCallback>& callback, const wp<BroadcastRadio>& mParentDevice);
|
||||
void forceClose();
|
||||
|
||||
// Methods from ::android::hardware::broadcastradio::V1_1::ITuner follow.
|
||||
Return<Result> setConfiguration(const BandConfig& config) override;
|
||||
Return<void> getConfiguration(getConfiguration_cb _hidl_cb) override;
|
||||
Return<Result> scan(Direction direction, bool skipSubChannel) override;
|
||||
Return<Result> step(Direction direction, bool skipSubChannel) override;
|
||||
Return<Result> tune(uint32_t channel, uint32_t subChannel) override;
|
||||
Return<Result> cancel() override;
|
||||
Return<void> getProgramInformation(getProgramInformation_cb _hidl_cb) override;
|
||||
Return<void> getProgramInformation_1_1(getProgramInformation_1_1_cb _hidl_cb) override;
|
||||
Return<ProgramListResult> startBackgroundScan() override;
|
||||
Return<void> getProgramList(const hidl_string& filter, getProgramList_cb _hidl_cb) override;
|
||||
Return<void> isAnalogForced(isAnalogForced_cb _hidl_cb) override;
|
||||
Return<Result> setAnalogForced(bool isForced) override;
|
||||
// V1_1::ITuner methods
|
||||
virtual Return<Result> setConfiguration(const V1_0::BandConfig& config) override;
|
||||
virtual Return<void> getConfiguration(getConfiguration_cb _hidl_cb) override;
|
||||
virtual Return<Result> scan(V1_0::Direction direction, bool skipSubChannel) override;
|
||||
virtual Return<Result> step(V1_0::Direction direction, bool skipSubChannel) override;
|
||||
virtual Return<Result> tune(uint32_t channel, uint32_t subChannel) override;
|
||||
virtual Return<Result> tuneByProgramSelector(const ProgramSelector& program) override;
|
||||
virtual Return<Result> cancel() override;
|
||||
virtual Return<Result> cancelAnnouncement() override;
|
||||
virtual Return<void> getProgramInformation(getProgramInformation_cb _hidl_cb) override;
|
||||
virtual Return<void> getProgramInformation_1_1(getProgramInformation_1_1_cb _hidl_cb) override;
|
||||
virtual Return<ProgramListResult> startBackgroundScan() override;
|
||||
virtual Return<void> getProgramList(const hidl_vec<VendorKeyValue>& filter,
|
||||
getProgramList_cb _hidl_cb) override;
|
||||
virtual Return<Result> setAnalogForced(bool isForced) override;
|
||||
virtual Return<void> isAnalogForced(isAnalogForced_cb _hidl_cb) override;
|
||||
|
||||
static void callback(radio_hal_event_t *halEvent, void *cookie);
|
||||
void onCallback(radio_hal_event_t *halEvent);
|
||||
private:
|
||||
std::mutex mMut;
|
||||
WorkerThread mThread;
|
||||
bool mIsClosed = false;
|
||||
|
||||
void setHalTuner(const struct radio_tuner *halTuner) { mHalTuner = halTuner; }
|
||||
const struct radio_tuner *getHalTuner() { return mHalTuner; }
|
||||
|
||||
private:
|
||||
~Tuner();
|
||||
|
||||
const struct radio_tuner *mHalTuner;
|
||||
V1_0::Class mClassId;
|
||||
const sp<V1_0::ITunerCallback> mCallback;
|
||||
const sp<V1_1::ITunerCallback> mCallback1_1;
|
||||
const wp<BroadcastRadio> mParentDevice;
|
||||
};
|
||||
|
||||
std::reference_wrapper<VirtualRadio> mVirtualRadio;
|
||||
bool mIsAmfmConfigSet = false;
|
||||
V1_0::BandConfig mAmfmConfig;
|
||||
bool mIsTuneCompleted = false;
|
||||
ProgramSelector mCurrentProgram = {};
|
||||
ProgramInfo mCurrentProgramInfo = {};
|
||||
std::atomic<bool> mIsAnalogForced;
|
||||
|
||||
utils::HalRevision getHalRev() const;
|
||||
void tuneInternalLocked(const ProgramSelector& sel);
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_1
|
||||
|
||||
@@ -1,299 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#define LOG_TAG "BroadcastRadioHalUtils"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <log/log.h>
|
||||
#include <system/radio_metadata.h>
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace implementation {
|
||||
|
||||
using V1_0::Band;
|
||||
using V1_0::Deemphasis;
|
||||
using V1_0::Direction;
|
||||
using V1_0::MetadataKey;
|
||||
using V1_0::MetadataType;
|
||||
using V1_0::Rds;
|
||||
|
||||
const char *Utils::sClassModuleNames[] = {
|
||||
RADIO_HARDWARE_MODULE_ID_FM, /* corresponds to RADIO_CLASS_AM_FM */
|
||||
RADIO_HARDWARE_MODULE_ID_SAT, /* corresponds to RADIO_CLASS_SAT */
|
||||
RADIO_HARDWARE_MODULE_ID_DT, /* corresponds to RADIO_CLASS_DT */
|
||||
};
|
||||
|
||||
// make sure HIDL enum values are aligned with legacy values
|
||||
static_assert(RADIO_CLASS_AM_FM == static_cast<int>(Class::AM_FM),
|
||||
"AM/FM class mismatch with legacy");
|
||||
static_assert(RADIO_CLASS_SAT == static_cast<int>(Class::SAT),
|
||||
"SAT class mismatch with legacy");
|
||||
static_assert(RADIO_CLASS_DT == static_cast<int>(Class::DT),
|
||||
"DT class mismatch with legacy");
|
||||
|
||||
static_assert(RADIO_BAND_AM == static_cast<int>(Band::AM),
|
||||
"AM band mismatch with legacy");
|
||||
static_assert(RADIO_BAND_FM == static_cast<int>(Band::FM),
|
||||
"FM band mismatch with legacy");
|
||||
static_assert(RADIO_BAND_AM_HD == static_cast<int>(Band::AM_HD),
|
||||
"AM HD band mismatch with legacy");
|
||||
static_assert(RADIO_BAND_FM_HD == static_cast<int>(Band::FM_HD),
|
||||
"FM HD band mismatch with legacy");
|
||||
|
||||
static_assert(RADIO_RDS_NONE == static_cast<int>(Rds::NONE),
|
||||
"RDS NONE mismatch with legacy");
|
||||
static_assert(RADIO_RDS_WORLD == static_cast<int>(Rds::WORLD),
|
||||
"RDS WORLD mismatch with legacy");
|
||||
static_assert(RADIO_RDS_US == static_cast<int>(Rds::US),
|
||||
"RDS US mismatch with legacy");
|
||||
|
||||
static_assert(RADIO_DEEMPHASIS_50 == static_cast<int>(Deemphasis::D50),
|
||||
"De-emphasis 50 mismatch with legacy");
|
||||
static_assert(RADIO_DEEMPHASIS_75 == static_cast<int>(Deemphasis::D75),
|
||||
"De-emphasis 75 mismatch with legacy");
|
||||
|
||||
static_assert(RADIO_DIRECTION_UP == static_cast<int>(Direction::UP),
|
||||
"Direction Up mismatch with legacy");
|
||||
static_assert(RADIO_DIRECTION_DOWN == static_cast<int>(Direction::DOWN),
|
||||
"Direction Up mismatch with legacy");
|
||||
|
||||
static_assert(RADIO_METADATA_TYPE_INVALID == static_cast<int>(MetadataType::INVALID),
|
||||
"Metadata type INVALID mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_TYPE_INT == static_cast<int>(MetadataType::INT),
|
||||
"Metadata type INT mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_TYPE_TEXT == static_cast<int>(MetadataType::TEXT),
|
||||
"Metadata type TEXT mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_TYPE_RAW == static_cast<int>(MetadataType::RAW),
|
||||
"Metadata type RAW mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_TYPE_CLOCK == static_cast<int>(MetadataType::CLOCK),
|
||||
"Metadata type CLOCK mismatch with legacy");
|
||||
|
||||
static_assert(RADIO_METADATA_KEY_INVALID == static_cast<int>(MetadataKey::INVALID),
|
||||
"Metadata key INVALID mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_RDS_PI == static_cast<int>(MetadataKey::RDS_PI),
|
||||
"Metadata key RDS_PI mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_RDS_PS == static_cast<int>(MetadataKey::RDS_PS),
|
||||
"Metadata key RDS_PS mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_RDS_PTY == static_cast<int>(MetadataKey::RDS_PTY),
|
||||
"Metadata key RDS_PTY mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_RBDS_PTY == static_cast<int>(MetadataKey::RBDS_PTY),
|
||||
"Metadata key RBDS_PTY mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_RDS_RT == static_cast<int>(MetadataKey::RDS_RT),
|
||||
"Metadata key RDS_RT mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_TITLE == static_cast<int>(MetadataKey::TITLE),
|
||||
"Metadata key TITLE mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_ARTIST == static_cast<int>(MetadataKey::ARTIST),
|
||||
"Metadata key ARTIST mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_ALBUM == static_cast<int>(MetadataKey::ALBUM),
|
||||
"Metadata key ALBUM mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_GENRE == static_cast<int>(MetadataKey::GENRE),
|
||||
"Metadata key GENRE mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_ICON == static_cast<int>(MetadataKey::ICON),
|
||||
"Metadata key ICON mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_ART == static_cast<int>(MetadataKey::ART),
|
||||
"Metadata key ART mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_CLOCK == static_cast<int>(MetadataKey::CLOCK),
|
||||
"Metadata key CLOCK mismatch with legacy");
|
||||
|
||||
|
||||
//static
|
||||
const char * Utils::getClassString(Class ClassId)
|
||||
{
|
||||
int id = static_cast<int>(ClassId);
|
||||
|
||||
if ((id < 0) ||
|
||||
(id >= NELEM(sClassModuleNames))) {
|
||||
ALOGE("invalid class ID %d", id);
|
||||
return NULL;
|
||||
}
|
||||
return sClassModuleNames[id];
|
||||
}
|
||||
|
||||
//static
|
||||
Result Utils::convertHalResult(int rc)
|
||||
{
|
||||
switch (rc) {
|
||||
case 0:
|
||||
return Result::OK;
|
||||
case -EINVAL:
|
||||
return Result::INVALID_ARGUMENTS;
|
||||
case -ENOSYS:
|
||||
return Result::INVALID_STATE;
|
||||
case -ETIMEDOUT:
|
||||
return Result::TIMEOUT;
|
||||
case -ENODEV:
|
||||
default:
|
||||
return Result::NOT_INITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void Utils::convertBandConfigFromHal(
|
||||
BandConfig *config,
|
||||
const radio_hal_band_config_t *halConfig)
|
||||
{
|
||||
|
||||
config->type = static_cast<Band>(halConfig->type);
|
||||
config->antennaConnected = halConfig->antenna_connected;
|
||||
config->lowerLimit = halConfig->lower_limit;
|
||||
config->upperLimit = halConfig->upper_limit;
|
||||
config->spacings.setToExternal(const_cast<unsigned int *>(&halConfig->spacings[0]),
|
||||
halConfig->num_spacings * sizeof(uint32_t));
|
||||
// FIXME: transfer buffer ownership. should have a method for that in hidl_vec
|
||||
config->spacings.resize(halConfig->num_spacings);
|
||||
|
||||
if (config->type == Band::FM) {
|
||||
config->ext.fm.deemphasis = static_cast<Deemphasis>(halConfig->fm.deemphasis);
|
||||
config->ext.fm.stereo = halConfig->fm.stereo;
|
||||
config->ext.fm.rds = static_cast<Rds>(halConfig->fm.rds);
|
||||
config->ext.fm.ta = halConfig->fm.ta;
|
||||
config->ext.fm.af = halConfig->fm.af;
|
||||
config->ext.fm.ea = halConfig->fm.ea;
|
||||
} else {
|
||||
config->ext.am.stereo = halConfig->am.stereo;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void Utils::convertPropertiesFromHal(Properties *properties,
|
||||
const radio_hal_properties_t *halProperties)
|
||||
{
|
||||
properties->classId = static_cast<Class>(halProperties->class_id);
|
||||
properties->implementor.setToExternal(halProperties->implementor, strlen(halProperties->implementor));
|
||||
properties->product.setToExternal(halProperties->product, strlen(halProperties->product));
|
||||
properties->version.setToExternal(halProperties->version, strlen(halProperties->version));
|
||||
properties->serial.setToExternal(halProperties->serial, strlen(halProperties->serial));
|
||||
properties->numTuners = halProperties->num_tuners;
|
||||
properties->numAudioSources = halProperties->num_audio_sources;
|
||||
properties->supportsCapture = halProperties->supports_capture;
|
||||
|
||||
BandConfig *bands =
|
||||
new BandConfig[halProperties->num_bands];
|
||||
for (size_t i = 0; i < halProperties->num_bands; i++) {
|
||||
convertBandConfigFromHal(&bands[i], &halProperties->bands[i]);
|
||||
}
|
||||
properties->bands.setToExternal(bands, halProperties->num_bands);
|
||||
// FIXME: transfer buffer ownership. should have a method for that in hidl_vec
|
||||
properties->bands.resize(halProperties->num_bands);
|
||||
delete[] bands;
|
||||
}
|
||||
|
||||
//static
|
||||
void Utils::convertBandConfigToHal(radio_hal_band_config_t *halConfig, const BandConfig *config)
|
||||
{
|
||||
halConfig->type = static_cast<radio_band_t>(config->type);
|
||||
halConfig->antenna_connected = config->antennaConnected;
|
||||
halConfig->lower_limit = config->lowerLimit;
|
||||
halConfig->upper_limit = config->upperLimit;
|
||||
halConfig->num_spacings = config->spacings.size();
|
||||
if (halConfig->num_spacings > RADIO_NUM_SPACINGS_MAX) {
|
||||
halConfig->num_spacings = RADIO_NUM_SPACINGS_MAX;
|
||||
}
|
||||
memcpy(halConfig->spacings, config->spacings.data(),
|
||||
sizeof(uint32_t) * halConfig->num_spacings);
|
||||
|
||||
if (config->type == Band::FM) {
|
||||
halConfig->fm.deemphasis = static_cast<radio_deemphasis_t>(config->ext.fm.deemphasis);
|
||||
halConfig->fm.stereo = config->ext.fm.stereo;
|
||||
halConfig->fm.rds = static_cast<radio_rds_t>(config->ext.fm.rds);
|
||||
halConfig->fm.ta = config->ext.fm.ta;
|
||||
halConfig->fm.af = config->ext.fm.af;
|
||||
halConfig->fm.ea = config->ext.fm.ea;
|
||||
} else {
|
||||
halConfig->am.stereo = config->ext.am.stereo;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//static
|
||||
void Utils::convertProgramInfoFromHal(ProgramInfo *info, radio_program_info_t *halInfo)
|
||||
{
|
||||
auto &info_1_1 = *info;
|
||||
auto &info_1_0 = info->base;
|
||||
|
||||
info_1_0.channel = halInfo->channel;
|
||||
info_1_0.subChannel = halInfo->sub_channel;
|
||||
info_1_0.tuned = halInfo->tuned;
|
||||
info_1_0.stereo = halInfo->stereo;
|
||||
info_1_0.digital = halInfo->digital;
|
||||
info_1_0.signalStrength = halInfo->signal_strength;
|
||||
convertMetaDataFromHal(info_1_0.metadata, halInfo->metadata);
|
||||
// TODO(b/34348946): add support for HAL 1.1 fields
|
||||
info_1_1.flags = 0;
|
||||
}
|
||||
|
||||
//static
|
||||
int Utils::convertMetaDataFromHal(hidl_vec<MetaData>& metadata, radio_metadata_t *halMetadata)
|
||||
{
|
||||
if (halMetadata == NULL) {
|
||||
ALOGE("Invalid argument: halMetadata is NULL");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = radio_metadata_get_count(halMetadata);
|
||||
if (count <= 0) {
|
||||
return count;
|
||||
}
|
||||
MetaData *newMetadata = new MetaData[count];
|
||||
int outCount = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
radio_metadata_key_t key;
|
||||
radio_metadata_type_t type;
|
||||
void *value;
|
||||
size_t size;
|
||||
if (radio_metadata_get_at_index(halMetadata, i , &key, &type, &value, &size) != 0 ||
|
||||
size == 0) {
|
||||
continue;
|
||||
}
|
||||
switch (type) {
|
||||
case RADIO_METADATA_TYPE_INT: {
|
||||
newMetadata[outCount].intValue = *(static_cast<int32_t *>(value));
|
||||
} break;
|
||||
case RADIO_METADATA_TYPE_TEXT: {
|
||||
newMetadata[outCount].stringValue = static_cast<char *>(value);
|
||||
} break;
|
||||
case RADIO_METADATA_TYPE_RAW: {
|
||||
newMetadata[outCount].rawValue.setToExternal(static_cast<uint8_t *>(value), size);
|
||||
// FIXME: transfer buffer ownership. should have a method for that in hidl_vec
|
||||
newMetadata[outCount].rawValue.resize(size);
|
||||
} break;
|
||||
case RADIO_METADATA_TYPE_CLOCK: {
|
||||
radio_metadata_clock_t *clock = static_cast<radio_metadata_clock_t *>(value);
|
||||
newMetadata[outCount].clockValue.utcSecondsSinceEpoch =
|
||||
clock->utc_seconds_since_epoch;
|
||||
newMetadata[outCount].clockValue.timezoneOffsetInMinutes =
|
||||
clock->timezone_offset_in_minutes;
|
||||
} break;
|
||||
}
|
||||
newMetadata[outCount].type = static_cast<MetadataType>(type);
|
||||
newMetadata[outCount].key = static_cast<MetadataKey>(key);
|
||||
outCount++;
|
||||
}
|
||||
metadata.setToExternal(newMetadata, outCount);
|
||||
// FIXME: transfer buffer ownership. should have a method for that in hidl_vec
|
||||
metadata.resize(outCount);
|
||||
return outCount;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_1
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
|
||||
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
|
||||
|
||||
#include <android/hardware/broadcastradio/1.1/types.h>
|
||||
#include <hardware/radio.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace implementation {
|
||||
|
||||
using V1_0::Class;
|
||||
using V1_0::BandConfig;
|
||||
using V1_0::MetaData;
|
||||
using V1_0::Properties;
|
||||
|
||||
class Utils {
|
||||
public:
|
||||
static const char * getClassString(Class ClassId);
|
||||
static Result convertHalResult(int rc);
|
||||
static void convertBandConfigFromHal(BandConfig *config,
|
||||
const radio_hal_band_config_t *halConfig);
|
||||
static void convertPropertiesFromHal(Properties *properties,
|
||||
const radio_hal_properties_t *halProperties);
|
||||
static void convertBandConfigToHal(radio_hal_band_config_t *halConfig,
|
||||
const BandConfig *config);
|
||||
static void convertProgramInfoFromHal(ProgramInfo *info,
|
||||
radio_program_info_t *halInfo);
|
||||
static int convertMetaDataFromHal(hidl_vec<MetaData>& metadata,
|
||||
radio_metadata_t *halMetadata);
|
||||
private:
|
||||
static const char * sClassModuleNames[];
|
||||
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_1
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
|
||||
106
broadcastradio/1.1/default/VirtualProgram.cpp
Normal file
106
broadcastradio/1.1/default/VirtualProgram.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "VirtualProgram.h"
|
||||
|
||||
#include <broadcastradio-utils/Utils.h>
|
||||
|
||||
#include "resources.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace implementation {
|
||||
|
||||
using std::vector;
|
||||
|
||||
using V1_0::MetaData;
|
||||
using V1_0::MetadataKey;
|
||||
using V1_0::MetadataType;
|
||||
using utils::HalRevision;
|
||||
|
||||
static MetaData createDemoBitmap(MetadataKey key, HalRevision halRev) {
|
||||
MetaData bmp = {MetadataType::INT, key, resources::demoPngId, {}, {}, {}};
|
||||
if (halRev < HalRevision::V1_1) {
|
||||
bmp.type = MetadataType::RAW;
|
||||
bmp.intValue = 0;
|
||||
bmp.rawValue = hidl_vec<uint8_t>(resources::demoPng, std::end(resources::demoPng));
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
|
||||
ProgramInfo VirtualProgram::getProgramInfo(HalRevision halRev) const {
|
||||
ProgramInfo info11 = {};
|
||||
auto& info10 = info11.base;
|
||||
|
||||
utils::getLegacyChannel(selector, &info10.channel, &info10.subChannel);
|
||||
info11.selector = selector;
|
||||
info10.tuned = true;
|
||||
info10.stereo = true;
|
||||
info10.digital = utils::isDigital(selector);
|
||||
info10.signalStrength = info10.digital ? 100 : 80;
|
||||
|
||||
info10.metadata = hidl_vec<MetaData>({
|
||||
{MetadataType::TEXT, MetadataKey::RDS_PS, {}, {}, programName, {}},
|
||||
{MetadataType::TEXT, MetadataKey::TITLE, {}, {}, songTitle, {}},
|
||||
{MetadataType::TEXT, MetadataKey::ARTIST, {}, {}, songArtist, {}},
|
||||
createDemoBitmap(MetadataKey::ICON, halRev),
|
||||
createDemoBitmap(MetadataKey::ART, halRev),
|
||||
});
|
||||
|
||||
info11.vendorInfo = hidl_vec<VendorKeyValue>({
|
||||
{"com.google.dummy", "dummy"},
|
||||
{"com.google.dummy.VirtualProgram", std::to_string(reinterpret_cast<uintptr_t>(this))},
|
||||
});
|
||||
|
||||
return info11;
|
||||
}
|
||||
|
||||
// Defining order on virtual programs, how they appear on band.
|
||||
// It's mostly for default implementation purposes, may not be complete or correct.
|
||||
bool operator<(const VirtualProgram& lhs, const VirtualProgram& rhs) {
|
||||
auto& l = lhs.selector;
|
||||
auto& r = rhs.selector;
|
||||
|
||||
// Two programs with the same primaryId is considered the same.
|
||||
if (l.programType != r.programType) return l.programType < r.programType;
|
||||
if (l.primaryId.type != r.primaryId.type) return l.primaryId.type < r.primaryId.type;
|
||||
if (l.primaryId.value != r.primaryId.value) return l.primaryId.value < r.primaryId.value;
|
||||
|
||||
// A little exception for HD Radio subchannel - we check secondary ID too.
|
||||
if (utils::hasId(l, IdentifierType::HD_SUBCHANNEL) &&
|
||||
utils::hasId(r, IdentifierType::HD_SUBCHANNEL)) {
|
||||
return utils::getId(l, IdentifierType::HD_SUBCHANNEL) <
|
||||
utils::getId(r, IdentifierType::HD_SUBCHANNEL);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<ProgramInfo> getProgramInfoVector(const vector<VirtualProgram>& vec, HalRevision halRev) {
|
||||
vector<ProgramInfo> out;
|
||||
out.reserve(vec.size());
|
||||
for (auto&& program : vec) {
|
||||
out.push_back(program.getProgramInfo(halRev));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_1
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
55
broadcastradio/1.1/default/VirtualProgram.h
Normal file
55
broadcastradio/1.1/default/VirtualProgram.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALPROGRAM_H
|
||||
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALPROGRAM_H
|
||||
|
||||
#include <android/hardware/broadcastradio/1.1/types.h>
|
||||
#include <broadcastradio-utils/Utils.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace implementation {
|
||||
|
||||
/**
|
||||
* A radio program mock.
|
||||
*
|
||||
* This represents broadcast waves flying over the air,
|
||||
* not an entry for a captured station in the radio tuner memory.
|
||||
*/
|
||||
struct VirtualProgram {
|
||||
ProgramSelector selector;
|
||||
|
||||
std::string programName = "";
|
||||
std::string songArtist = "";
|
||||
std::string songTitle = "";
|
||||
|
||||
ProgramInfo getProgramInfo(utils::HalRevision halRev) const;
|
||||
|
||||
friend bool operator<(const VirtualProgram& lhs, const VirtualProgram& rhs);
|
||||
};
|
||||
|
||||
std::vector<ProgramInfo> getProgramInfoVector(const std::vector<VirtualProgram>& vec,
|
||||
utils::HalRevision halRev);
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_1
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALPROGRAM_H
|
||||
105
broadcastradio/1.1/default/VirtualRadio.cpp
Normal file
105
broadcastradio/1.1/default/VirtualRadio.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#define LOG_TAG "BroadcastRadioDefault.VirtualRadio"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include "VirtualRadio.h"
|
||||
|
||||
#include <broadcastradio-utils/Utils.h>
|
||||
#include <log/log.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace implementation {
|
||||
|
||||
using V1_0::Band;
|
||||
using V1_0::Class;
|
||||
|
||||
using std::lock_guard;
|
||||
using std::move;
|
||||
using std::mutex;
|
||||
using std::vector;
|
||||
|
||||
using utils::make_selector;
|
||||
|
||||
static const vector<VirtualProgram> gInitialFmPrograms{
|
||||
{make_selector(Band::FM, 94900), "Wild 94.9", "Drake ft. Rihanna", "Too Good"},
|
||||
{make_selector(Band::FM, 96500), "KOIT", "Celine Dion", "All By Myself"},
|
||||
{make_selector(Band::FM, 97300), "Alice@97.3", "Drops of Jupiter", "Train"},
|
||||
{make_selector(Band::FM, 99700), "99.7 Now!", "The Chainsmokers", "Closer"},
|
||||
{make_selector(Band::FM, 101300), "101-3 KISS-FM", "Justin Timberlake", "Rock Your Body"},
|
||||
{make_selector(Band::FM, 103700), "iHeart80s @ 103.7", "Michael Jackson", "Billie Jean"},
|
||||
{make_selector(Band::FM, 106100), "106 KMEL", "Drake", "Marvins Room"},
|
||||
};
|
||||
|
||||
static VirtualRadio gEmptyRadio({});
|
||||
static VirtualRadio gFmRadio(gInitialFmPrograms);
|
||||
|
||||
VirtualRadio::VirtualRadio(const vector<VirtualProgram> initialList) : mPrograms(initialList) {}
|
||||
|
||||
vector<VirtualProgram> VirtualRadio::getProgramList() {
|
||||
lock_guard<mutex> lk(mMut);
|
||||
return mPrograms;
|
||||
}
|
||||
|
||||
bool VirtualRadio::getProgram(const ProgramSelector& selector, VirtualProgram& programOut) {
|
||||
lock_guard<mutex> lk(mMut);
|
||||
for (auto&& program : mPrograms) {
|
||||
if (utils::tunesTo(selector, program.selector)) {
|
||||
programOut = program;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
VirtualRadio& getRadio(V1_0::Class classId) {
|
||||
switch (classId) {
|
||||
case Class::AM_FM:
|
||||
return getFmRadio();
|
||||
case Class::SAT:
|
||||
return getSatRadio();
|
||||
case Class::DT:
|
||||
return getDigitalRadio();
|
||||
default:
|
||||
ALOGE("Invalid class ID");
|
||||
return gEmptyRadio;
|
||||
}
|
||||
}
|
||||
|
||||
VirtualRadio& getAmRadio() {
|
||||
return gEmptyRadio;
|
||||
}
|
||||
|
||||
VirtualRadio& getFmRadio() {
|
||||
return gFmRadio;
|
||||
}
|
||||
|
||||
VirtualRadio& getSatRadio() {
|
||||
return gEmptyRadio;
|
||||
}
|
||||
|
||||
VirtualRadio& getDigitalRadio() {
|
||||
return gEmptyRadio;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_1
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
80
broadcastradio/1.1/default/VirtualRadio.h
Normal file
80
broadcastradio/1.1/default/VirtualRadio.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALRADIO_H
|
||||
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALRADIO_H
|
||||
|
||||
#include "VirtualProgram.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace implementation {
|
||||
|
||||
/**
|
||||
* A radio frequency space mock.
|
||||
*
|
||||
* This represents all broadcast waves in the air for a given radio technology,
|
||||
* not a captured station list in the radio tuner memory.
|
||||
*
|
||||
* It's meant to abstract out radio content from default tuner implementation.
|
||||
*/
|
||||
class VirtualRadio {
|
||||
public:
|
||||
VirtualRadio(const std::vector<VirtualProgram> initialList);
|
||||
|
||||
std::vector<VirtualProgram> getProgramList();
|
||||
bool getProgram(const ProgramSelector& selector, VirtualProgram& program);
|
||||
|
||||
private:
|
||||
std::mutex mMut;
|
||||
std::vector<VirtualProgram> mPrograms;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get virtual radio space for a given radio class.
|
||||
*
|
||||
* As a space, each virtual radio always exists. For example, DAB frequencies
|
||||
* exists in US, but contains no programs.
|
||||
*
|
||||
* The lifetime of the virtual radio space is virtually infinite, but for the
|
||||
* needs of default implementation, it's bound with the lifetime of default
|
||||
* implementation process.
|
||||
*
|
||||
* Internally, it's a static object, so trying to access the reference during
|
||||
* default implementation library unloading may result in segmentation fault.
|
||||
* It's unlikely for testing purposes.
|
||||
*
|
||||
* @param classId A class of radio technology.
|
||||
* @return A reference to virtual radio space for a given technology.
|
||||
*/
|
||||
VirtualRadio& getRadio(V1_0::Class classId);
|
||||
|
||||
VirtualRadio& getAmRadio();
|
||||
VirtualRadio& getFmRadio();
|
||||
VirtualRadio& getSatRadio();
|
||||
VirtualRadio& getDigitalRadio();
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_1
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALRADIO_H
|
||||
@@ -0,0 +1,4 @@
|
||||
service broadcastradio-hal /vendor/bin/hw/android.hardware.broadcastradio@1.1-service
|
||||
class hal
|
||||
user audioserver
|
||||
group audio
|
||||
46
broadcastradio/1.1/default/resources.h
Normal file
46
broadcastradio/1.1/default/resources.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_RESOURCES_H
|
||||
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_RESOURCES_H
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace implementation {
|
||||
namespace resources {
|
||||
|
||||
constexpr int32_t demoPngId = 123456;
|
||||
constexpr uint8_t demoPng[] = {
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44,
|
||||
0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25,
|
||||
0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x5d, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xed, 0xd9,
|
||||
0xc1, 0x09, 0x00, 0x30, 0x08, 0x04, 0xc1, 0x33, 0xfd, 0xf7, 0x6c, 0x6a, 0xc8, 0x23, 0x04,
|
||||
0xc9, 0x6c, 0x01, 0xc2, 0x20, 0xbe, 0x4c, 0x86, 0x57, 0x49, 0xba, 0xfb, 0xd6, 0xf4, 0xba,
|
||||
0x3e, 0x7f, 0x4d, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x8f, 0x00, 0xbd, 0xce, 0x7f,
|
||||
0xc0, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xb8, 0x0d, 0x32, 0xd4, 0x0c, 0x77, 0xbd,
|
||||
0xfb, 0xc1, 0xce, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};
|
||||
|
||||
} // namespace resources
|
||||
} // namespace implementation
|
||||
} // namespace V1_1
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_RESOURCES_H
|
||||
36
broadcastradio/1.1/default/service.cpp
Normal file
36
broadcastradio/1.1/default/service.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#define LOG_TAG "BroadcastRadioDefault.service"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <hidl/HidlTransportSupport.h>
|
||||
|
||||
#include "BroadcastRadioFactory.h"
|
||||
|
||||
using android::hardware::configureRpcThreadpool;
|
||||
using android::hardware::joinRpcThreadpool;
|
||||
using android::hardware::broadcastradio::V1_1::implementation::BroadcastRadioFactory;
|
||||
|
||||
int main(int /* argc */, char** /* argv */) {
|
||||
configureRpcThreadpool(4, true);
|
||||
|
||||
BroadcastRadioFactory broadcastRadioFactory;
|
||||
auto status = broadcastRadioFactory.registerAsService();
|
||||
CHECK_EQ(status, android::OK) << "Failed to register Broadcast Radio HAL implementation";
|
||||
|
||||
joinRpcThreadpool();
|
||||
return 1; // joinRpcThreadpool shouldn't exit
|
||||
}
|
||||
29
broadcastradio/1.1/tests/Android.bp
Normal file
29
broadcastradio/1.1/tests/Android.bp
Normal file
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
cc_test {
|
||||
name: "android.hardware.broadcastradio@1.1-utils-tests",
|
||||
vendor: true,
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
],
|
||||
srcs: [
|
||||
"WorkerThread_test.cpp",
|
||||
],
|
||||
static_libs: ["android.hardware.broadcastradio@1.1-utils-lib"],
|
||||
}
|
||||
8
broadcastradio/1.1/tests/OWNERS
Normal file
8
broadcastradio/1.1/tests/OWNERS
Normal file
@@ -0,0 +1,8 @@
|
||||
# Automotive team
|
||||
egranata@google.com
|
||||
keunyoung@google.com
|
||||
twasilczyk@google.com
|
||||
|
||||
# VTS team
|
||||
ryanjcampbell@google.com
|
||||
yim@google.com
|
||||
138
broadcastradio/1.1/tests/WorkerThread_test.cpp
Normal file
138
broadcastradio/1.1/tests/WorkerThread_test.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <broadcastradio-utils/WorkerThread.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
using android::WorkerThread;
|
||||
|
||||
using std::atomic;
|
||||
using std::chrono::time_point;
|
||||
using std::chrono::steady_clock;
|
||||
using std::is_sorted;
|
||||
using std::lock_guard;
|
||||
using std::mutex;
|
||||
using std::this_thread::sleep_for;
|
||||
using std::vector;
|
||||
|
||||
#define ASSERT_EQ_WITH_TOLERANCE(val1, val2, tolerance) \
|
||||
ASSERT_LE((val1) - (tolerance), (val2)); \
|
||||
ASSERT_GE((val1) + (tolerance), (val2));
|
||||
|
||||
TEST(WorkerThreadTest, oneTask) {
|
||||
atomic<bool> executed(false);
|
||||
atomic<time_point<steady_clock>> stop;
|
||||
WorkerThread thread;
|
||||
|
||||
auto start = steady_clock::now();
|
||||
thread.schedule(
|
||||
[&]() {
|
||||
stop = steady_clock::now();
|
||||
executed = true;
|
||||
},
|
||||
100ms);
|
||||
|
||||
sleep_for(150ms);
|
||||
|
||||
ASSERT_TRUE(executed);
|
||||
auto delta = stop.load() - start;
|
||||
ASSERT_EQ_WITH_TOLERANCE(delta, 100ms, 50ms);
|
||||
}
|
||||
|
||||
TEST(WorkerThreadTest, cancelSecond) {
|
||||
atomic<bool> executed1(false);
|
||||
atomic<bool> executed2(false);
|
||||
WorkerThread thread;
|
||||
|
||||
thread.schedule([&]() { executed2 = true; }, 100ms);
|
||||
thread.schedule([&]() { executed1 = true; }, 25ms);
|
||||
|
||||
sleep_for(50ms);
|
||||
thread.cancelAll();
|
||||
sleep_for(100ms);
|
||||
|
||||
ASSERT_TRUE(executed1);
|
||||
ASSERT_FALSE(executed2);
|
||||
}
|
||||
|
||||
TEST(WorkerThreadTest, executeInOrder) {
|
||||
mutex mut;
|
||||
vector<int> order;
|
||||
WorkerThread thread;
|
||||
|
||||
thread.schedule(
|
||||
[&]() {
|
||||
lock_guard<mutex> lk(mut);
|
||||
order.push_back(0);
|
||||
},
|
||||
50ms);
|
||||
|
||||
thread.schedule(
|
||||
[&]() {
|
||||
lock_guard<mutex> lk(mut);
|
||||
order.push_back(4);
|
||||
},
|
||||
400ms);
|
||||
|
||||
thread.schedule(
|
||||
[&]() {
|
||||
lock_guard<mutex> lk(mut);
|
||||
order.push_back(1);
|
||||
},
|
||||
100ms);
|
||||
|
||||
thread.schedule(
|
||||
[&]() {
|
||||
lock_guard<mutex> lk(mut);
|
||||
order.push_back(3);
|
||||
},
|
||||
300ms);
|
||||
|
||||
thread.schedule(
|
||||
[&]() {
|
||||
lock_guard<mutex> lk(mut);
|
||||
order.push_back(2);
|
||||
},
|
||||
200ms);
|
||||
|
||||
sleep_for(500ms);
|
||||
|
||||
ASSERT_EQ(5u, order.size());
|
||||
ASSERT_TRUE(is_sorted(order.begin(), order.end()));
|
||||
}
|
||||
|
||||
TEST(WorkerThreadTest, dontExecuteAfterDestruction) {
|
||||
atomic<bool> executed1(false);
|
||||
atomic<bool> executed2(false);
|
||||
{
|
||||
WorkerThread thread;
|
||||
|
||||
thread.schedule([&]() { executed2 = true; }, 100ms);
|
||||
thread.schedule([&]() { executed1 = true; }, 25ms);
|
||||
|
||||
sleep_for(50ms);
|
||||
}
|
||||
sleep_for(100ms);
|
||||
|
||||
ASSERT_TRUE(executed1);
|
||||
ASSERT_FALSE(executed2);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
@@ -43,6 +43,35 @@ enum ProgramInfoFlags : uint32_t {
|
||||
* increasing volume too much.
|
||||
*/
|
||||
MUTED = 1 << 1,
|
||||
|
||||
/**
|
||||
* Station broadcasts traffic information regularly,
|
||||
* but not necessarily right now.
|
||||
*/
|
||||
TRAFFIC_PROGRAM = 1 << 2,
|
||||
|
||||
/**
|
||||
* Station is broadcasting traffic information at the very moment.
|
||||
*/
|
||||
TRAFFIC_ANNOUNCEMENT = 1 << 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* A key-value pair for vendor-specific information to be passed as-is through
|
||||
* Android framework to the front-end application.
|
||||
*/
|
||||
struct VendorKeyValue {
|
||||
/**
|
||||
* Key must be prefixed with unique vendor Java-style namespace,
|
||||
* eg. 'com.somecompany.parameter1'.
|
||||
*/
|
||||
string key;
|
||||
|
||||
/**
|
||||
* Value must be passed through the framework without any changes.
|
||||
* Format of this string can vary across vendors.
|
||||
*/
|
||||
string value;
|
||||
};
|
||||
|
||||
struct Properties {
|
||||
@@ -55,16 +84,204 @@ struct Properties {
|
||||
bool supportsBackgroundScanning;
|
||||
|
||||
/**
|
||||
* Opaque vendor-specific string, to be passed to front-end without changes.
|
||||
* Format of this string can vary across vendors.
|
||||
* A list of supported ProgramType values.
|
||||
*
|
||||
* It may be used for extra features, that's not supported by a platform,
|
||||
* for example: "preset-slots=6;ultra-hd-capable=false".
|
||||
* If a program type is supported by radio module, it means it can tune
|
||||
* to ProgramSelector of a given type.
|
||||
*
|
||||
* Front-end application MUST verify vendor/product name from the
|
||||
* @1.0::Properties struct before doing any interpretation of this value.
|
||||
* Support for VENDOR program type does not guarantee compatibility, as
|
||||
* other module properties (implementor, product, version) must be checked.
|
||||
*/
|
||||
string vendorExension;
|
||||
vec<uint32_t> supportedProgramTypes;
|
||||
|
||||
/**
|
||||
* A list of supported IdentifierType values.
|
||||
*
|
||||
* If an identifier is supported by radio module, it means it can use it for
|
||||
* tuning to ProgramSelector with either primary or secondary Identifier of
|
||||
* a given type.
|
||||
*
|
||||
* Support for VENDOR identifier type does not guarantee compatibility, as
|
||||
* other module properties (implementor, product, version) must be checked.
|
||||
*/
|
||||
vec<uint32_t> supportedIdentifierTypes;
|
||||
|
||||
/**
|
||||
* Vendor-specific information.
|
||||
*
|
||||
* It may be used for extra features, not supported by the platform,
|
||||
* for example: com.me.preset-slots=6; com.me.ultra-hd-capable=false.
|
||||
*/
|
||||
vec<VendorKeyValue> vendorInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* Type of modulation.
|
||||
*
|
||||
* Used as a value for DRMO_MODULATION IdentifierType.
|
||||
*/
|
||||
enum Modulation : uint32_t {
|
||||
AM = 1,
|
||||
FM,
|
||||
};
|
||||
|
||||
/**
|
||||
* Type of a radio technology.
|
||||
*
|
||||
* VENDOR program types must be opaque to the framework.
|
||||
*
|
||||
* There are multiple VENDOR program types just to make vendor implementation
|
||||
* easier with multiple properitary radio technologies. They are treated the
|
||||
* same by the framework.
|
||||
*
|
||||
* All other values are reserved for future use.
|
||||
* Values not matching any enumerated constant must be ignored.
|
||||
*/
|
||||
enum ProgramType : uint32_t {
|
||||
AM = 1, // analogue AM radio (with or without RDS)
|
||||
FM, // analogue FM radio (with or without RDS)
|
||||
AM_HD, // AM HD Radio
|
||||
FM_HD, // FM HD Radio
|
||||
DAB, // Digital audio broadcasting
|
||||
DRMO, // Digital Radio Mondiale
|
||||
SXM, // SiriusXM Satellite Radio
|
||||
|
||||
// Vendor-specific, not synced across devices.
|
||||
VENDOR_START = 1000,
|
||||
VENDOR_END = 1999,
|
||||
};
|
||||
|
||||
/**
|
||||
* Type of program identifier component.
|
||||
*
|
||||
* It MUST match the radio technology for primary ID but does not have to match
|
||||
* it for secondary IDs. For example, a satellite program may set AM/FM fallback
|
||||
* frequency, if a station broadcasts both via satellite and AM/FM.
|
||||
*
|
||||
* VENDOR identifier types must be opaque to the framework.
|
||||
*
|
||||
* The value format for each (but VENDOR_PRIMARY) identifier is strictly defined
|
||||
* to maintain interoperability between devices made by different vendors.
|
||||
*
|
||||
* All other values are reserved for future use.
|
||||
* Values not matching any enumerated constant must be ignored.
|
||||
*/
|
||||
enum IdentifierType : uint32_t {
|
||||
AMFM_FREQUENCY = 1, // kHz
|
||||
RDS_PI, // 16bit
|
||||
|
||||
/**
|
||||
* 64bit compound primary identifier for HD Radio.
|
||||
*
|
||||
* Consists of (from the LSB):
|
||||
* - 32bit: Station ID number;
|
||||
* - 4bit: HD_SUBCHANNEL;
|
||||
* - 18bit: AMFM_FREQUENCY.
|
||||
* The remaining bits should be set to zeros when writing on the chip side
|
||||
* and ignored when read.
|
||||
*/
|
||||
HD_STATION_ID_EXT,
|
||||
|
||||
/**
|
||||
* HD Radio subchannel - a value of range 0-7.
|
||||
*
|
||||
* The subchannel index is 0-based (where 0 is MPS and 1..7 are SPS),
|
||||
* as opposed to HD Radio standard (where it's 1-based).
|
||||
*/
|
||||
HD_SUBCHANNEL,
|
||||
|
||||
/**
|
||||
* 24bit compound primary identifier for DAB.
|
||||
*
|
||||
* Consists of (from the LSB):
|
||||
* - 16bit: SId;
|
||||
* - 8bit: ECC code.
|
||||
* The remaining bits should be set to zeros when writing on the chip side
|
||||
* and ignored when read.
|
||||
*/
|
||||
DAB_SIDECC,
|
||||
|
||||
DAB_ENSEMBLE, // 16bit
|
||||
DAB_SCID, // 12bit
|
||||
DAB_FREQUENCY, // kHz
|
||||
DRMO_SERVICE_ID, // 24bit
|
||||
DRMO_FREQUENCY, // kHz
|
||||
DRMO_MODULATION, // Modulation enum
|
||||
SXM_SERVICE_ID, // 32bit
|
||||
SXM_CHANNEL, // 0-999 range
|
||||
|
||||
/**
|
||||
* Primary identifier for vendor-specific radio technology.
|
||||
* The value format is determined by a vendor.
|
||||
*
|
||||
* It must not be used in any other programType than corresponding VENDOR
|
||||
* type between VENDOR_START and VENDOR_END (eg. identifier type 1015 must
|
||||
* not be used in any program type other than 1015).
|
||||
*/
|
||||
VENDOR_PRIMARY_START = ProgramType:VENDOR_START,
|
||||
VENDOR_PRIMARY_END = ProgramType:VENDOR_END,
|
||||
};
|
||||
|
||||
/**
|
||||
* A single program identifier component, eg. frequency or channel ID.
|
||||
*
|
||||
* The uint32_t type field maps to IdentifierType enum. It's not straight,
|
||||
* because the enum may be extended in future versions of the HAL. Values out of
|
||||
* the enum range must not be used when writing and ignored when reading.
|
||||
*
|
||||
* The uint64_t value field holds the value in format described in comments for
|
||||
* IdentifierType enum.
|
||||
*/
|
||||
struct ProgramIdentifier {
|
||||
uint32_t type; // IdentifierType
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
/**
|
||||
* A set of identifiers necessary to tune to a given station.
|
||||
*
|
||||
* This can hold various identifiers, like
|
||||
* - AM/FM frequency
|
||||
* - HD Radio subchannel
|
||||
* - DAB channel info
|
||||
*
|
||||
* The uint32_t programType field maps to ProgramType enum. It's not straight,
|
||||
* because the enum may be extended in future versions of the HAL. Values out of
|
||||
* the enum range must not be used when writing and ignored when reading.
|
||||
*
|
||||
* The primary ID uniquely identifies a station and can be used for equality
|
||||
* check. The secondary IDs are supplementary and can speed up tuning process,
|
||||
* but the primary ID is sufficient (ie. after a full band scan).
|
||||
*
|
||||
* Two selectors with different secondary IDs, but the same primary ID are
|
||||
* considered equal. In particular, secondary IDs vector may get updated for
|
||||
* an entry on the program list (ie. when a better frequency for a given
|
||||
* station is found).
|
||||
*
|
||||
* The primaryId of a given programType MUST be of a specific type:
|
||||
* - AM, FM: RDS_PI if the station broadcasts RDS, AMFM_FREQUENCY otherwise;
|
||||
* - AM_HD, FM_HD: HD_STATION_ID_EXT;
|
||||
* - DAB: DAB_SIDECC;
|
||||
* - DRMO: DRMO_SERVICE_ID;
|
||||
* - SXM: SXM_SERVICE_ID;
|
||||
* - VENDOR: VENDOR_PRIMARY.
|
||||
*/
|
||||
struct ProgramSelector {
|
||||
uint32_t programType; // ProgramType
|
||||
ProgramIdentifier primaryId; // uniquely identifies a station
|
||||
vec<ProgramIdentifier> secondaryIds;
|
||||
|
||||
/**
|
||||
* Opaque vendor-specific identifiers, to be passed to front-end
|
||||
* without changes.
|
||||
*
|
||||
* The order is meaningful, ie. the first element may be defined as
|
||||
* frequency, second as the subchannel etc.
|
||||
*
|
||||
* The vector is not serialized (either locally or to the cloud),
|
||||
* unless it's a VENDOR program type.
|
||||
*/
|
||||
vec<uint64_t> vendorIds;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -73,17 +290,16 @@ struct Properties {
|
||||
*/
|
||||
struct ProgramInfo {
|
||||
@1.0::ProgramInfo base;
|
||||
|
||||
ProgramSelector selector;
|
||||
|
||||
bitfield<ProgramInfoFlags> flags;
|
||||
|
||||
/**
|
||||
* Opaque vendor-specific string, to be passed to front-end without changes.
|
||||
* Format of this string can vary across vendors.
|
||||
* Vendor-specific information.
|
||||
*
|
||||
* It may be used for extra features, that's not supported by a platform,
|
||||
* for example: "paid-service=true;bitrate=320kbps".
|
||||
*
|
||||
* Front-end application MUST verify vendor/product name from the
|
||||
* @1.0::Properties struct before doing any interpretation of this value.
|
||||
* It may be used for extra features, not supported by the platform,
|
||||
* for example: paid-service=true; bitrate=320kbps.
|
||||
*/
|
||||
string vendorExension;
|
||||
vec<VendorKeyValue> vendorInfo;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2016 The Android Open Source Project
|
||||
//
|
||||
// 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.
|
||||
@@ -11,23 +12,23 @@
|
||||
// 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.
|
||||
//
|
||||
|
||||
cc_binary {
|
||||
proprietary: true,
|
||||
defaults: ["hidl_defaults"],
|
||||
cc_library_static {
|
||||
name: "android.hardware.broadcastradio@1.1-utils-lib",
|
||||
vendor_available: true,
|
||||
relative_install_path: "hw",
|
||||
name: "android.hardware.power@1.1-service",
|
||||
init_rc: ["android.hardware.power@1.1-service.rc"],
|
||||
srcs: ["service.cpp" , "Power.cpp"],
|
||||
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
],
|
||||
srcs: [
|
||||
"Utils.cpp",
|
||||
"WorkerThread.cpp",
|
||||
],
|
||||
export_include_dirs: ["include"],
|
||||
shared_libs: [
|
||||
"liblog",
|
||||
"libdl",
|
||||
"libutils",
|
||||
"libhardware",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"android.hardware.power@1.0",
|
||||
"android.hardware.power@1.1",
|
||||
"android.hardware.broadcastradio@1.1",
|
||||
],
|
||||
}
|
||||
4
broadcastradio/1.1/utils/OWNERS
Normal file
4
broadcastradio/1.1/utils/OWNERS
Normal file
@@ -0,0 +1,4 @@
|
||||
# Automotive team
|
||||
egranata@google.com
|
||||
keunyoung@google.com
|
||||
twasilczyk@google.com
|
||||
234
broadcastradio/1.1/utils/Utils.cpp
Normal file
234
broadcastradio/1.1/utils/Utils.cpp
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#define LOG_TAG "BroadcastRadioDefault.utils"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <broadcastradio-utils/Utils.h>
|
||||
|
||||
#include <log/log.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace utils {
|
||||
|
||||
using V1_0::Band;
|
||||
|
||||
static bool isCompatibleProgramType(const uint32_t ia, const uint32_t ib) {
|
||||
auto a = static_cast<ProgramType>(ia);
|
||||
auto b = static_cast<ProgramType>(ib);
|
||||
|
||||
if (a == b) return true;
|
||||
if (a == ProgramType::AM && b == ProgramType::AM_HD) return true;
|
||||
if (a == ProgramType::AM_HD && b == ProgramType::AM) return true;
|
||||
if (a == ProgramType::FM && b == ProgramType::FM_HD) return true;
|
||||
if (a == ProgramType::FM_HD && b == ProgramType::FM) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool bothHaveId(const ProgramSelector& a, const ProgramSelector& b,
|
||||
const IdentifierType type) {
|
||||
return hasId(a, type) && hasId(b, type);
|
||||
}
|
||||
|
||||
static bool anyHaveId(const ProgramSelector& a, const ProgramSelector& b,
|
||||
const IdentifierType type) {
|
||||
return hasId(a, type) || hasId(b, type);
|
||||
}
|
||||
|
||||
static bool haveEqualIds(const ProgramSelector& a, const ProgramSelector& b,
|
||||
const IdentifierType type) {
|
||||
if (!bothHaveId(a, b, type)) return false;
|
||||
/* We should check all Ids of a given type (ie. other AF),
|
||||
* but it doesn't matter for default implementation.
|
||||
*/
|
||||
auto aId = getId(a, type);
|
||||
auto bId = getId(b, type);
|
||||
return aId == bId;
|
||||
}
|
||||
|
||||
bool tunesTo(const ProgramSelector& a, const ProgramSelector& b) {
|
||||
if (!isCompatibleProgramType(a.programType, b.programType)) return false;
|
||||
|
||||
auto type = getType(a);
|
||||
|
||||
switch (type) {
|
||||
case ProgramType::AM:
|
||||
case ProgramType::AM_HD:
|
||||
case ProgramType::FM:
|
||||
case ProgramType::FM_HD:
|
||||
if (haveEqualIds(a, b, IdentifierType::HD_STATION_ID_EXT)) return true;
|
||||
|
||||
// if HD Radio subchannel is specified, it must match
|
||||
if (anyHaveId(a, b, IdentifierType::HD_SUBCHANNEL)) {
|
||||
// missing subchannel (analog) is an equivalent of first subchannel (MPS)
|
||||
auto aCh = getId(a, IdentifierType::HD_SUBCHANNEL, 0);
|
||||
auto bCh = getId(b, IdentifierType::HD_SUBCHANNEL, 0);
|
||||
if (aCh != bCh) return false;
|
||||
}
|
||||
|
||||
if (haveEqualIds(a, b, IdentifierType::RDS_PI)) return true;
|
||||
|
||||
return haveEqualIds(a, b, IdentifierType::AMFM_FREQUENCY);
|
||||
case ProgramType::DAB:
|
||||
return haveEqualIds(a, b, IdentifierType::DAB_SIDECC);
|
||||
case ProgramType::DRMO:
|
||||
return haveEqualIds(a, b, IdentifierType::DRMO_SERVICE_ID);
|
||||
case ProgramType::SXM:
|
||||
if (anyHaveId(a, b, IdentifierType::SXM_SERVICE_ID)) {
|
||||
return haveEqualIds(a, b, IdentifierType::SXM_SERVICE_ID);
|
||||
}
|
||||
return haveEqualIds(a, b, IdentifierType::SXM_CHANNEL);
|
||||
default: // includes all vendor types
|
||||
ALOGW("Unsupported program type: %s", toString(type).c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ProgramType getType(const ProgramSelector& sel) {
|
||||
return static_cast<ProgramType>(sel.programType);
|
||||
}
|
||||
|
||||
bool isAmFm(const ProgramType type) {
|
||||
switch (type) {
|
||||
case ProgramType::AM:
|
||||
case ProgramType::FM:
|
||||
case ProgramType::AM_HD:
|
||||
case ProgramType::FM_HD:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool isAm(const Band band) {
|
||||
return band == Band::AM || band == Band::AM_HD;
|
||||
}
|
||||
|
||||
bool isFm(const Band band) {
|
||||
return band == Band::FM || band == Band::FM_HD;
|
||||
}
|
||||
|
||||
bool hasId(const ProgramSelector& sel, const IdentifierType type) {
|
||||
auto itype = static_cast<uint32_t>(type);
|
||||
if (sel.primaryId.type == itype) return true;
|
||||
// not optimal, but we don't care in default impl
|
||||
for (auto&& id : sel.secondaryIds) {
|
||||
if (id.type == itype) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t getId(const ProgramSelector& sel, const IdentifierType type) {
|
||||
auto itype = static_cast<uint32_t>(type);
|
||||
if (sel.primaryId.type == itype) return sel.primaryId.value;
|
||||
// not optimal, but we don't care in default impl
|
||||
for (auto&& id : sel.secondaryIds) {
|
||||
if (id.type == itype) return id.value;
|
||||
}
|
||||
ALOGW("Identifier %s not found", toString(type).c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t getId(const ProgramSelector& sel, const IdentifierType type, uint64_t defval) {
|
||||
if (!hasId(sel, type)) return defval;
|
||||
return getId(sel, type);
|
||||
}
|
||||
|
||||
ProgramSelector make_selector(Band band, uint32_t channel, uint32_t subChannel) {
|
||||
ProgramSelector sel = {};
|
||||
|
||||
ALOGW_IF((subChannel > 0) && (band == Band::AM || band == Band::FM),
|
||||
"got subChannel for non-HD AM/FM");
|
||||
|
||||
// we can't use ProgramType::AM_HD or FM_HD, because we don't know HD station ID
|
||||
ProgramType type;
|
||||
if (isAm(band)) {
|
||||
type = ProgramType::AM;
|
||||
} else if (isFm(band)) {
|
||||
type = ProgramType::FM;
|
||||
} else {
|
||||
LOG_ALWAYS_FATAL("Unsupported band: %s", toString(band).c_str());
|
||||
}
|
||||
|
||||
sel.programType = static_cast<uint32_t>(type);
|
||||
sel.primaryId.type = static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY);
|
||||
sel.primaryId.value = channel;
|
||||
if (subChannel > 0) {
|
||||
/* stating sub channel for AM/FM channel does not give any guarantees,
|
||||
* but we can't do much more without HD station ID
|
||||
*
|
||||
* The legacy APIs had 1-based subChannels, while ProgramSelector is 0-based.
|
||||
*/
|
||||
sel.secondaryIds = hidl_vec<ProgramIdentifier>{
|
||||
{static_cast<uint32_t>(IdentifierType::HD_SUBCHANNEL), subChannel - 1},
|
||||
};
|
||||
}
|
||||
|
||||
return sel;
|
||||
}
|
||||
|
||||
bool getLegacyChannel(const ProgramSelector& sel, uint32_t* channelOut, uint32_t* subChannelOut) {
|
||||
if (channelOut) *channelOut = 0;
|
||||
if (subChannelOut) *subChannelOut = 0;
|
||||
if (isAmFm(getType(sel))) {
|
||||
if (channelOut) *channelOut = getId(sel, IdentifierType::AMFM_FREQUENCY);
|
||||
if (subChannelOut && hasId(sel, IdentifierType::HD_SUBCHANNEL)) {
|
||||
// The legacy APIs had 1-based subChannels, while ProgramSelector is 0-based.
|
||||
*subChannelOut = getId(sel, IdentifierType::HD_SUBCHANNEL) + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isDigital(const ProgramSelector& sel) {
|
||||
switch (getType(sel)) {
|
||||
case ProgramType::AM:
|
||||
case ProgramType::FM:
|
||||
return false;
|
||||
default:
|
||||
// VENDOR might not be digital, but it doesn't matter for default impl.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
} // namespace V1_1
|
||||
|
||||
namespace V1_0 {
|
||||
|
||||
bool operator==(const BandConfig& l, const BandConfig& r) {
|
||||
if (l.type != r.type) return false;
|
||||
if (l.antennaConnected != r.antennaConnected) return false;
|
||||
if (l.lowerLimit != r.lowerLimit) return false;
|
||||
if (l.upperLimit != r.upperLimit) return false;
|
||||
if (l.spacings != r.spacings) return false;
|
||||
if (V1_1::utils::isAm(l.type)) {
|
||||
return l.ext.am == r.ext.am;
|
||||
} else if (V1_1::utils::isFm(l.type)) {
|
||||
return l.ext.fm == r.ext.fm;
|
||||
} else {
|
||||
ALOGW("Unsupported band config type: %s", toString(l.type).c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace V1_0
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
89
broadcastradio/1.1/utils/WorkerThread.cpp
Normal file
89
broadcastradio/1.1/utils/WorkerThread.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "WorkerThread"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <broadcastradio-utils/WorkerThread.h>
|
||||
|
||||
#include <log/log.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
using std::chrono::milliseconds;
|
||||
using std::chrono::steady_clock;
|
||||
using std::function;
|
||||
using std::lock_guard;
|
||||
using std::mutex;
|
||||
using std::priority_queue;
|
||||
using std::this_thread::sleep_for;
|
||||
using std::unique_lock;
|
||||
|
||||
bool operator<(const WorkerThread::Task& lhs, const WorkerThread::Task& rhs) {
|
||||
return lhs.when > rhs.when;
|
||||
}
|
||||
|
||||
WorkerThread::WorkerThread() : mIsTerminating(false), mThread(&WorkerThread::threadLoop, this) {}
|
||||
|
||||
WorkerThread::~WorkerThread() {
|
||||
ALOGV("%s", __func__);
|
||||
{
|
||||
lock_guard<mutex> lk(mMut);
|
||||
mIsTerminating = true;
|
||||
mCond.notify_one();
|
||||
}
|
||||
mThread.join();
|
||||
}
|
||||
|
||||
void WorkerThread::schedule(function<void()> task, milliseconds delay) {
|
||||
ALOGV("%s", __func__);
|
||||
|
||||
auto when = steady_clock::now() + delay;
|
||||
|
||||
lock_guard<mutex> lk(mMut);
|
||||
mTasks.push(Task({when, task}));
|
||||
mCond.notify_one();
|
||||
}
|
||||
|
||||
void WorkerThread::cancelAll() {
|
||||
ALOGV("%s", __func__);
|
||||
|
||||
lock_guard<mutex> lk(mMut);
|
||||
priority_queue<Task>().swap(mTasks); // empty queue
|
||||
}
|
||||
|
||||
void WorkerThread::threadLoop() {
|
||||
ALOGV("%s", __func__);
|
||||
while (!mIsTerminating) {
|
||||
unique_lock<mutex> lk(mMut);
|
||||
if (mTasks.empty()) {
|
||||
mCond.wait(lk);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto task = mTasks.top();
|
||||
if (task.when > steady_clock::now()) {
|
||||
mCond.wait_until(lk, task.when);
|
||||
continue;
|
||||
}
|
||||
|
||||
mTasks.pop();
|
||||
lk.unlock(); // what() might need to schedule another task
|
||||
task.what();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
|
||||
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
|
||||
|
||||
#include <android/hardware/broadcastradio/1.1/types.h>
|
||||
#include <chrono>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace utils {
|
||||
|
||||
// TODO(b/64115813): move it out from frameworks/base/services/core/jni/BroadcastRadio/types.h
|
||||
enum class HalRevision : uint32_t {
|
||||
V1_0 = 1,
|
||||
V1_1,
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks, if {@code pointer} tunes to {@channel}.
|
||||
*
|
||||
* For example, having a channel {AMFM_FREQUENCY = 103.3}:
|
||||
* - selector {AMFM_FREQUENCY = 103.3, HD_SUBCHANNEL = 0} can tune to this channel;
|
||||
* - selector {AMFM_FREQUENCY = 103.3, HD_SUBCHANNEL = 1} can't.
|
||||
*
|
||||
* @param pointer selector we're trying to match against channel.
|
||||
* @param channel existing channel.
|
||||
*/
|
||||
bool tunesTo(const ProgramSelector& pointer, const ProgramSelector& channel);
|
||||
|
||||
ProgramType getType(const ProgramSelector& sel);
|
||||
bool isAmFm(const ProgramType type);
|
||||
|
||||
bool isAm(const V1_0::Band band);
|
||||
bool isFm(const V1_0::Band band);
|
||||
|
||||
bool hasId(const ProgramSelector& sel, const IdentifierType type);
|
||||
|
||||
/**
|
||||
* Returns ID (either primary or secondary) for a given program selector.
|
||||
*
|
||||
* If the selector does not contain given type, returns 0 and emits a warning.
|
||||
*/
|
||||
uint64_t getId(const ProgramSelector& sel, const IdentifierType type);
|
||||
|
||||
/**
|
||||
* Returns ID (either primary or secondary) for a given program selector.
|
||||
*
|
||||
* If the selector does not contain given type, returns default value.
|
||||
*/
|
||||
uint64_t getId(const ProgramSelector& sel, const IdentifierType type, uint64_t defval);
|
||||
|
||||
ProgramSelector make_selector(V1_0::Band band, uint32_t channel, uint32_t subChannel = 0);
|
||||
|
||||
bool getLegacyChannel(const ProgramSelector& sel, uint32_t* channelOut, uint32_t* subChannelOut);
|
||||
|
||||
bool isDigital(const ProgramSelector& sel);
|
||||
|
||||
} // namespace utils
|
||||
} // namespace V1_1
|
||||
|
||||
namespace V1_0 {
|
||||
|
||||
bool operator==(const BandConfig& l, const BandConfig& r);
|
||||
|
||||
} // namespace V1_0
|
||||
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_WORKERTHREAD_H
|
||||
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_WORKERTHREAD_H
|
||||
|
||||
#include <chrono>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
|
||||
namespace android {
|
||||
|
||||
class WorkerThread {
|
||||
public:
|
||||
WorkerThread();
|
||||
virtual ~WorkerThread();
|
||||
|
||||
void schedule(std::function<void()> task, std::chrono::milliseconds delay);
|
||||
void cancelAll();
|
||||
|
||||
private:
|
||||
struct Task {
|
||||
std::chrono::time_point<std::chrono::steady_clock> when;
|
||||
std::function<void()> what;
|
||||
};
|
||||
friend bool operator<(const Task& lhs, const Task& rhs);
|
||||
|
||||
std::atomic<bool> mIsTerminating;
|
||||
std::mutex mMut;
|
||||
std::condition_variable mCond;
|
||||
std::thread mThread;
|
||||
std::priority_queue<Task> mTasks;
|
||||
|
||||
void threadLoop();
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_WORKERTHREAD_H
|
||||
8
broadcastradio/1.1/vts/OWNERS
Normal file
8
broadcastradio/1.1/vts/OWNERS
Normal file
@@ -0,0 +1,8 @@
|
||||
# Automotive team
|
||||
egranata@google.com
|
||||
keunyoung@google.com
|
||||
twasilczyk@google.com
|
||||
|
||||
# VTS team
|
||||
ryanjcampbell@google.com
|
||||
yim@google.com
|
||||
@@ -16,22 +16,13 @@
|
||||
|
||||
cc_test {
|
||||
name: "VtsHalBroadcastradioV1_1TargetTest",
|
||||
defaults: ["hidl_defaults"],
|
||||
defaults: ["VtsHalTargetTestDefaults"],
|
||||
srcs: ["VtsHalBroadcastradioV1_1TargetTest.cpp"],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"liblog",
|
||||
"libcutils",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libnativehelper",
|
||||
"libutils",
|
||||
static_libs: [
|
||||
"android.hardware.broadcastradio@1.0",
|
||||
"android.hardware.broadcastradio@1.1",
|
||||
],
|
||||
static_libs: ["VtsHalHidlTargetTestBase"],
|
||||
cflags: [
|
||||
"-O0",
|
||||
"-g",
|
||||
"android.hardware.broadcastradio@1.1-utils-lib",
|
||||
"android.hardware.broadcastradio@1.1-vts-utils-lib",
|
||||
"libgmock",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -14,463 +14,527 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "BroadcastRadioHidlHalTest"
|
||||
#include <VtsHalHidlTargetTestBase.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <cutils/native_handle.h>
|
||||
#include <cutils/properties.h>
|
||||
#include <hidl/HidlTransportSupport.h>
|
||||
#include <utils/threads.h>
|
||||
#define LOG_TAG "broadcastradio.vts"
|
||||
|
||||
#include <VtsHalHidlTargetTestBase.h>
|
||||
#include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
|
||||
#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
|
||||
#include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h>
|
||||
#include <android/hardware/broadcastradio/1.1/ITuner.h>
|
||||
#include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
|
||||
#include <android/hardware/broadcastradio/1.1/types.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <broadcastradio-utils/Utils.h>
|
||||
#include <broadcastradio-vts-utils/call-barrier.h>
|
||||
#include <broadcastradio-vts-utils/mock-timeout.h>
|
||||
#include <cutils/native_handle.h>
|
||||
#include <cutils/properties.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <hidl/HidlTransportSupport.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace V1_0 = ::android::hardware::broadcastradio::V1_0;
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_1 {
|
||||
namespace vts {
|
||||
|
||||
using ::android::sp;
|
||||
using ::android::Mutex;
|
||||
using ::android::Condition;
|
||||
using ::android::hardware::Return;
|
||||
using ::android::hardware::Void;
|
||||
using ::android::hardware::broadcastradio::V1_0::BandConfig;
|
||||
using ::android::hardware::broadcastradio::V1_0::Class;
|
||||
using ::android::hardware::broadcastradio::V1_0::Direction;
|
||||
using ::android::hardware::broadcastradio::V1_0::IBroadcastRadio;
|
||||
using ::android::hardware::broadcastradio::V1_0::MetaData;
|
||||
using ::android::hardware::broadcastradio::V1_0::Properties;
|
||||
using ::android::hardware::broadcastradio::V1_1::IBroadcastRadioFactory;
|
||||
using ::android::hardware::broadcastradio::V1_1::ITuner;
|
||||
using ::android::hardware::broadcastradio::V1_1::ITunerCallback;
|
||||
using ::android::hardware::broadcastradio::V1_1::ProgramInfo;
|
||||
using ::android::hardware::broadcastradio::V1_1::Result;
|
||||
using ::android::hardware::broadcastradio::V1_1::ProgramListResult;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
using testing::_;
|
||||
using testing::AnyNumber;
|
||||
using testing::ByMove;
|
||||
using testing::DoAll;
|
||||
using testing::Invoke;
|
||||
using testing::SaveArg;
|
||||
|
||||
// The main test class for Broadcast Radio HIDL HAL.
|
||||
using broadcastradio::vts::CallBarrier;
|
||||
using V1_0::BandConfig;
|
||||
using V1_0::Class;
|
||||
using V1_0::MetaData;
|
||||
using V1_0::MetadataKey;
|
||||
using V1_0::MetadataType;
|
||||
|
||||
class BroadcastRadioHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
||||
protected:
|
||||
virtual void SetUp() override {
|
||||
auto factory = ::testing::VtsHalHidlTargetTestBase::getService<IBroadcastRadioFactory>();
|
||||
if (factory != 0) {
|
||||
factory->connectModule(Class::AM_FM,
|
||||
[&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
|
||||
if (retval == Result::OK) {
|
||||
mRadio = IBroadcastRadio::castFrom(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
mTunerCallback = new MyCallback(this);
|
||||
ASSERT_NE(nullptr, mRadio.get());
|
||||
ASSERT_NE(nullptr, mTunerCallback.get());
|
||||
}
|
||||
using std::chrono::steady_clock;
|
||||
using std::this_thread::sleep_for;
|
||||
|
||||
virtual void TearDown() override {
|
||||
mTuner.clear();
|
||||
mRadio.clear();
|
||||
}
|
||||
static constexpr auto kConfigTimeout = 10s;
|
||||
static constexpr auto kConnectModuleTimeout = 1s;
|
||||
static constexpr auto kTuneTimeout = 30s;
|
||||
static constexpr auto kEventPropagationTimeout = 1s;
|
||||
static constexpr auto kFullScanTimeout = 1min;
|
||||
|
||||
class MyCallback : public ITunerCallback {
|
||||
public:
|
||||
static constexpr ProgramType kStandardProgramTypes[] = {
|
||||
ProgramType::AM, ProgramType::FM, ProgramType::AM_HD, ProgramType::FM_HD,
|
||||
ProgramType::DAB, ProgramType::DRMO, ProgramType::SXM};
|
||||
|
||||
// ITunerCallback methods (see doc in ITunerCallback.hal)
|
||||
virtual Return<void> hardwareFailure() {
|
||||
ALOGI("%s", __FUNCTION__);
|
||||
mParentTest->onHwFailureCallback();
|
||||
return Void();
|
||||
}
|
||||
|
||||
virtual Return<void> configChange(Result result, const BandConfig& config __unused) {
|
||||
ALOGI("%s result %d", __FUNCTION__, result);
|
||||
mParentTest->onResultCallback(result);
|
||||
return Void();
|
||||
}
|
||||
|
||||
virtual Return<void> tuneComplete(Result result __unused, const V1_0::ProgramInfo& info __unused) {
|
||||
return Void();
|
||||
}
|
||||
|
||||
virtual Return<void> tuneComplete_1_1(Result result, const ProgramInfo& info __unused) {
|
||||
ALOGI("%s result %d", __FUNCTION__, result);
|
||||
mParentTest->onResultCallback(result);
|
||||
return Void();
|
||||
}
|
||||
|
||||
virtual Return<void> afSwitch(const V1_0::ProgramInfo& info __unused) {
|
||||
return Void();
|
||||
}
|
||||
|
||||
virtual Return<void> afSwitch_1_1(const ProgramInfo& info __unused) {
|
||||
return Void();
|
||||
}
|
||||
|
||||
virtual Return<void> antennaStateChange(bool connected) {
|
||||
ALOGI("%s connected %d", __FUNCTION__, connected);
|
||||
return Void();
|
||||
}
|
||||
|
||||
virtual Return<void> trafficAnnouncement(bool active) {
|
||||
ALOGI("%s active %d", __FUNCTION__, active);
|
||||
return Void();
|
||||
}
|
||||
|
||||
virtual Return<void> emergencyAnnouncement(bool active) {
|
||||
ALOGI("%s active %d", __FUNCTION__, active);
|
||||
return Void();
|
||||
}
|
||||
|
||||
virtual Return<void> newMetadata(uint32_t channel __unused, uint32_t subChannel __unused,
|
||||
const ::android::hardware::hidl_vec<MetaData>& metadata __unused) {
|
||||
ALOGI("%s", __FUNCTION__);
|
||||
return Void();
|
||||
}
|
||||
|
||||
virtual Return<void> backgroundScanAvailable(bool isAvailable __unused) {
|
||||
return Void();
|
||||
}
|
||||
|
||||
virtual Return<void> backgroundScanComplete(ProgramListResult result __unused) {
|
||||
return Void();
|
||||
}
|
||||
|
||||
virtual Return<void> programListChanged() {
|
||||
return Void();
|
||||
}
|
||||
|
||||
MyCallback(BroadcastRadioHidlTest *parentTest) : mParentTest(parentTest) {}
|
||||
|
||||
private:
|
||||
// BroadcastRadioHidlTest instance to which callbacks will be notified.
|
||||
BroadcastRadioHidlTest *mParentTest;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Method called by MyCallback when a callback with no status or boolean value is received
|
||||
*/
|
||||
void onCallback() {
|
||||
Mutex::Autolock _l(mLock);
|
||||
onCallback_l();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called by MyCallback when hardwareFailure() callback is received
|
||||
*/
|
||||
void onHwFailureCallback() {
|
||||
Mutex::Autolock _l(mLock);
|
||||
mHwFailure = true;
|
||||
onCallback_l();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called by MyCallback when a callback with status is received
|
||||
*/
|
||||
void onResultCallback(Result result) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
mResultCallbackData = result;
|
||||
onCallback_l();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called by MyCallback when a boolean indication is received
|
||||
*/
|
||||
void onBoolCallback(bool result) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
mBoolCallbackData = result;
|
||||
onCallback_l();
|
||||
}
|
||||
|
||||
|
||||
BroadcastRadioHidlTest() :
|
||||
mCallbackCalled(false), mBoolCallbackData(false),
|
||||
mResultCallbackData(Result::OK), mHwFailure(false) {}
|
||||
|
||||
void onCallback_l() {
|
||||
if (!mCallbackCalled) {
|
||||
mCallbackCalled = true;
|
||||
mCallbackCond.broadcast();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool waitForCallback(nsecs_t reltime = 0) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
nsecs_t endTime = systemTime() + reltime;
|
||||
while (!mCallbackCalled) {
|
||||
if (reltime == 0) {
|
||||
mCallbackCond.wait(mLock);
|
||||
} else {
|
||||
nsecs_t now = systemTime();
|
||||
if (now > endTime) {
|
||||
return false;
|
||||
}
|
||||
mCallbackCond.waitRelative(mLock, endTime - now);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getProperties();
|
||||
bool openTuner();
|
||||
bool checkAntenna();
|
||||
|
||||
static const nsecs_t kConfigCallbacktimeoutNs = seconds_to_nanoseconds(10);
|
||||
static const nsecs_t kTuneCallbacktimeoutNs = seconds_to_nanoseconds(30);
|
||||
|
||||
sp<IBroadcastRadio> mRadio;
|
||||
Properties mHalProperties;
|
||||
sp<ITuner> mTuner;
|
||||
sp<MyCallback> mTunerCallback;
|
||||
Mutex mLock;
|
||||
Condition mCallbackCond;
|
||||
bool mCallbackCalled;
|
||||
bool mBoolCallbackData;
|
||||
Result mResultCallbackData;
|
||||
bool mHwFailure;
|
||||
};
|
||||
|
||||
// A class for test environment setup (kept since this file is a template).
|
||||
class BroadcastRadioHidlEnvironment : public ::testing::Environment {
|
||||
public:
|
||||
virtual void SetUp() {}
|
||||
virtual void TearDown() {}
|
||||
};
|
||||
|
||||
bool BroadcastRadioHidlTest::getProperties()
|
||||
{
|
||||
if (mHalProperties.bands.size() == 0) {
|
||||
Result halResult = Result::NOT_INITIALIZED;
|
||||
Return<void> hidlReturn =
|
||||
mRadio->getProperties([&](Result result, const Properties& properties) {
|
||||
halResult = result;
|
||||
if (result == Result::OK) {
|
||||
mHalProperties = properties;
|
||||
}
|
||||
});
|
||||
|
||||
EXPECT_TRUE(hidlReturn.isOk());
|
||||
EXPECT_EQ(Result::OK, halResult);
|
||||
EXPECT_EQ(Class::AM_FM, mHalProperties.classId);
|
||||
EXPECT_GT(mHalProperties.numTuners, 0u);
|
||||
EXPECT_GT(mHalProperties.bands.size(), 0u);
|
||||
}
|
||||
return mHalProperties.bands.size() > 0;
|
||||
static void printSkipped(std::string msg) {
|
||||
std::cout << "[ SKIPPED ] " << msg << std::endl;
|
||||
}
|
||||
|
||||
bool BroadcastRadioHidlTest::openTuner()
|
||||
{
|
||||
if (!getProperties()) {
|
||||
return false;
|
||||
struct TunerCallbackMock : public ITunerCallback {
|
||||
TunerCallbackMock() { EXPECT_CALL(*this, hardwareFailure()).Times(0); }
|
||||
|
||||
MOCK_METHOD0(hardwareFailure, Return<void>());
|
||||
MOCK_TIMEOUT_METHOD2(configChange, Return<void>(Result, const BandConfig&));
|
||||
MOCK_METHOD2(tuneComplete, Return<void>(Result, const V1_0::ProgramInfo&));
|
||||
MOCK_TIMEOUT_METHOD2(tuneComplete_1_1, Return<void>(Result, const ProgramSelector&));
|
||||
MOCK_METHOD1(afSwitch, Return<void>(const V1_0::ProgramInfo&));
|
||||
MOCK_METHOD1(antennaStateChange, Return<void>(bool connected));
|
||||
MOCK_METHOD1(trafficAnnouncement, Return<void>(bool active));
|
||||
MOCK_METHOD1(emergencyAnnouncement, Return<void>(bool active));
|
||||
MOCK_METHOD3(newMetadata, Return<void>(uint32_t ch, uint32_t subCh, const hidl_vec<MetaData>&));
|
||||
MOCK_METHOD1(backgroundScanAvailable, Return<void>(bool));
|
||||
MOCK_TIMEOUT_METHOD1(backgroundScanComplete, Return<void>(ProgramListResult));
|
||||
MOCK_METHOD0(programListChanged, Return<void>());
|
||||
MOCK_TIMEOUT_METHOD1(currentProgramInfoChanged, Return<void>(const ProgramInfo&));
|
||||
};
|
||||
|
||||
class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase,
|
||||
public ::testing::WithParamInterface<Class> {
|
||||
protected:
|
||||
virtual void SetUp() override;
|
||||
virtual void TearDown() override;
|
||||
|
||||
bool openTuner();
|
||||
bool nextBand();
|
||||
bool getProgramList(std::function<void(const hidl_vec<ProgramInfo>& list)> cb);
|
||||
|
||||
Class radioClass;
|
||||
bool skipped = false;
|
||||
|
||||
sp<IBroadcastRadio> mRadioModule;
|
||||
sp<ITuner> mTuner;
|
||||
sp<TunerCallbackMock> mCallback = new TunerCallbackMock();
|
||||
|
||||
private:
|
||||
const BandConfig& getBand(unsigned idx);
|
||||
|
||||
unsigned currentBandIndex = 0;
|
||||
hidl_vec<BandConfig> mBands;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears strong pointer and waits until the object gets destroyed.
|
||||
*
|
||||
* @param ptr The pointer to get cleared.
|
||||
* @param timeout Time to wait for other references.
|
||||
*/
|
||||
template <typename T>
|
||||
static void clearAndWait(sp<T>& ptr, std::chrono::milliseconds timeout) {
|
||||
wp<T> wptr = ptr;
|
||||
ptr.clear();
|
||||
auto limit = steady_clock::now() + timeout;
|
||||
while (wptr.promote() != nullptr) {
|
||||
constexpr auto step = 10ms;
|
||||
if (steady_clock::now() + step > limit) {
|
||||
FAIL() << "Pointer was not released within timeout";
|
||||
break;
|
||||
}
|
||||
sleep_for(step);
|
||||
}
|
||||
if (mTuner.get() == nullptr) {
|
||||
}
|
||||
|
||||
void BroadcastRadioHalTest::SetUp() {
|
||||
radioClass = GetParam();
|
||||
|
||||
// lookup HIDL service
|
||||
auto factory = getService<IBroadcastRadioFactory>();
|
||||
ASSERT_NE(nullptr, factory.get());
|
||||
|
||||
// connect radio module
|
||||
Result connectResult;
|
||||
CallBarrier onConnect;
|
||||
factory->connectModule(radioClass, [&](Result ret, const sp<V1_0::IBroadcastRadio>& radio) {
|
||||
connectResult = ret;
|
||||
if (ret == Result::OK) mRadioModule = IBroadcastRadio::castFrom(radio);
|
||||
onConnect.call();
|
||||
});
|
||||
ASSERT_TRUE(onConnect.waitForCall(kConnectModuleTimeout));
|
||||
|
||||
if (connectResult == Result::INVALID_ARGUMENTS) {
|
||||
printSkipped("This device class is not supported.");
|
||||
skipped = true;
|
||||
return;
|
||||
}
|
||||
ASSERT_EQ(connectResult, Result::OK);
|
||||
ASSERT_NE(nullptr, mRadioModule.get());
|
||||
|
||||
// get module properties
|
||||
Properties prop11;
|
||||
auto& prop10 = prop11.base;
|
||||
auto propResult =
|
||||
mRadioModule->getProperties_1_1([&](const Properties& properties) { prop11 = properties; });
|
||||
|
||||
ASSERT_TRUE(propResult.isOk());
|
||||
EXPECT_EQ(radioClass, prop10.classId);
|
||||
EXPECT_GT(prop10.numTuners, 0u);
|
||||
EXPECT_GT(prop11.supportedProgramTypes.size(), 0u);
|
||||
EXPECT_GT(prop11.supportedIdentifierTypes.size(), 0u);
|
||||
if (radioClass == Class::AM_FM) {
|
||||
EXPECT_GT(prop10.bands.size(), 0u);
|
||||
}
|
||||
mBands = prop10.bands;
|
||||
}
|
||||
|
||||
void BroadcastRadioHalTest::TearDown() {
|
||||
mTuner.clear();
|
||||
mRadioModule.clear();
|
||||
clearAndWait(mCallback, 1s);
|
||||
}
|
||||
|
||||
bool BroadcastRadioHalTest::openTuner() {
|
||||
EXPECT_EQ(nullptr, mTuner.get());
|
||||
|
||||
if (radioClass == Class::AM_FM) {
|
||||
EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _);
|
||||
}
|
||||
|
||||
Result halResult = Result::NOT_INITIALIZED;
|
||||
auto openCb = [&](Result result, const sp<V1_0::ITuner>& tuner) {
|
||||
halResult = result;
|
||||
if (result != Result::OK) return;
|
||||
mTuner = ITuner::castFrom(tuner);
|
||||
};
|
||||
currentBandIndex = 0;
|
||||
auto hidlResult = mRadioModule->openTuner(getBand(0), true, mCallback, openCb);
|
||||
|
||||
EXPECT_TRUE(hidlResult.isOk());
|
||||
EXPECT_EQ(Result::OK, halResult);
|
||||
EXPECT_NE(nullptr, mTuner.get());
|
||||
if (radioClass == Class::AM_FM && mTuner != nullptr) {
|
||||
EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
|
||||
|
||||
BandConfig halConfig;
|
||||
Result halResult = Result::NOT_INITIALIZED;
|
||||
auto hidlReturn = mRadio->openTuner(mHalProperties.bands[0], true, mTunerCallback,
|
||||
[&](Result result, const sp<V1_0::ITuner>& tuner) {
|
||||
halResult = result;
|
||||
if (result == Result::OK) {
|
||||
mTuner = ITuner::castFrom(tuner);
|
||||
}
|
||||
});
|
||||
EXPECT_TRUE(hidlReturn.isOk());
|
||||
mTuner->getConfiguration([&](Result result, const BandConfig& config) {
|
||||
halResult = result;
|
||||
halConfig = config;
|
||||
});
|
||||
EXPECT_EQ(Result::OK, halResult);
|
||||
EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
|
||||
EXPECT_TRUE(halConfig.antennaConnected);
|
||||
}
|
||||
|
||||
EXPECT_NE(nullptr, mTuner.get());
|
||||
return nullptr != mTuner.get();
|
||||
}
|
||||
|
||||
bool BroadcastRadioHidlTest::checkAntenna()
|
||||
{
|
||||
BandConfig halConfig;
|
||||
Result halResult = Result::NOT_INITIALIZED;
|
||||
Return<void> hidlReturn =
|
||||
mTuner->getConfiguration([&](Result result, const BandConfig& config) {
|
||||
halResult = result;
|
||||
if (result == Result::OK) {
|
||||
halConfig = config;
|
||||
}
|
||||
});
|
||||
const BandConfig& BroadcastRadioHalTest::getBand(unsigned idx) {
|
||||
static const BandConfig dummyBandConfig = {};
|
||||
|
||||
return ((halResult == Result::OK) && (halConfig.antennaConnected == true));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test IBroadcastRadio::getProperties() method
|
||||
*
|
||||
* Verifies that:
|
||||
* - the HAL implements the method
|
||||
* - the method returns 0 (no error)
|
||||
* - the implementation class is AM_FM
|
||||
* - the implementation supports at least one tuner
|
||||
* - the implementation supports at one band
|
||||
*/
|
||||
TEST_F(BroadcastRadioHidlTest, GetProperties) {
|
||||
EXPECT_TRUE(getProperties());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IBroadcastRadio::openTuner() method
|
||||
*
|
||||
* Verifies that:
|
||||
* - the HAL implements the method
|
||||
* - the method returns 0 (no error) and a valid ITuner interface
|
||||
*/
|
||||
TEST_F(BroadcastRadioHidlTest, OpenTuner) {
|
||||
EXPECT_TRUE(openTuner());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ITuner::setConfiguration() and getConfiguration methods
|
||||
*
|
||||
* Verifies that:
|
||||
* - the HAL implements both methods
|
||||
* - the methods return 0 (no error)
|
||||
* - the configuration callback is received within kConfigCallbacktimeoutNs ns
|
||||
* - the configuration read back from HAl has the same class Id
|
||||
*/
|
||||
TEST_F(BroadcastRadioHidlTest, SetAndGetConfiguration) {
|
||||
ASSERT_TRUE(openTuner());
|
||||
// test setConfiguration
|
||||
mCallbackCalled = false;
|
||||
Return<Result> hidlResult = mTuner->setConfiguration(mHalProperties.bands[0]);
|
||||
EXPECT_TRUE(hidlResult.isOk());
|
||||
EXPECT_EQ(Result::OK, hidlResult);
|
||||
EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
|
||||
EXPECT_EQ(Result::OK, mResultCallbackData);
|
||||
|
||||
// test getConfiguration
|
||||
BandConfig halConfig;
|
||||
Result halResult;
|
||||
Return<void> hidlReturn =
|
||||
mTuner->getConfiguration([&](Result result, const BandConfig& config) {
|
||||
halResult = result;
|
||||
if (result == Result::OK) {
|
||||
halConfig = config;
|
||||
}
|
||||
});
|
||||
EXPECT_TRUE(hidlReturn.isOk());
|
||||
EXPECT_EQ(Result::OK, halResult);
|
||||
EXPECT_EQ(mHalProperties.bands[0].type, halConfig.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ITuner::scan
|
||||
*
|
||||
* Verifies that:
|
||||
* - the HAL implements the method
|
||||
* - the method returns 0 (no error)
|
||||
* - the tuned callback is received within kTuneCallbacktimeoutNs ns
|
||||
*/
|
||||
TEST_F(BroadcastRadioHidlTest, Scan) {
|
||||
ASSERT_TRUE(openTuner());
|
||||
ASSERT_TRUE(checkAntenna());
|
||||
// test scan UP
|
||||
mCallbackCalled = false;
|
||||
Return<Result> hidlResult = mTuner->scan(Direction::UP, true);
|
||||
EXPECT_TRUE(hidlResult.isOk());
|
||||
EXPECT_EQ(Result::OK, hidlResult);
|
||||
EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
|
||||
|
||||
// test scan DOWN
|
||||
mCallbackCalled = false;
|
||||
hidlResult = mTuner->scan(Direction::DOWN, true);
|
||||
EXPECT_TRUE(hidlResult.isOk());
|
||||
EXPECT_EQ(Result::OK, hidlResult);
|
||||
EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ITuner::step
|
||||
*
|
||||
* Verifies that:
|
||||
* - the HAL implements the method
|
||||
* - the method returns 0 (no error)
|
||||
* - the tuned callback is received within kTuneCallbacktimeoutNs ns
|
||||
*/
|
||||
TEST_F(BroadcastRadioHidlTest, Step) {
|
||||
ASSERT_TRUE(openTuner());
|
||||
ASSERT_TRUE(checkAntenna());
|
||||
// test step UP
|
||||
mCallbackCalled = false;
|
||||
Return<Result> hidlResult = mTuner->step(Direction::UP, true);
|
||||
EXPECT_TRUE(hidlResult.isOk());
|
||||
EXPECT_EQ(Result::OK, hidlResult);
|
||||
EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
|
||||
|
||||
// test step DOWN
|
||||
mCallbackCalled = false;
|
||||
hidlResult = mTuner->step(Direction::DOWN, true);
|
||||
EXPECT_TRUE(hidlResult.isOk());
|
||||
EXPECT_EQ(Result::OK, hidlResult);
|
||||
EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ITuner::tune, getProgramInformation and cancel methods
|
||||
*
|
||||
* Verifies that:
|
||||
* - the HAL implements the methods
|
||||
* - the methods return 0 (no error)
|
||||
* - the tuned callback is received within kTuneCallbacktimeoutNs ns after tune()
|
||||
*/
|
||||
TEST_F(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
|
||||
ASSERT_TRUE(openTuner());
|
||||
ASSERT_TRUE(checkAntenna());
|
||||
|
||||
// test tune
|
||||
ASSERT_GT(mHalProperties.bands[0].spacings.size(), 0u);
|
||||
ASSERT_GT(mHalProperties.bands[0].upperLimit, mHalProperties.bands[0].lowerLimit);
|
||||
|
||||
// test scan UP
|
||||
uint32_t lowerLimit = mHalProperties.bands[0].lowerLimit;
|
||||
uint32_t upperLimit = mHalProperties.bands[0].upperLimit;
|
||||
uint32_t spacing = mHalProperties.bands[0].spacings[0];
|
||||
|
||||
uint32_t channel =
|
||||
lowerLimit + (((upperLimit - lowerLimit) / 2 + spacing - 1) / spacing) * spacing;
|
||||
mCallbackCalled = false;
|
||||
mResultCallbackData = Result::NOT_INITIALIZED;
|
||||
Return<Result> hidlResult = mTuner->tune(channel, 0);
|
||||
EXPECT_TRUE(hidlResult.isOk());
|
||||
EXPECT_EQ(Result::OK, hidlResult);
|
||||
EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
|
||||
|
||||
// test getProgramInformation
|
||||
ProgramInfo halInfo;
|
||||
Result halResult = Result::NOT_INITIALIZED;
|
||||
Return<void> hidlReturn = mTuner->getProgramInformation_1_1(
|
||||
[&](Result result, const ProgramInfo& info) {
|
||||
halResult = result;
|
||||
if (result == Result::OK) {
|
||||
halInfo = info;
|
||||
}
|
||||
});
|
||||
EXPECT_TRUE(hidlReturn.isOk());
|
||||
EXPECT_EQ(Result::OK, halResult);
|
||||
auto &halInfo_1_1 = halInfo.base;
|
||||
if (mResultCallbackData == Result::OK) {
|
||||
EXPECT_TRUE(halInfo_1_1.tuned);
|
||||
EXPECT_LE(halInfo_1_1.channel, upperLimit);
|
||||
EXPECT_GE(halInfo_1_1.channel, lowerLimit);
|
||||
} else {
|
||||
EXPECT_EQ(false, halInfo_1_1.tuned);
|
||||
if (radioClass != Class::AM_FM) {
|
||||
ALOGD("Not AM/FM radio, returning dummy band config");
|
||||
return dummyBandConfig;
|
||||
}
|
||||
|
||||
// test cancel
|
||||
mTuner->tune(lowerLimit, 0);
|
||||
hidlResult = mTuner->cancel();
|
||||
EXPECT_GT(mBands.size(), idx);
|
||||
if (mBands.size() <= idx) {
|
||||
ALOGD("Band index out of bound, returning dummy band config");
|
||||
return dummyBandConfig;
|
||||
}
|
||||
|
||||
auto& band = mBands[idx];
|
||||
ALOGD("Returning %s band", toString(band.type).c_str());
|
||||
return band;
|
||||
}
|
||||
|
||||
bool BroadcastRadioHalTest::nextBand() {
|
||||
if (currentBandIndex + 1 >= mBands.size()) return false;
|
||||
currentBandIndex++;
|
||||
|
||||
BandConfig bandCb;
|
||||
EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _)
|
||||
.WillOnce(DoAll(SaveArg<1>(&bandCb), testing::Return(ByMove(Void()))));
|
||||
auto hidlResult = mTuner->setConfiguration(getBand(currentBandIndex));
|
||||
EXPECT_EQ(Result::OK, hidlResult);
|
||||
EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
|
||||
EXPECT_EQ(getBand(currentBandIndex), bandCb);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BroadcastRadioHalTest::getProgramList(
|
||||
std::function<void(const hidl_vec<ProgramInfo>& list)> cb) {
|
||||
ProgramListResult getListResult = ProgramListResult::NOT_INITIALIZED;
|
||||
bool isListEmpty = true;
|
||||
auto getListCb = [&](ProgramListResult result, const hidl_vec<ProgramInfo>& list) {
|
||||
ALOGD("getListCb(%s, ProgramInfo[%zu])", toString(result).c_str(), list.size());
|
||||
getListResult = result;
|
||||
if (result != ProgramListResult::OK) return;
|
||||
isListEmpty = (list.size() == 0);
|
||||
if (!isListEmpty) cb(list);
|
||||
};
|
||||
|
||||
// first try...
|
||||
EXPECT_TIMEOUT_CALL(*mCallback, backgroundScanComplete, ProgramListResult::OK)
|
||||
.Times(AnyNumber());
|
||||
auto hidlResult = mTuner->getProgramList({}, getListCb);
|
||||
EXPECT_TRUE(hidlResult.isOk());
|
||||
if (!hidlResult.isOk()) return false;
|
||||
|
||||
if (getListResult == ProgramListResult::NOT_STARTED) {
|
||||
auto result = mTuner->startBackgroundScan();
|
||||
EXPECT_EQ(ProgramListResult::OK, result);
|
||||
getListResult = ProgramListResult::NOT_READY; // continue as in NOT_READY case
|
||||
}
|
||||
if (getListResult == ProgramListResult::NOT_READY) {
|
||||
EXPECT_TIMEOUT_CALL_WAIT(*mCallback, backgroundScanComplete, kFullScanTimeout);
|
||||
|
||||
// second (last) try...
|
||||
hidlResult = mTuner->getProgramList({}, getListCb);
|
||||
EXPECT_TRUE(hidlResult.isOk());
|
||||
if (!hidlResult.isOk()) return false;
|
||||
EXPECT_EQ(ProgramListResult::OK, getListResult);
|
||||
}
|
||||
|
||||
return !isListEmpty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IBroadcastRadio::openTuner() method called twice.
|
||||
*
|
||||
* Verifies that:
|
||||
* - the openTuner method succeeds when called for the second time without
|
||||
* deleting previous ITuner instance.
|
||||
*
|
||||
* This is a more strict requirement than in 1.0, where a second openTuner
|
||||
* might fail.
|
||||
*/
|
||||
TEST_P(BroadcastRadioHalTest, OpenTunerTwice) {
|
||||
if (skipped) return;
|
||||
|
||||
ASSERT_TRUE(openTuner());
|
||||
|
||||
auto secondTuner = mTuner;
|
||||
mTuner.clear();
|
||||
|
||||
ASSERT_TRUE(openTuner());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test tuning to program list entry.
|
||||
*
|
||||
* Verifies that:
|
||||
* - getProgramList either succeeds or returns NOT_STARTED/NOT_READY status;
|
||||
* - if the program list is NOT_STARTED, startBackgroundScan makes it completed
|
||||
* within a full scan timeout and the next getProgramList call succeeds;
|
||||
* - if the program list is not empty, tuneByProgramSelector call succeeds;
|
||||
* - getProgramInformation_1_1 returns the same selector as returned in tuneComplete_1_1 call.
|
||||
*/
|
||||
TEST_P(BroadcastRadioHalTest, TuneFromProgramList) {
|
||||
if (skipped) return;
|
||||
ASSERT_TRUE(openTuner());
|
||||
|
||||
ProgramInfo firstProgram;
|
||||
bool foundAny = false;
|
||||
do {
|
||||
auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
|
||||
// don't copy the whole list out, it might be heavy
|
||||
firstProgram = list[0];
|
||||
};
|
||||
if (getProgramList(getCb)) foundAny = true;
|
||||
} while (nextBand());
|
||||
if (HasFailure()) return;
|
||||
if (!foundAny) {
|
||||
printSkipped("Program list is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
ProgramInfo infoCb;
|
||||
ProgramSelector selCb;
|
||||
EXPECT_CALL(*mCallback, tuneComplete(_, _)).Times(0);
|
||||
EXPECT_TIMEOUT_CALL(*mCallback, tuneComplete_1_1, Result::OK, _)
|
||||
.WillOnce(DoAll(SaveArg<1>(&selCb), testing::Return(ByMove(Void()))));
|
||||
EXPECT_TIMEOUT_CALL(*mCallback, currentProgramInfoChanged, _)
|
||||
.WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
|
||||
auto tuneResult = mTuner->tuneByProgramSelector(firstProgram.selector);
|
||||
ASSERT_EQ(Result::OK, tuneResult);
|
||||
EXPECT_TIMEOUT_CALL_WAIT(*mCallback, tuneComplete_1_1, kTuneTimeout);
|
||||
EXPECT_TIMEOUT_CALL_WAIT(*mCallback, currentProgramInfoChanged, kEventPropagationTimeout);
|
||||
EXPECT_EQ(firstProgram.selector.primaryId, selCb.primaryId);
|
||||
EXPECT_EQ(infoCb.selector, selCb);
|
||||
|
||||
bool called = false;
|
||||
auto getResult = mTuner->getProgramInformation_1_1([&](Result result, ProgramInfo info) {
|
||||
called = true;
|
||||
EXPECT_EQ(Result::OK, result);
|
||||
EXPECT_EQ(selCb, info.selector);
|
||||
});
|
||||
ASSERT_TRUE(getResult.isOk());
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that primary vendor identifier isn't used for standard program types.
|
||||
*
|
||||
* Verifies that:
|
||||
* - tuneByProgramSelector fails when VENDORn_PRIMARY is set as a primary
|
||||
* identifier for program types other than VENDORn.
|
||||
*/
|
||||
TEST_P(BroadcastRadioHalTest, TuneFailsForPrimaryVendor) {
|
||||
if (skipped) return;
|
||||
ASSERT_TRUE(openTuner());
|
||||
|
||||
for (auto ptype : kStandardProgramTypes) {
|
||||
ALOGD("Checking %s...", toString(ptype).c_str());
|
||||
ProgramSelector sel = {};
|
||||
sel.programType = static_cast<uint32_t>(ptype);
|
||||
sel.primaryId.type = static_cast<uint32_t>(IdentifierType::VENDOR_PRIMARY_START);
|
||||
|
||||
auto tuneResult = mTuner->tuneByProgramSelector(sel);
|
||||
ASSERT_NE(Result::OK, tuneResult);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that tune with unknown program type fails.
|
||||
*
|
||||
* Verifies that:
|
||||
* - tuneByProgramSelector fails with INVALID_ARGUMENT when unknown program type is passed.
|
||||
*/
|
||||
TEST_P(BroadcastRadioHalTest, TuneFailsForUnknownProgram) {
|
||||
if (skipped) return;
|
||||
ASSERT_TRUE(openTuner());
|
||||
|
||||
// Program type is 1-based, so 0 will be always invalid.
|
||||
ProgramSelector sel = {};
|
||||
auto tuneResult = mTuner->tuneByProgramSelector(sel);
|
||||
ASSERT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cancelling announcement.
|
||||
*
|
||||
* Verifies that:
|
||||
* - cancelAnnouncement succeeds either when there is an announcement or there is none.
|
||||
*/
|
||||
TEST_P(BroadcastRadioHalTest, CancelAnnouncement) {
|
||||
if (skipped) return;
|
||||
ASSERT_TRUE(openTuner());
|
||||
|
||||
auto hidlResult = mTuner->cancelAnnouncement();
|
||||
EXPECT_EQ(Result::OK, hidlResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getImage call with invalid image ID.
|
||||
*
|
||||
* Verifies that:
|
||||
* - getImage call handles argument 0 gracefully.
|
||||
*/
|
||||
TEST_P(BroadcastRadioHalTest, GetNoImage) {
|
||||
if (skipped) return;
|
||||
|
||||
size_t len = 0;
|
||||
auto hidlResult =
|
||||
mRadioModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
|
||||
|
||||
ASSERT_TRUE(hidlResult.isOk());
|
||||
ASSERT_EQ(0u, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test proper image format in metadata.
|
||||
*
|
||||
* Verifies that:
|
||||
* - all images in metadata are provided out-of-band (by id, not as a binary blob);
|
||||
* - images are available for getImage call.
|
||||
*/
|
||||
TEST_P(BroadcastRadioHalTest, OobImagesOnly) {
|
||||
if (skipped) return;
|
||||
ASSERT_TRUE(openTuner());
|
||||
|
||||
std::vector<int> imageIds;
|
||||
|
||||
do {
|
||||
auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
|
||||
for (auto&& program : list) {
|
||||
for (auto&& entry : program.base.metadata) {
|
||||
EXPECT_NE(MetadataType::RAW, entry.type);
|
||||
if (entry.key != MetadataKey::ICON && entry.key != MetadataKey::ART) continue;
|
||||
EXPECT_NE(0, entry.intValue);
|
||||
EXPECT_EQ(0u, entry.rawValue.size());
|
||||
if (entry.intValue != 0) imageIds.push_back(entry.intValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
getProgramList(getCb);
|
||||
} while (nextBand());
|
||||
|
||||
if (imageIds.size() == 0) {
|
||||
printSkipped("No images found");
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto id : imageIds) {
|
||||
ALOGD("Checking image %d", id);
|
||||
|
||||
size_t len = 0;
|
||||
auto hidlResult =
|
||||
mRadioModule->getImage(id, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
|
||||
|
||||
ASSERT_TRUE(hidlResult.isOk());
|
||||
ASSERT_GT(len, 0u);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test AnalogForced switch.
|
||||
*
|
||||
* Verifies that:
|
||||
* - setAnalogForced results either with INVALID_STATE, or isAnalogForced replying the same.
|
||||
*/
|
||||
TEST_P(BroadcastRadioHalTest, AnalogForcedSwitch) {
|
||||
if (skipped) return;
|
||||
ASSERT_TRUE(openTuner());
|
||||
|
||||
bool forced;
|
||||
Result halIsResult;
|
||||
auto isCb = [&](Result result, bool isForced) {
|
||||
halIsResult = result;
|
||||
forced = isForced;
|
||||
};
|
||||
|
||||
// set analog mode
|
||||
auto setResult = mTuner->setAnalogForced(true);
|
||||
ASSERT_TRUE(setResult.isOk());
|
||||
if (Result::INVALID_STATE == setResult) {
|
||||
// if setter fails, getter should fail too - it means the switch is not supported at all
|
||||
auto isResult = mTuner->isAnalogForced(isCb);
|
||||
ASSERT_TRUE(isResult.isOk());
|
||||
EXPECT_EQ(Result::INVALID_STATE, halIsResult);
|
||||
return;
|
||||
}
|
||||
ASSERT_EQ(Result::OK, setResult);
|
||||
|
||||
// check, if it's analog
|
||||
auto isResult = mTuner->isAnalogForced(isCb);
|
||||
ASSERT_TRUE(isResult.isOk());
|
||||
EXPECT_EQ(Result::OK, halIsResult);
|
||||
ASSERT_TRUE(forced);
|
||||
|
||||
// set digital mode
|
||||
setResult = mTuner->setAnalogForced(false);
|
||||
ASSERT_EQ(Result::OK, setResult);
|
||||
|
||||
// check, if it's digital
|
||||
isResult = mTuner->isAnalogForced(isCb);
|
||||
ASSERT_TRUE(isResult.isOk());
|
||||
EXPECT_EQ(Result::OK, halIsResult);
|
||||
ASSERT_FALSE(forced);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(BroadcastRadioHalTestCases, BroadcastRadioHalTest,
|
||||
::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
|
||||
|
||||
} // namespace vts
|
||||
} // namespace V1_1
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::AddGlobalTestEnvironment(new BroadcastRadioHidlEnvironment);
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
int status = RUN_ALL_TESTS();
|
||||
ALOGI("Test result = %d", status);
|
||||
|
||||
28
broadcastradio/1.1/vts/utils/Android.bp
Normal file
28
broadcastradio/1.1/vts/utils/Android.bp
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
cc_library_static {
|
||||
name: "android.hardware.broadcastradio@1.1-vts-utils-lib",
|
||||
srcs: [
|
||||
"call-barrier.cpp",
|
||||
],
|
||||
export_include_dirs: ["include"],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
],
|
||||
}
|
||||
45
broadcastradio/1.1/vts/utils/call-barrier.cpp
Normal file
45
broadcastradio/1.1/vts/utils/call-barrier.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <broadcastradio-vts-utils/call-barrier.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace vts {
|
||||
|
||||
using std::lock_guard;
|
||||
using std::mutex;
|
||||
using std::unique_lock;
|
||||
|
||||
void CallBarrier::call() {
|
||||
lock_guard<mutex> lk(mMut);
|
||||
mWasCalled = true;
|
||||
mCond.notify_all();
|
||||
}
|
||||
|
||||
bool CallBarrier::waitForCall(std::chrono::milliseconds timeout) {
|
||||
unique_lock<mutex> lk(mMut);
|
||||
|
||||
if (mWasCalled) return true;
|
||||
|
||||
auto status = mCond.wait_for(lk, timeout);
|
||||
return status == std::cv_status::no_timeout;
|
||||
}
|
||||
|
||||
} // namespace vts
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_CALL_BARRIER
|
||||
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_CALL_BARRIER
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace vts {
|
||||
|
||||
/**
|
||||
* A barrier for thread synchronization, where one should wait for another to
|
||||
* reach a specific point in execution.
|
||||
*/
|
||||
class CallBarrier {
|
||||
public:
|
||||
/**
|
||||
* Notify the other thread it may continue execution.
|
||||
*
|
||||
* This may be called before the other thread starts waiting on the barrier.
|
||||
*/
|
||||
void call();
|
||||
|
||||
/**
|
||||
* Wait for the other thread to reach call() execution point.
|
||||
*
|
||||
* @param timeout a maximum time to wait.
|
||||
* @returns {@code false} if timed out, {@code true} otherwise.
|
||||
*/
|
||||
bool waitForCall(std::chrono::milliseconds timeout);
|
||||
|
||||
private:
|
||||
bool mWasCalled = false;
|
||||
std::mutex mMut;
|
||||
std::condition_variable mCond;
|
||||
};
|
||||
|
||||
} // namespace vts
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_CALL_BARRIER
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
|
||||
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <thread>
|
||||
|
||||
/**
|
||||
* Common helper objects for gmock timeout extension.
|
||||
*
|
||||
* INTERNAL IMPLEMENTATION - don't use in user code.
|
||||
*/
|
||||
#define EGMOCK_TIMEOUT_METHOD_DEF_(Method, ...) \
|
||||
std::atomic<bool> egmock_called_##Method; \
|
||||
std::mutex egmock_mut_##Method; \
|
||||
std::condition_variable egmock_cond_##Method;
|
||||
|
||||
/**
|
||||
* Common method body for gmock timeout extension.
|
||||
*
|
||||
* INTERNAL IMPLEMENTATION - don't use in user code.
|
||||
*/
|
||||
#define EGMOCK_TIMEOUT_METHOD_BODY_(Method, ...) \
|
||||
auto ret = egmock_##Method(__VA_ARGS__); \
|
||||
{ \
|
||||
std::lock_guard<std::mutex> lk(egmock_mut_##Method); \
|
||||
egmock_called_##Method = true; \
|
||||
egmock_cond_##Method.notify_all(); \
|
||||
} \
|
||||
return ret;
|
||||
|
||||
/**
|
||||
* Gmock MOCK_METHOD0 timeout-capable extension.
|
||||
*/
|
||||
#define MOCK_TIMEOUT_METHOD0(Method, ...) \
|
||||
MOCK_METHOD0(egmock_##Method, __VA_ARGS__); \
|
||||
EGMOCK_TIMEOUT_METHOD_DEF_(Method); \
|
||||
virtual GMOCK_RESULT_(, __VA_ARGS__) Method() { EGMOCK_TIMEOUT_METHOD_BODY_(Method); }
|
||||
|
||||
/**
|
||||
* Gmock MOCK_METHOD1 timeout-capable extension.
|
||||
*/
|
||||
#define MOCK_TIMEOUT_METHOD1(Method, ...) \
|
||||
MOCK_METHOD1(egmock_##Method, __VA_ARGS__); \
|
||||
EGMOCK_TIMEOUT_METHOD_DEF_(Method); \
|
||||
virtual GMOCK_RESULT_(, __VA_ARGS__) Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1) { \
|
||||
EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Gmock MOCK_METHOD2 timeout-capable extension.
|
||||
*/
|
||||
#define MOCK_TIMEOUT_METHOD2(Method, ...) \
|
||||
MOCK_METHOD2(egmock_##Method, __VA_ARGS__); \
|
||||
EGMOCK_TIMEOUT_METHOD_DEF_(Method); \
|
||||
virtual GMOCK_RESULT_(, __VA_ARGS__) \
|
||||
Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1, GMOCK_ARG_(, 2, __VA_ARGS__) egmock_a2) { \
|
||||
EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1, egmock_a2); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Gmock EXPECT_CALL timeout-capable extension.
|
||||
*
|
||||
* It has slightly different syntax from the original macro, to make method name accessible.
|
||||
* So, instead of typing
|
||||
* EXPECT_CALL(account, charge(100, Currency::USD));
|
||||
* you need to inline arguments
|
||||
* EXPECT_TIMEOUT_CALL(account, charge, 100, Currency::USD);
|
||||
*/
|
||||
#define EXPECT_TIMEOUT_CALL(obj, Method, ...) \
|
||||
(obj).egmock_called_##Method = false; \
|
||||
EXPECT_CALL(obj, egmock_##Method(__VA_ARGS__))
|
||||
|
||||
/**
|
||||
* Waits for an earlier EXPECT_TIMEOUT_CALL to execute.
|
||||
*
|
||||
* It does not fully support special constraints of the EXPECT_CALL clause, just proceeds when the
|
||||
* first call to a given method comes. For example, in the following code:
|
||||
* EXPECT_TIMEOUT_CALL(account, charge, 100, _);
|
||||
* account.charge(50, Currency::USD);
|
||||
* EXPECT_TIMEOUT_CALL_WAIT(account, charge, 500ms);
|
||||
* the wait clause will just continue, as the charge method was called.
|
||||
*
|
||||
* @param obj object for a call
|
||||
* @param Method the method to wait for
|
||||
* @param timeout the maximum time for waiting
|
||||
*/
|
||||
#define EXPECT_TIMEOUT_CALL_WAIT(obj, Method, timeout) \
|
||||
{ \
|
||||
std::unique_lock<std::mutex> lk((obj).egmock_mut_##Method); \
|
||||
if (!(obj).egmock_called_##Method) { \
|
||||
auto status = (obj).egmock_cond_##Method.wait_for(lk, timeout); \
|
||||
EXPECT_EQ(std::cv_status::no_timeout, status); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "CameraParameters.h"
|
||||
#include <system/graphics.h>
|
||||
|
||||
|
||||
@@ -26,6 +26,9 @@ cc_library_shared {
|
||||
static_libs: [
|
||||
"android.hardware.camera.common@1.0-helper"
|
||||
],
|
||||
header_libs: [
|
||||
"media_plugin_headers",
|
||||
],
|
||||
include_dirs: [
|
||||
"frameworks/native/include/media/openmax"
|
||||
],
|
||||
|
||||
6
camera/device/1.0/default/OWNERS
Normal file
6
camera/device/1.0/default/OWNERS
Normal file
@@ -0,0 +1,6 @@
|
||||
cychen@google.com
|
||||
epeev@google.com
|
||||
etalvala@google.com
|
||||
shuzhenwang@google.com
|
||||
yinchiayeh@google.com
|
||||
zhijunhe@google.com
|
||||
@@ -177,7 +177,7 @@ Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_
|
||||
if (callback == nullptr) {
|
||||
ALOGE("%s: cannot open camera %s. callback is null!",
|
||||
__FUNCTION__, mCameraId.c_str());
|
||||
_hidl_cb(Status::ILLEGAL_ARGUMENT, session);
|
||||
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
|
||||
return Void();
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_
|
||||
// this must be a disconnected camera
|
||||
ALOGE("%s: cannot open camera %s. camera is disconnected!",
|
||||
__FUNCTION__, mCameraId.c_str());
|
||||
_hidl_cb(Status::CAMERA_DISCONNECTED, session);
|
||||
_hidl_cb(Status::CAMERA_DISCONNECTED, nullptr);
|
||||
return Void();
|
||||
} else {
|
||||
mLock.lock();
|
||||
@@ -239,7 +239,7 @@ Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_
|
||||
return Void();
|
||||
}
|
||||
|
||||
session = new CameraDeviceSession(
|
||||
session = createSession(
|
||||
device, info.static_camera_characteristics, callback);
|
||||
if (session == nullptr) {
|
||||
ALOGE("%s: camera device session allocation failed", __FUNCTION__);
|
||||
@@ -255,9 +255,19 @@ Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_
|
||||
return Void();
|
||||
}
|
||||
mSession = session;
|
||||
|
||||
IF_ALOGV() {
|
||||
session->getInterface()->interfaceChain([](
|
||||
::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
|
||||
ALOGV("Session interface chain:");
|
||||
for (auto iface : interfaceChain) {
|
||||
ALOGV(" %s", iface.c_str());
|
||||
}
|
||||
});
|
||||
}
|
||||
mLock.unlock();
|
||||
}
|
||||
_hidl_cb(status, session);
|
||||
_hidl_cb(status, session->getInterface());
|
||||
return Void();
|
||||
}
|
||||
|
||||
@@ -286,6 +296,13 @@ Return<void> CameraDevice::dumpState(const ::android::hardware::hidl_handle& han
|
||||
session->dumpState(handle);
|
||||
return Void();
|
||||
}
|
||||
|
||||
sp<CameraDeviceSession> CameraDevice::createSession(camera3_device_t* device,
|
||||
const camera_metadata_t* deviceInfo,
|
||||
const sp<ICameraDeviceCallback>& callback) {
|
||||
return new CameraDeviceSession(device, deviceInfo, callback);
|
||||
}
|
||||
|
||||
// End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice.
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
@@ -49,7 +49,6 @@ CameraDeviceSession::CameraDeviceSession(
|
||||
mDerivePostRawSensKey(false),
|
||||
mNumPartialResults(1),
|
||||
mResultBatcher(callback) {
|
||||
|
||||
mDeviceInfo = deviceInfo;
|
||||
camera_metadata_entry partialResultsCount =
|
||||
mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
|
||||
@@ -328,7 +327,8 @@ void CameraDeviceSession::ResultBatcher::setBatchedStreams(
|
||||
mStreamsToBatch = streamsToBatch;
|
||||
}
|
||||
|
||||
void CameraDeviceSession::ResultBatcher::setResultMetadataQueue(std::shared_ptr<ResultMetadataQueue> q) {
|
||||
void CameraDeviceSession::ResultBatcher::setResultMetadataQueue(
|
||||
std::shared_ptr<ResultMetadataQueue> q) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
mResultMetadataQueue = q;
|
||||
}
|
||||
@@ -387,7 +387,8 @@ void CameraDeviceSession::ResultBatcher::checkAndRemoveFirstBatch() {
|
||||
}
|
||||
}
|
||||
|
||||
void CameraDeviceSession::ResultBatcher::sendBatchShutterCbsLocked(std::shared_ptr<InflightBatch> batch) {
|
||||
void CameraDeviceSession::ResultBatcher::sendBatchShutterCbsLocked(
|
||||
std::shared_ptr<InflightBatch> batch) {
|
||||
if (batch->mShutterDelivered) {
|
||||
ALOGW("%s: batch shutter callback already sent!", __FUNCTION__);
|
||||
return;
|
||||
@@ -441,7 +442,8 @@ void CameraDeviceSession::ResultBatcher::pushStreamBuffer(
|
||||
}
|
||||
}
|
||||
|
||||
void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch) {
|
||||
void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
|
||||
std::shared_ptr<InflightBatch> batch) {
|
||||
sendBatchBuffersLocked(batch, mStreamsToBatch);
|
||||
}
|
||||
|
||||
@@ -736,7 +738,7 @@ void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& res
|
||||
|
||||
// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
|
||||
Return<void> CameraDeviceSession::constructDefaultRequestSettings(
|
||||
RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) {
|
||||
RequestTemplate type, ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) {
|
||||
Status status = initStatus();
|
||||
CameraMetadata outMetadata;
|
||||
const camera_metadata_t *rawRequest;
|
||||
@@ -802,7 +804,8 @@ android_dataspace CameraDeviceSession::mapToLegacyDataspace(
|
||||
}
|
||||
|
||||
Return<void> CameraDeviceSession::configureStreams(
|
||||
const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) {
|
||||
const StreamConfiguration& requestedConfiguration,
|
||||
ICameraDeviceSession::configureStreams_cb _hidl_cb) {
|
||||
Status status = initStatus();
|
||||
HalStreamConfiguration outStreams;
|
||||
|
||||
@@ -960,13 +963,13 @@ void CameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& caches
|
||||
}
|
||||
|
||||
Return<void> CameraDeviceSession::getCaptureRequestMetadataQueue(
|
||||
getCaptureRequestMetadataQueue_cb _hidl_cb) {
|
||||
ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) {
|
||||
_hidl_cb(*mRequestMetadataQueue->getDesc());
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> CameraDeviceSession::getCaptureResultMetadataQueue(
|
||||
getCaptureResultMetadataQueue_cb _hidl_cb) {
|
||||
ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) {
|
||||
_hidl_cb(*mResultMetadataQueue->getDesc());
|
||||
return Void();
|
||||
}
|
||||
@@ -974,7 +977,7 @@ Return<void> CameraDeviceSession::getCaptureResultMetadataQueue(
|
||||
Return<void> CameraDeviceSession::processCaptureRequest(
|
||||
const hidl_vec<CaptureRequest>& requests,
|
||||
const hidl_vec<BufferCache>& cachesToRemove,
|
||||
processCaptureRequest_cb _hidl_cb) {
|
||||
ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) {
|
||||
updateBufferCaches(cachesToRemove);
|
||||
|
||||
uint32_t numRequestProcessed = 0;
|
||||
|
||||
@@ -55,6 +55,8 @@ using ::android::hardware::hidl_string;
|
||||
using ::android::sp;
|
||||
using ::android::Mutex;
|
||||
|
||||
struct Camera3Stream;
|
||||
|
||||
/**
|
||||
* Function pointer types with C calling convention to
|
||||
* use for HAL callback functions.
|
||||
@@ -69,12 +71,12 @@ extern "C" {
|
||||
const camera3_notify_msg_t *);
|
||||
}
|
||||
|
||||
struct CameraDeviceSession : public ICameraDeviceSession, private camera3_callback_ops {
|
||||
struct CameraDeviceSession : public virtual RefBase, protected camera3_callback_ops {
|
||||
|
||||
CameraDeviceSession(camera3_device_t*,
|
||||
const camera_metadata_t* deviceInfo,
|
||||
const sp<ICameraDeviceCallback>&);
|
||||
~CameraDeviceSession();
|
||||
virtual ~CameraDeviceSession();
|
||||
// Call by CameraDevice to dump active device states
|
||||
void dumpState(const native_handle_t* fd);
|
||||
// Caller must use this method to check if CameraDeviceSession ctor failed
|
||||
@@ -83,23 +85,35 @@ struct CameraDeviceSession : public ICameraDeviceSession, private camera3_callba
|
||||
void disconnect();
|
||||
bool isClosed();
|
||||
|
||||
// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
|
||||
// Retrieve the HIDL interface, split into its own class to avoid inheritance issues when
|
||||
// dealing with minor version revs and simultaneous implementation and interface inheritance
|
||||
virtual sp<ICameraDeviceSession> getInterface() {
|
||||
return new TrampolineSessionInterface_3_2(this);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow
|
||||
|
||||
Return<void> constructDefaultRequestSettings(
|
||||
RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) override;
|
||||
RequestTemplate type,
|
||||
ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb);
|
||||
Return<void> configureStreams(
|
||||
const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) override;
|
||||
const StreamConfiguration& requestedConfiguration,
|
||||
ICameraDeviceSession::configureStreams_cb _hidl_cb);
|
||||
Return<void> getCaptureRequestMetadataQueue(
|
||||
getCaptureRequestMetadataQueue_cb _hidl_cb) override;
|
||||
ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb);
|
||||
Return<void> getCaptureResultMetadataQueue(
|
||||
getCaptureResultMetadataQueue_cb _hidl_cb) override;
|
||||
ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb);
|
||||
Return<void> processCaptureRequest(
|
||||
const hidl_vec<CaptureRequest>& requests,
|
||||
const hidl_vec<BufferCache>& cachesToRemove,
|
||||
processCaptureRequest_cb _hidl_cb) override;
|
||||
Return<Status> flush() override;
|
||||
Return<void> close() override;
|
||||
ICameraDeviceSession::processCaptureRequest_cb _hidl_cb);
|
||||
Return<Status> flush();
|
||||
Return<void> close();
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
// protecting mClosed/mDisconnected/mInitFail
|
||||
mutable Mutex mStateLock;
|
||||
// device is closed either
|
||||
@@ -302,6 +316,52 @@ private:
|
||||
*/
|
||||
static callbacks_process_capture_result_t sProcessCaptureResult;
|
||||
static callbacks_notify_t sNotify;
|
||||
|
||||
private:
|
||||
|
||||
struct TrampolineSessionInterface_3_2 : public ICameraDeviceSession {
|
||||
TrampolineSessionInterface_3_2(sp<CameraDeviceSession> parent) :
|
||||
mParent(parent) {}
|
||||
|
||||
virtual Return<void> constructDefaultRequestSettings(
|
||||
V3_2::RequestTemplate type,
|
||||
V3_2::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override {
|
||||
return mParent->constructDefaultRequestSettings(type, _hidl_cb);
|
||||
}
|
||||
|
||||
virtual Return<void> configureStreams(
|
||||
const V3_2::StreamConfiguration& requestedConfiguration,
|
||||
V3_2::ICameraDeviceSession::configureStreams_cb _hidl_cb) override {
|
||||
return mParent->configureStreams(requestedConfiguration, _hidl_cb);
|
||||
}
|
||||
|
||||
virtual Return<void> processCaptureRequest(const hidl_vec<V3_2::CaptureRequest>& requests,
|
||||
const hidl_vec<V3_2::BufferCache>& cachesToRemove,
|
||||
V3_2::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override {
|
||||
return mParent->processCaptureRequest(requests, cachesToRemove, _hidl_cb);
|
||||
}
|
||||
|
||||
virtual Return<void> getCaptureRequestMetadataQueue(
|
||||
V3_2::ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) override {
|
||||
return mParent->getCaptureRequestMetadataQueue(_hidl_cb);
|
||||
}
|
||||
|
||||
virtual Return<void> getCaptureResultMetadataQueue(
|
||||
V3_2::ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) override {
|
||||
return mParent->getCaptureResultMetadataQueue(_hidl_cb);
|
||||
}
|
||||
|
||||
virtual Return<Status> flush() override {
|
||||
return mParent->flush();
|
||||
}
|
||||
|
||||
virtual Return<void> close() override {
|
||||
return mParent->close();
|
||||
}
|
||||
|
||||
private:
|
||||
sp<CameraDeviceSession> mParent;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
@@ -80,7 +80,13 @@ struct CameraDevice : public ICameraDevice {
|
||||
Return<void> dumpState(const ::android::hardware::hidl_handle& fd) override;
|
||||
/* End of Methods from ::android::hardware::camera::device::V3_2::ICameraDevice */
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
// Overridden by child implementations for returning different versions of CameraDeviceSession
|
||||
virtual sp<CameraDeviceSession> createSession(camera3_device_t*,
|
||||
const camera_metadata_t* deviceInfo,
|
||||
const sp<ICameraDeviceCallback>&);
|
||||
|
||||
const sp<CameraModule> mModule;
|
||||
const std::string mCameraId;
|
||||
// const after ctor
|
||||
|
||||
6
camera/device/3.2/default/OWNERS
Normal file
6
camera/device/3.2/default/OWNERS
Normal file
@@ -0,0 +1,6 @@
|
||||
cychen@google.com
|
||||
epeev@google.com
|
||||
etalvala@google.com
|
||||
shuzhenwang@google.com
|
||||
yinchiayeh@google.com
|
||||
zhijunhe@google.com
|
||||
25
camera/device/3.3/Android.bp
Normal file
25
camera/device/3.3/Android.bp
Normal file
@@ -0,0 +1,25 @@
|
||||
// This file is autogenerated by hidl-gen -Landroidbp.
|
||||
|
||||
hidl_interface {
|
||||
name: "android.hardware.camera.device@3.3",
|
||||
root: "android.hardware",
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
srcs: [
|
||||
"types.hal",
|
||||
"ICameraDeviceSession.hal",
|
||||
],
|
||||
interfaces: [
|
||||
"android.hardware.camera.common@1.0",
|
||||
"android.hardware.camera.device@3.2",
|
||||
"android.hardware.graphics.common@1.0",
|
||||
"android.hidl.base@1.0",
|
||||
],
|
||||
types: [
|
||||
"HalStream",
|
||||
"HalStreamConfiguration",
|
||||
],
|
||||
gen_java: false,
|
||||
}
|
||||
|
||||
50
camera/device/3.3/ICameraDeviceSession.hal
Normal file
50
camera/device/3.3/ICameraDeviceSession.hal
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.camera.device@3.3;
|
||||
|
||||
import android.hardware.camera.common@1.0::Status;
|
||||
import android.hardware.camera.device@3.2::ICameraDeviceSession;
|
||||
import android.hardware.camera.device@3.2::StreamConfiguration;
|
||||
|
||||
/**
|
||||
* Camera device active session interface.
|
||||
*
|
||||
* Obtained via ICameraDevice::open(), this interface contains the methods to
|
||||
* configure and request captures from an active camera device.
|
||||
*
|
||||
*/
|
||||
interface ICameraDeviceSession extends @3.2::ICameraDeviceSession {
|
||||
|
||||
/**
|
||||
* configureStreams_3_3:
|
||||
*
|
||||
* Identical to @3.2::ICameraDeviceSession.configureStreams, except that:
|
||||
*
|
||||
* - The output HalStreamConfiguration now contains an overrideDataspace
|
||||
* field, to be used by the HAL to select a different dataspace for some
|
||||
* use cases when dealing with the IMPLEMENTATION_DEFINED pixel format.
|
||||
*
|
||||
* Clients may invoke either this method or
|
||||
* @3.2::ICameraDeviceSession.configureStreams() for stream configuration.
|
||||
* This method is recommended for clients to use since it provides more
|
||||
* flexibility.
|
||||
*/
|
||||
configureStreams_3_3(StreamConfiguration requestedConfiguration)
|
||||
generates (Status status,
|
||||
@3.3::HalStreamConfiguration halConfiguration);
|
||||
|
||||
};
|
||||
30
camera/device/3.3/default/Android.bp
Normal file
30
camera/device/3.3/default/Android.bp
Normal file
@@ -0,0 +1,30 @@
|
||||
cc_library_shared {
|
||||
name: "camera.device@3.3-impl",
|
||||
defaults: ["hidl_defaults"],
|
||||
proprietary: true,
|
||||
srcs: ["CameraDevice.cpp",
|
||||
"CameraDeviceSession.cpp",
|
||||
"convert.cpp"],
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libutils",
|
||||
"libcutils",
|
||||
"camera.device@3.2-impl",
|
||||
"android.hardware.camera.device@3.2",
|
||||
"android.hardware.camera.device@3.3",
|
||||
"android.hardware.camera.provider@2.4",
|
||||
"android.hardware.graphics.mapper@2.0",
|
||||
"liblog",
|
||||
"libhardware",
|
||||
"libcamera_metadata",
|
||||
"libfmq"
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.camera.common@1.0-helper"
|
||||
],
|
||||
export_include_dirs: ["."],
|
||||
export_shared_lib_headers: [
|
||||
"libfmq",
|
||||
]
|
||||
}
|
||||
67
camera/device/3.3/default/CameraDevice.cpp
Normal file
67
camera/device/3.3/default/CameraDevice.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "CamDev@3.3-impl"
|
||||
#include <log/log.h>
|
||||
|
||||
#include <utils/Vector.h>
|
||||
#include <utils/Trace.h>
|
||||
#include "CameraDevice_3_3.h"
|
||||
#include <include/convert.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace camera {
|
||||
namespace device {
|
||||
namespace V3_3 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::hardware::camera::common::V1_0::Status;
|
||||
using namespace ::android::hardware::camera::device;
|
||||
|
||||
CameraDevice::CameraDevice(
|
||||
sp<CameraModule> module, const std::string& cameraId,
|
||||
const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames) :
|
||||
V3_2::implementation::CameraDevice(module, cameraId, cameraDeviceNames) {
|
||||
}
|
||||
|
||||
CameraDevice::~CameraDevice() {
|
||||
}
|
||||
|
||||
sp<V3_2::implementation::CameraDeviceSession> CameraDevice::createSession(camera3_device_t* device,
|
||||
const camera_metadata_t* deviceInfo,
|
||||
const sp<V3_2::ICameraDeviceCallback>& callback) {
|
||||
sp<CameraDeviceSession> session = new CameraDeviceSession(device, deviceInfo, callback);
|
||||
IF_ALOGV() {
|
||||
session->getInterface()->interfaceChain([](
|
||||
::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
|
||||
ALOGV("Session interface chain:");
|
||||
for (auto iface : interfaceChain) {
|
||||
ALOGV(" %s", iface.c_str());
|
||||
}
|
||||
});
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
// End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice.
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V3_3
|
||||
} // namespace device
|
||||
} // namespace camera
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
178
camera/device/3.3/default/CameraDeviceSession.cpp
Normal file
178
camera/device/3.3/default/CameraDeviceSession.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "CamDevSession@3.3-impl"
|
||||
#include <android/log.h>
|
||||
|
||||
#include <set>
|
||||
#include <utils/Trace.h>
|
||||
#include <hardware/gralloc.h>
|
||||
#include <hardware/gralloc1.h>
|
||||
#include "CameraDeviceSession.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace camera {
|
||||
namespace device {
|
||||
namespace V3_3 {
|
||||
namespace implementation {
|
||||
|
||||
CameraDeviceSession::CameraDeviceSession(
|
||||
camera3_device_t* device,
|
||||
const camera_metadata_t* deviceInfo,
|
||||
const sp<V3_2::ICameraDeviceCallback>& callback) :
|
||||
V3_2::implementation::CameraDeviceSession(device, deviceInfo, callback) {
|
||||
}
|
||||
|
||||
CameraDeviceSession::~CameraDeviceSession() {
|
||||
}
|
||||
|
||||
Return<void> CameraDeviceSession::configureStreams_3_3(
|
||||
const StreamConfiguration& requestedConfiguration,
|
||||
ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb) {
|
||||
Status status = initStatus();
|
||||
HalStreamConfiguration outStreams;
|
||||
|
||||
// hold the inflight lock for entire configureStreams scope since there must not be any
|
||||
// inflight request/results during stream configuration.
|
||||
Mutex::Autolock _l(mInflightLock);
|
||||
if (!mInflightBuffers.empty()) {
|
||||
ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
|
||||
__FUNCTION__, mInflightBuffers.size());
|
||||
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
|
||||
return Void();
|
||||
}
|
||||
|
||||
if (!mInflightAETriggerOverrides.empty()) {
|
||||
ALOGE("%s: trying to configureStreams while there are still %zu inflight"
|
||||
" trigger overrides!", __FUNCTION__,
|
||||
mInflightAETriggerOverrides.size());
|
||||
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
|
||||
return Void();
|
||||
}
|
||||
|
||||
if (!mInflightRawBoostPresent.empty()) {
|
||||
ALOGE("%s: trying to configureStreams while there are still %zu inflight"
|
||||
" boost overrides!", __FUNCTION__,
|
||||
mInflightRawBoostPresent.size());
|
||||
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
|
||||
return Void();
|
||||
}
|
||||
|
||||
if (status != Status::OK) {
|
||||
_hidl_cb(status, outStreams);
|
||||
return Void();
|
||||
}
|
||||
|
||||
camera3_stream_configuration_t stream_list;
|
||||
hidl_vec<camera3_stream_t*> streams;
|
||||
|
||||
stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
|
||||
stream_list.num_streams = requestedConfiguration.streams.size();
|
||||
streams.resize(stream_list.num_streams);
|
||||
stream_list.streams = streams.data();
|
||||
|
||||
for (uint32_t i = 0; i < stream_list.num_streams; i++) {
|
||||
int id = requestedConfiguration.streams[i].id;
|
||||
|
||||
if (mStreamMap.count(id) == 0) {
|
||||
Camera3Stream stream;
|
||||
V3_2::implementation::convertFromHidl(requestedConfiguration.streams[i], &stream);
|
||||
mStreamMap[id] = stream;
|
||||
mStreamMap[id].data_space = mapToLegacyDataspace(
|
||||
mStreamMap[id].data_space);
|
||||
mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
|
||||
} else {
|
||||
// width/height/format must not change, but usage/rotation might need to change
|
||||
if (mStreamMap[id].stream_type !=
|
||||
(int) requestedConfiguration.streams[i].streamType ||
|
||||
mStreamMap[id].width != requestedConfiguration.streams[i].width ||
|
||||
mStreamMap[id].height != requestedConfiguration.streams[i].height ||
|
||||
mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
|
||||
mStreamMap[id].data_space !=
|
||||
mapToLegacyDataspace( static_cast<android_dataspace_t> (
|
||||
requestedConfiguration.streams[i].dataSpace))) {
|
||||
ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
|
||||
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
|
||||
return Void();
|
||||
}
|
||||
mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
|
||||
mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
|
||||
}
|
||||
streams[i] = &mStreamMap[id];
|
||||
}
|
||||
|
||||
ATRACE_BEGIN("camera3->configure_streams");
|
||||
status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
|
||||
ATRACE_END();
|
||||
|
||||
// In case Hal returns error most likely it was not able to release
|
||||
// the corresponding resources of the deleted streams.
|
||||
if (ret == OK) {
|
||||
// delete unused streams, note we do this after adding new streams to ensure new stream
|
||||
// will not have the same address as deleted stream, and HAL has a chance to reference
|
||||
// the to be deleted stream in configure_streams call
|
||||
for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
|
||||
int id = it->first;
|
||||
bool found = false;
|
||||
for (const auto& stream : requestedConfiguration.streams) {
|
||||
if (id == stream.id) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Unmap all buffers of deleted stream
|
||||
// in case the configuration call succeeds and HAL
|
||||
// is able to release the corresponding resources too.
|
||||
cleanupBuffersLocked(id);
|
||||
it = mStreamMap.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// Track video streams
|
||||
mVideoStreamIds.clear();
|
||||
for (const auto& stream : requestedConfiguration.streams) {
|
||||
if (stream.streamType == V3_2::StreamType::OUTPUT &&
|
||||
stream.usage &
|
||||
graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
|
||||
mVideoStreamIds.push_back(stream.id);
|
||||
}
|
||||
}
|
||||
mResultBatcher.setBatchedStreams(mVideoStreamIds);
|
||||
}
|
||||
|
||||
if (ret == -EINVAL) {
|
||||
status = Status::ILLEGAL_ARGUMENT;
|
||||
} else if (ret != OK) {
|
||||
status = Status::INTERNAL_ERROR;
|
||||
} else {
|
||||
convertToHidl(stream_list, &outStreams);
|
||||
mFirstRequest = true;
|
||||
}
|
||||
|
||||
_hidl_cb(status, outStreams);
|
||||
return Void();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V3_3
|
||||
} // namespace device
|
||||
} // namespace camera
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user