[automerge] Fix array out of bound in audioTransportToHal. 2p: f16c6d3a57 am: 377e999d1b
Original change: https://googleplex-android-review.googlesource.com/c/platform/hardware/interfaces/+/19214732
Change-Id: I3247e21feeec867a71694e2ed3e13d930cc54d8d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/atrace/1.0/default/android.hardware.atrace@1.0-service.rc b/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
index 7110b45..31459b4 100644
--- a/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
+++ b/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
@@ -14,4 +14,4 @@
interface android.hardware.atrace@1.0::IAtraceDevice default
class early_hal
user system
- group system
+ group system readtracefs
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index 901b7ee..b170ff4 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -48,6 +48,8 @@
"libhidlbase",
"liblog",
"libmedia_helper",
+ "libmediautils_vendor",
+ "libmemunreachable",
"libutils",
"android.hardware.audio.common-util",
],
@@ -138,8 +140,8 @@
defaults: ["android.hardware.audio@6.0-impl_default"],
}
-cc_library_shared {
- name: "android.hardware.audio@7.0-impl",
+cc_defaults {
+ name: "android.hardware.audio@7.0-impl_default",
defaults: ["android.hardware.audio-impl_default"],
shared_libs: [
"android.hardware.audio@7.0",
@@ -155,3 +157,8 @@
"-include common/all-versions/VersionMacro.h",
],
}
+
+cc_library_shared {
+ name: "android.hardware.audio@7.0-impl",
+ defaults: ["android.hardware.audio@7.0-impl_default"],
+}
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 130dfba..c33e6f3 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -30,6 +30,8 @@
#include <algorithm>
#include <android/log.h>
+#include <mediautils/MemoryLeakTrackUtil.h>
+#include <memunreachable/memunreachable.h>
#include <HidlUtils.h>
@@ -456,9 +458,32 @@
}
#endif
-Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
+Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
- analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
+ const int fd0 = fd->data[0];
+ bool dumpMem = false;
+ bool unreachableMemory = false;
+ for (const auto& option : options) {
+ if (option == "-m") {
+ dumpMem = true;
+ } else if (option == "--unreachable") {
+ unreachableMemory = true;
+ }
+ }
+
+ if (dumpMem) {
+ dprintf(fd0, "\nDumping memory:\n");
+ std::string s = dumpMemoryAddresses(100 /* limit */);
+ write(fd0, s.c_str(), s.size());
+ }
+ if (unreachableMemory) {
+ dprintf(fd0, "\nDumping unreachable memory:\n");
+ // TODO - should limit be an argument parameter?
+ std::string s = GetUnreachableMemoryString(true /* contents */, 100 /* limit */);
+ write(fd0, s.c_str(), s.size());
+ }
+
+ analyzeStatus("dump", mDevice->dump(mDevice, fd0));
}
return Void();
}
diff --git a/audio/core/all-versions/vts/functional/6.0/Generators.cpp b/audio/core/all-versions/vts/functional/6.0/Generators.cpp
index 6b4dbc1..e3b98c9 100644
--- a/audio/core/all-versions/vts/functional/6.0/Generators.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/Generators.cpp
@@ -36,9 +36,14 @@
std::vector<DeviceConfigParameter> generateOutputDeviceConfigParameters(bool oneProfilePerDevice) {
std::vector<DeviceConfigParameter> result;
for (const auto& device : getDeviceParameters()) {
- auto module =
- getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+ const std::string moduleName = std::get<PARAM_DEVICE_NAME>(device);
+ auto module = getCachedPolicyConfig().getModuleFromName(moduleName);
for (const auto& ioProfile : module->getOutputProfiles()) {
+ if (getCachedPolicyConfig()
+ .getAttachedSinkDeviceForMixPort(moduleName, ioProfile->getName())
+ .empty()) {
+ continue; // no attached device
+ }
for (const auto& profile : ioProfile->getAudioProfiles()) {
const auto& channels = profile->getChannels();
const auto& sampleRates = profile->getSampleRates();
@@ -94,9 +99,14 @@
std::vector<DeviceConfigParameter> generateInputDeviceConfigParameters(bool oneProfilePerDevice) {
std::vector<DeviceConfigParameter> result;
for (const auto& device : getDeviceParameters()) {
- auto module =
- getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+ const std::string moduleName = std::get<PARAM_DEVICE_NAME>(device);
+ auto module = getCachedPolicyConfig().getModuleFromName(moduleName);
for (const auto& ioProfile : module->getInputProfiles()) {
+ if (getCachedPolicyConfig()
+ .getAttachedSourceDeviceForMixPort(moduleName, ioProfile->getName())
+ .empty()) {
+ continue; // no attached device
+ }
for (const auto& profile : ioProfile->getAudioProfiles()) {
const auto& channels = profile->getChannels();
const auto& sampleRates = profile->getSampleRates();
diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
index 0cc6a5b..2759801 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -499,18 +499,10 @@
return xsd::isLinearPcm(std::get<PARAM_CONFIG>(cfg).base.format)
// MMAP NOIRQ and HW A/V Sync profiles use special writing protocols.
&&
- std::find_if(flags.begin(), flags.end(),
- [](const auto& flag) {
- return flag == toString(xsd::AudioInOutFlag::
- AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) ||
- flag == toString(xsd::AudioInOutFlag::
- AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
- }) == flags.end() &&
- !getCachedPolicyConfig()
- .getAttachedSinkDeviceForMixPort(
- std::get<PARAM_DEVICE_NAME>(std::get<PARAM_DEVICE>(cfg)),
- std::get<PARAM_PORT_NAME>(cfg))
- .empty();
+ std::find_if(flags.begin(), flags.end(), [](const auto& flag) {
+ return flag == toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) ||
+ flag == toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
+ }) == flags.end();
});
return pcmParams;
}();
@@ -677,20 +669,13 @@
// reading h/w hotword might require Soundtrigger to be active.
&&
std::find_if(
- flags.begin(), flags.end(),
- [](const auto& flag) {
+ flags.begin(), flags.end(), [](const auto& flag) {
return flag == toString(
xsd::AudioInOutFlag::
AUDIO_INPUT_FLAG_MMAP_NOIRQ) ||
flag == toString(xsd::AudioInOutFlag::
AUDIO_INPUT_FLAG_HW_HOTWORD);
- }) == flags.end() &&
- !getCachedPolicyConfig()
- .getAttachedSourceDeviceForMixPort(
- std::get<PARAM_DEVICE_NAME>(
- std::get<PARAM_DEVICE>(cfg)),
- std::get<PARAM_PORT_NAME>(cfg))
- .empty();
+ }) == flags.end();
});
return pcmParams;
}();
diff --git a/audio/core/all-versions/vts/functional/7.0/Generators.cpp b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
index d2ba339..42bf1d3 100644
--- a/audio/core/all-versions/vts/functional/7.0/Generators.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
@@ -95,13 +95,21 @@
std::vector<DeviceConfigParameter> generateOutputDeviceConfigParameters(bool oneProfilePerDevice) {
std::vector<DeviceConfigParameter> result;
for (const auto& device : getDeviceParameters()) {
- auto module =
- getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+ const std::string moduleName = std::get<PARAM_DEVICE_NAME>(device);
+ auto module = getCachedPolicyConfig().getModuleFromName(moduleName);
if (!module || !module->getFirstMixPorts()) break;
for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
if (mixPort.getRole() != xsd::Role::source) continue; // not an output profile
+ if (getCachedPolicyConfig()
+ .getAttachedSinkDeviceForMixPort(moduleName, mixPort.getName())
+ .empty()) {
+ continue; // no attached device
+ }
auto [flags, isOffload] = generateOutFlags(mixPort);
for (const auto& profile : mixPort.getProfile()) {
+ if (!profile.hasFormat() || !profile.hasSamplingRates() ||
+ !profile.hasChannelMasks())
+ continue;
auto configs = combineAudioConfig(profile.getChannelMasks(),
profile.getSamplingRates(), profile.getFormat());
for (auto& config : configs) {
@@ -220,17 +228,25 @@
std::vector<DeviceConfigParameter> generateInputDeviceConfigParameters(bool oneProfilePerDevice) {
std::vector<DeviceConfigParameter> result;
for (const auto& device : getDeviceParameters()) {
- auto module =
- getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+ const std::string moduleName = std::get<PARAM_DEVICE_NAME>(device);
+ auto module = getCachedPolicyConfig().getModuleFromName(moduleName);
if (!module || !module->getFirstMixPorts()) break;
for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
if (mixPort.getRole() != xsd::Role::sink) continue; // not an input profile
+ if (getCachedPolicyConfig()
+ .getAttachedSourceDeviceForMixPort(moduleName, mixPort.getName())
+ .empty()) {
+ continue; // no attached device
+ }
std::vector<AudioInOutFlag> flags;
if (mixPort.hasFlags()) {
std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(),
std::back_inserter(flags), [](auto flag) { return toString(flag); });
}
for (const auto& profile : mixPort.getProfile()) {
+ if (!profile.hasFormat() || !profile.hasSamplingRates() ||
+ !profile.hasChannelMasks())
+ continue;
auto configs = combineAudioConfig(profile.getChannelMasks(),
profile.getSamplingRates(), profile.getFormat());
for (const auto& config : configs) {
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index e446a7f..cfee26a 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -211,6 +211,7 @@
data: [
"tests/apm_config_no_vx.xml",
"tests/apm_config_with_vx.xml",
+ "tests/apm_config_b_205808571_6_0.xml",
],
test_config: "tests/HalAudioV6_0GeneratorTest.xml",
}
@@ -239,6 +240,8 @@
data: [
"tests/apm_config_no_vx_7_0.xml",
"tests/apm_config_with_vx_7_0.xml",
+ "tests/apm_config_b_204314749_7_0.xml",
+ "tests/apm_config_b_205808571_7_0.xml",
],
test_config: "tests/HalAudioV7_0GeneratorTest.xml",
}
diff --git a/audio/core/all-versions/vts/functional/PolicyConfig.h b/audio/core/all-versions/vts/functional/PolicyConfig.h
index a94041c..171d03f 100644
--- a/audio/core/all-versions/vts/functional/PolicyConfig.h
+++ b/audio/core/all-versions/vts/functional/PolicyConfig.h
@@ -76,6 +76,16 @@
const std::set<std::string>& getModulesWithDevicesNames() const {
return mModulesWithDevicesNames;
}
+ std::string getAttachedSinkDeviceForMixPort(const std::string& moduleName,
+ const std::string& mixPortName) const {
+ return findAttachedDevice(getAttachedDevices(moduleName),
+ getSinkDevicesForMixPort(moduleName, mixPortName));
+ }
+ std::string getAttachedSourceDeviceForMixPort(const std::string& moduleName,
+ const std::string& mixPortName) const {
+ return findAttachedDevice(getAttachedDevices(moduleName),
+ getSourceDevicesForMixPort(moduleName, mixPortName));
+ }
bool haveInputProfilesInModule(const std::string& name) const {
auto module = getModuleFromName(name);
return module && !module->getInputProfiles().empty();
@@ -92,6 +102,8 @@
for (const auto& module : hwModules) {
if (module->getDeclaredDevices().indexOf(device) >= 0) {
mModulesWithDevicesNames.insert(module->getName());
+ mAttachedDevicesPerModule[module->getName()].push_back(
+ device->getTagName());
break;
}
}
@@ -100,16 +112,64 @@
for (const auto& module : hwModules) {
if (module->getDeclaredDevices().indexOf(device) >= 0) {
mModulesWithDevicesNames.insert(module->getName());
+ mAttachedDevicesPerModule[module->getName()].push_back(
+ device->getTagName());
break;
}
}
}
}
}
+ std::string findAttachedDevice(const std::vector<std::string>& attachedDevices,
+ const std::set<std::string>& possibleDevices) const {
+ for (const auto& device : attachedDevices) {
+ if (possibleDevices.count(device)) return device;
+ }
+ return {};
+ }
+ std::vector<std::string> getAttachedDevices(const std::string& moduleName) const {
+ if (auto iter = mAttachedDevicesPerModule.find(moduleName);
+ iter != mAttachedDevicesPerModule.end()) {
+ return iter->second;
+ }
+ return {};
+ }
+ std::set<std::string> getSinkDevicesForMixPort(const std::string& moduleName,
+ const std::string& mixPortName) const {
+ std::set<std::string> result;
+ auto module = getModuleFromName(moduleName);
+ if (module != nullptr) {
+ for (const auto& route : module->getRoutes()) {
+ for (const auto& source : route->getSources()) {
+ if (source->getTagName() == mixPortName) {
+ result.insert(route->getSink()->getTagName());
+ }
+ }
+ }
+ }
+ return result;
+ }
+ std::set<std::string> getSourceDevicesForMixPort(const std::string& moduleName,
+ const std::string& mixPortName) const {
+ std::set<std::string> result;
+ auto module = getModuleFromName(moduleName);
+ if (module != nullptr) {
+ for (const auto& route : module->getRoutes()) {
+ if (route->getSink()->getTagName() == mixPortName) {
+ const auto& sources = route->getSources();
+ std::transform(sources.begin(), sources.end(),
+ std::inserter(result, result.end()),
+ [](const auto& source) { return source->getTagName(); });
+ }
+ }
+ }
+ return result;
+ }
const std::string mConfigFileName;
status_t mStatus = android::NO_INIT;
std::string mFilePath;
sp<const android::HwModule> mPrimaryModule = nullptr;
std::set<std::string> mModulesWithDevicesNames;
+ std::map<std::string, std::vector<std::string>> mAttachedDevicesPerModule;
};
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml
index f035baf..ae57125 100644
--- a/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml
@@ -34,5 +34,6 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalAudioV6_0TargetTest" />
+ <option name="native-test-timeout" value="5m" />
</test>
</configuration>
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml
index 6635f31..55dbaf1 100644
--- a/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml
@@ -34,5 +34,6 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalAudioV7_0TargetTest" />
+ <option name="native-test-timeout" value="5m" />
</test>
</configuration>
diff --git a/audio/core/all-versions/vts/functional/tests/HalAudioV6_0GeneratorTest.xml b/audio/core/all-versions/vts/functional/tests/HalAudioV6_0GeneratorTest.xml
index 0c85a05..0230447 100644
--- a/audio/core/all-versions/vts/functional/tests/HalAudioV6_0GeneratorTest.xml
+++ b/audio/core/all-versions/vts/functional/tests/HalAudioV6_0GeneratorTest.xml
@@ -24,6 +24,7 @@
<option name="cleanup" value="true" />
<option name="push" value="apm_config_no_vx.xml->/data/local/tmp/apm_config_no_vx.xml" />
<option name="push" value="apm_config_with_vx.xml->/data/local/tmp/apm_config_with_vx.xml" />
+ <option name="push" value="apm_config_b_205808571_6_0.xml->/data/local/tmp/apm_config_b_205808571_6_0.xml" />
<option name="push" value="HalAudioV6_0GeneratorTest->/data/local/tmp/HalAudioV6_0GeneratorTest" />
</target_preparer>
diff --git a/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml b/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml
index 2e79455..0d8abd3 100644
--- a/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml
+++ b/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml
@@ -24,6 +24,8 @@
<option name="cleanup" value="true" />
<option name="push" value="apm_config_no_vx_7_0.xml->/data/local/tmp/apm_config_no_vx.xml" />
<option name="push" value="apm_config_with_vx_7_0.xml->/data/local/tmp/apm_config_with_vx.xml" />
+ <option name="push" value="apm_config_b_204314749_7_0.xml->/data/local/tmp/apm_config_b_204314749_7_0.xml" />
+ <option name="push" value="apm_config_b_205808571_7_0.xml->/data/local/tmp/apm_config_b_205808571_7_0.xml" />
<option name="push" value="HalAudioV7_0GeneratorTest->/data/local/tmp/HalAudioV7_0GeneratorTest" />
</target_preparer>
diff --git a/audio/core/all-versions/vts/functional/tests/apm_config_b_204314749_7_0.xml b/audio/core/all-versions/vts/functional/tests/apm_config_b_204314749_7_0.xml
new file mode 100644
index 0000000..5bdca9a
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/tests/apm_config_b_204314749_7_0.xml
@@ -0,0 +1,263 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<audioPolicyConfiguration version="7.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <!-- version section contains a “version” tag in the form “major.minor” e.g. version=”1.0” -->
+
+ <!-- Global configuration Decalaration -->
+ <globalConfiguration speaker_drc_enabled="false"/>
+
+
+ <!-- Modules section:
+ There is one section per audio HW module present on the platform.
+ Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”.
+ The module names are the same as in current .conf file:
+ “primary”, “A2DP”, “remote_submix”, “USB”
+ Each module will contain the following sections:
+ “devicePorts”: a list of device descriptors for all input and output devices accessible via this
+ module.
+ This contains both permanently attached devices and removable devices.
+ “mixPorts”: listing all output and input streams exposed by the audio HAL
+ “routes”: list of possible connections between input and output devices or between stream and
+ devices.
+ "route": is defined by an attribute:
+ -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
+ -"sink": the sink involved in this route
+ -"sources": all the sources than can be connected to the sink via vis route
+ “attachedDevices”: permanently attached devices.
+ The attachedDevices section is a list of devices names. The names correspond to device names
+ defined in <devicePorts> section.
+ “defaultOutputDevice”: device to be used by default when no policy rule applies
+ -->
+ <modules>
+ <!-- Primary Audio HAL -->
+ <module name="primary" halVersion="3.0">
+ <attachedDevices>
+ <item>Speaker</item>
+ <item>Built-In Mic</item>
+ <item>Built-In Back Mic</item>
+ <item>Echo Reference</item>
+ <item>Tuner</item>
+ </attachedDevices>
+ <defaultOutputDevice>Speaker</defaultOutputDevice>
+ <mixPorts>
+ <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="tunnel pcm" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="direct pcm" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="direct output" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+ <profile name=""/>
+ </mixPort>
+ <mixPort name="tunnel direct output" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+ <profile name=""/>
+ </mixPort>
+ <mixPort name="mmap_no_irq_out" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="primary input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ <mixPort name="tunnel a2dp" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+ <profile name=""/>
+ </mixPort>
+ <mixPort name="direct a2dp" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+ <profile name=""/>
+ </mixPort>
+ <mixPort name="echo reference" role="sink">
+ <profile name="echo_reference" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ <mixPort name="built-in mic" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="16000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ <mixPort name="ble_in" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
+ <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER">
+ <gains>
+ <gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-10000"
+ maxValueMB="0"
+ defaultValueMB="-6000"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="HDMI Out" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">
+ </devicePort>
+ <devicePort tagName="Tuner" role="source" type="AUDIO_DEVICE_IN_TV_TUNER">
+ <gains>
+ <gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-10000"
+ maxValueMB="0"
+ defaultValueMB="-6000"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+
+ <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source" address="top">
+ <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ <devicePort tagName="Echo Reference" type="AUDIO_DEVICE_IN_ECHO_REFERENCE" role="source">
+ <profile name="echo_reference" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BLE-In" type="AUDIO_DEVICE_IN_BLUETOOTH_BLE" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ </devicePorts>
+ <!-- route declaration, i.e. list all available sources for a given sink -->
+ <routes>
+ <route type="mix" sink="HDMI Out"
+ sources="primary output,tunnel pcm,direct output,Tuner,mmap_no_irq_out,tunnel direct output"/>
+ <route type="mix" sink="Speaker"
+ sources="primary output,tunnel pcm,direct pcm,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="BT SCO"
+ sources="primary output,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="BT SCO Headset"
+ sources="primary output,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="Wired Headset"
+ sources="primary output,tunnel pcm,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="Wired Headphones"
+ sources="primary output,tunnel pcm,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="primary input"
+ sources="Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic,Tuner"/>
+ <route type="mix" sink="BT A2DP Out"
+ sources="primary output,tunnel a2dp,direct a2dp,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="BT A2DP Headphones"
+ sources="primary output,tunnel a2dp,direct a2dp,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="BT A2DP Speaker"
+ sources="primary output,tunnel a2dp,direct a2dp,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="echo reference"
+ sources="Echo Reference"/>
+ <route type="mix" sink="built-in mic"
+ sources="Built-In Mic"/>
+ <route type="mix" sink="ble_in"
+ sources="BLE-In"/>
+ </routes>
+
+ </module>
+
+ <!-- A2dp Audio HAL -->
+ <!-- <xi:include href="a2dp_audio_policy_configuration.xml"/> -->
+
+ <!-- Usb Audio HAL -->
+ <!-- <xi:include href="usb_audio_policy_configuration.xml"/> -->
+
+ <!-- Remote Submix Audio HAL -->
+ <!-- <xi:include href="r_submix_audio_policy_configuration.xml"/> -->
+
+ <!-- Hearing aid Audio HAL -->
+ <!-- <xi:include href="hearing_aid_audio_policy_configuration.xml"/> -->
+
+ <!-- MSD Audio HAL (optional) -->
+ <!-- <xi:include href="msd_audio_policy_configuration.xml"/> -->
+
+ </modules>
+ <!-- End of Modules section -->
+
+ <!-- Volume section -->
+
+ <!-- <xi:include href="audio_policy_volumes.xml"/> -->
+ <!-- <xi:include href="default_volume_tables.xml"/> -->
+
+ <!-- End of Volume section -->
+
+ <!-- Surround Sound configuration -->
+
+ <surroundSound>
+ <!-- Each of the listed formats gets an entry in Surround Settings dialog on TV devices.
+ There must be a corresponding Java ENCODING_... constant defined in AudioFormat.java,
+ and a display name defined in AudioFormat.toDisplayName. For the formats that don't
+ need a dedicated Surrond Settings dialog entry, a subformats list has to be used. -->
+ <formats>
+ <format name="AUDIO_FORMAT_AC3" />
+ <format name="AUDIO_FORMAT_E_AC3" />
+ <format name="AUDIO_FORMAT_E_AC3_JOC" />
+ <format name="AUDIO_FORMAT_DTS" />
+ </formats>
+ </surroundSound>
+
+ <!-- End of Surround Sound configuration -->
+
+</audioPolicyConfiguration>
diff --git a/audio/core/all-versions/vts/functional/tests/apm_config_b_205808571_6_0.xml b/audio/core/all-versions/vts/functional/tests/apm_config_b_205808571_6_0.xml
new file mode 100644
index 0000000..0f7bf7f
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/tests/apm_config_b_205808571_6_0.xml
@@ -0,0 +1,451 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (c) 2016-2021, The Linux Foundation. All rights reserved
+ Not a Contribution.
+-->
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <!-- version section contains a “version” tag in the form “major.minor” e.g. version=”1.0” -->
+
+ <!-- Global configuration Decalaration -->
+ <globalConfiguration speaker_drc_enabled="true" call_screen_mode_supported="true"/>
+
+
+ <!-- Modules section:
+ There is one section per audio HW module present on the platform.
+ Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”.
+ The module names are the same as in current .conf file:
+ “primary”, “A2DP”, “remote_submix”, “USB”
+ Each module will contain the following sections:
+ “devicePorts”: a list of device descriptors for all input and output devices accessible via this
+ module.
+ This contains both permanently attached devices and removable devices.
+ “mixPorts”: listing all output and input streams exposed by the audio HAL
+ “routes”: list of possible connections between input and output devices or between stream and
+ devices.
+ "route": is defined by an attribute:
+ -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
+ -"sink": the sink involved in this route
+ -"sources": all the sources than can be connected to the sink via vis route
+ “attachedDevices”: permanently attached devices.
+ The attachedDevices section is a list of devices names. The names correspond to device names
+ defined in <devicePorts> section.
+ “defaultOutputDevice”: device to be used by default when no policy rule applies
+ -->
+ <modules>
+ <!-- Primary Audio HAL -->
+ <module name="primary" halVersion="2.0">
+ <attachedDevices>
+ <item>Earpiece</item>
+ <item>Speaker</item>
+ <item>Telephony Tx</item>
+ <item>Built-In Mic</item>
+ <item>Built-In Back Mic</item>
+ <item>FM Tuner</item>
+ <item>Telephony Rx</item>
+ </attachedDevices>
+ <defaultOutputDevice>Speaker</defaultOutputDevice>
+ <mixPorts>
+ <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_FAST|AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="raw" role="source"
+ flags="AUDIO_OUTPUT_FLAG_FAST|AUDIO_OUTPUT_FLAG_RAW">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="haptics output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A"/>
+ </mixPort>
+ <mixPort name="deep_buffer" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="mmap_no_irq_out" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="hifi_playback" role="source" />
+ <mixPort name="compress_passthrough" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+ </mixPort>
+ <mixPort name="direct_pcm" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000,352800,384000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000,352800,384000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000,352800,384000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+ </mixPort>
+ <mixPort name="compressed_offload" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+ <profile name="" format="AUDIO_FORMAT_MP3"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_FLAC"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_ALAC"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_APE"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_LC"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_HE_V1"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_HE_V2"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_DTS"
+ samplingRates="32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_DTS_HD"
+ samplingRates="32000,44100,48000,64000,88200,96000,128000,176400,192000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_WMA"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_WMA_PRO"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_VORBIS"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_ADTS_LC"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_ADTS_HE_V1"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_ADTS_HE_V2"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ </mixPort>
+ <mixPort name="voice_tx" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="voip_rx" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_VOIP_RX">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000,32000,48000" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="incall_music_uplink" role="source"
+ flags="AUDIO_OUTPUT_FLAG_INCALL_MUSIC">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+
+ <mixPort name="primary input" role="sink" maxOpenCount="2" maxActiveCount="2">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </mixPort>
+ <mixPort name="fast input" role="sink"
+ flags="AUDIO_INPUT_FLAG_FAST">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </mixPort>
+ <mixPort name="quad mic" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_INDEX_MASK_4"/>
+ </mixPort>
+ <mixPort name="voip_tx" role="sink"
+ flags="AUDIO_INPUT_FLAG_VOIP_TX">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000,32000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </mixPort>
+ <mixPort name="usb_surround_sound" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,88200,96000,176400,192000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4,AUDIO_CHANNEL_IN_5POINT1,AUDIO_CHANNEL_INDEX_MASK_6,AUDIO_CHANNEL_IN_7POINT1,AUDIO_CHANNEL_INDEX_MASK_8"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,88200,96000,176400,192000"
+ channelMasks="AUDIO_CHANNEL_IN_5POINT1,AUDIO_CHANNEL_INDEX_MASK_6,AUDIO_CHANNEL_IN_7POINT1,AUDIO_CHANNEL_INDEX_MASK_8"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_FLOAT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,88200,96000,176400,192000"
+ channelMasks="AUDIO_CHANNEL_IN_5POINT1,AUDIO_CHANNEL_INDEX_MASK_6,AUDIO_CHANNEL_IN_7POINT1,AUDIO_CHANNEL_INDEX_MASK_8"/>
+ </mixPort>
+ <mixPort name="record_24" role="sink" maxOpenCount="2" maxActiveCount="2">
+ <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,96000,192000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,96000,192000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_FLOAT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,96000,192000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4"/>
+ </mixPort>
+ <mixPort name="voice_rx" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ <mixPort name="mmap_no_irq_in" role="sink" flags="AUDIO_INPUT_FLAG_MMAP_NOIRQ">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3"/>
+ </mixPort>
+ <mixPort name="hifi_input" role="sink" />
+ </mixPorts>
+
+ <devicePorts>
+ <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
+ <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Line" type="AUDIO_DEVICE_OUT_LINE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="HDMI" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,16000,22050,32000,44100,48000,64000,88200,96000,128000,176400,192000"/>
+ </devicePort>
+ <devicePort tagName="Proxy" type="AUDIO_DEVICE_OUT_PROXY" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,16000,22050,32000,44100,48000,64000,88200,96000,128000,176400,192000"/>
+ </devicePort>
+ <devicePort tagName="FM" type="AUDIO_DEVICE_OUT_FM" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink"
+ encodedFormats="AUDIO_FORMAT_SBC AUDIO_FORMAT_AAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_LDAC AUDIO_FORMAT_CELT AUDIO_FORMAT_APTX_ADAPTIVE AUDIO_FORMAT_APTX_TWSP VX_AUDIO_FORMAT_LC3">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink"
+ encodedFormats="AUDIO_FORMAT_SBC AUDIO_FORMAT_AAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_LDAC AUDIO_FORMAT_CELT AUDIO_FORMAT_APTX_ADAPTIVE AUDIO_FORMAT_APTX_TWSP VX_AUDIO_FORMAT_LC3">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink"
+ encodedFormats="AUDIO_FORMAT_SBC AUDIO_FORMAT_AAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_LDAC AUDIO_FORMAT_CELT AUDIO_FORMAT_APTX_ADAPTIVE AUDIO_FORMAT_APTX_TWSP VX_AUDIO_FORMAT_LC3">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="USB Device Out" type="AUDIO_DEVICE_OUT_USB_DEVICE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100,48000,64000,88200,96000,128000,176400,192000"/>
+ </devicePort>
+ <devicePort tagName="USB Headset Out" type="AUDIO_DEVICE_OUT_USB_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100,48000,64000,88200,96000,128000,176400,192000"/>
+ </devicePort>
+
+ <!-- Input devices declaration, i.e. Source DEVICE PORT -->
+ <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="FM Tuner" type="AUDIO_DEVICE_IN_FM_TUNER" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ <devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ <devicePort tagName="USB Device In" type="AUDIO_DEVICE_IN_USB_DEVICE" role="source">
+ </devicePort>
+ <devicePort tagName="USB Headset In" type="AUDIO_DEVICE_IN_USB_HEADSET" role="source">
+ </devicePort>
+ <devicePort tagName="A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source"
+ encodedFormats="VX_AUDIO_FORMAT_LC3">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+ </devicePort>
+
+ </devicePorts>
+ <!-- route declaration, i.e. list all available sources for a given sink -->
+ <routes>
+ <route type="mix" sink="Earpiece"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+ <route type="mix" sink="Speaker"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+ <route type="mix" sink="Wired Headset"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+ <route type="mix" sink="Wired Headphones"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+ <route type="mix" sink="Line"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+ <route type="mix" sink="HDMI"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,compress_passthrough,voip_rx,haptics output"/>
+ <route type="mix" sink="Proxy"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,haptics output"/>
+ <route type="mix" sink="FM"
+ sources="primary output"/>
+ <route type="mix" sink="BT SCO"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+ <route type="mix" sink="BT SCO Headset"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+ <route type="mix" sink="BT SCO Car Kit"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+ <route type="mix" sink="USB Device Out"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,hifi_playback,haptics output"/>
+ <route type="mix" sink="USB Headset Out"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,hifi_playback,haptics output"/>
+ <route type="mix" sink="Telephony Tx"
+ sources="voice_tx,incall_music_uplink"/>
+ <route type="mix" sink="voice_rx"
+ sources="Telephony Rx"/>
+ <route type="mix" sink="primary input"
+ sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic,FM Tuner,Telephony Rx,A2DP In"/>
+ <route type="mix" sink="usb_surround_sound"
+ sources="USB Device In,USB Headset In"/>
+ <route type="mix" sink="fast input"
+ sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,Wired Headset Mic"/>
+ <route type="mix" sink="quad mic"
+ sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,Wired Headset Mic"/>
+ <route type="mix" sink="voip_tx"
+ sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,USB Device In,USB Headset In,Wired Headset Mic"/>
+ <route type="mix" sink="record_24"
+ sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,A2DP In"/>
+ <route type="mix" sink="mmap_no_irq_in"
+ sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,USB Device In,USB Headset In"/>
+ <route type="mix" sink="BT A2DP Out"
+ sources="primary output,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+ <route type="mix" sink="BT A2DP Headphones"
+ sources="primary output,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+ <route type="mix" sink="BT A2DP Speaker"
+ sources="primary output,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+ <route type="mix" sink="hifi_input" sources="USB Device In,USB Headset In" />
+ </routes>
+
+ </module>
+
+ <!-- A2DP Audio HAL -->
+ <module name="a2dp" halVersion="2.0">
+ <mixPorts>
+ <mixPort name="a2dp input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ </mixPorts>
+
+ <devicePorts>
+ <devicePort tagName="BT A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+ </devicePort>
+ </devicePorts>
+
+ <routes>
+ <route type="mix" sink="a2dp input"
+ sources="BT A2DP In"/>
+ </routes>
+ </module>
+
+ <!-- Usb Audio HAL -->
+ <module name="usb" halVersion="2.0">
+ <mixPorts>
+ <mixPort name="usb_accessory output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="USB Host Out" type="AUDIO_DEVICE_OUT_USB_ACCESSORY" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="USB Host Out"
+ sources="usb_accessory output"/>
+ </routes>
+ </module>
+
+ <!-- Remote Submix Audio HAL -->
+ <!-- <xi:include href="/vendor/etc/r_submix_audio_policy_configuration.xml"/> -->
+
+ <!-- Bluetooth Audio HAL for hearing aid -->
+ <!-- <xi:include href="/vendor/etc/bluetooth_qti_hearing_aid_audio_policy_configuration.xml"/> -->
+
+ </modules>
+ <!-- End of Modules section -->
+
+ <!-- Volume section -->
+
+ <!-- <xi:include href="/vendor/etc/audio_policy_volumes.xml"/> -->
+ <!-- <xi:include href="/vendor/etc/default_volume_tables.xml"/> -->
+
+ <!-- End of Volume section -->
+
+</audioPolicyConfiguration>
diff --git a/audio/core/all-versions/vts/functional/tests/apm_config_b_205808571_7_0.xml b/audio/core/all-versions/vts/functional/tests/apm_config_b_205808571_7_0.xml
new file mode 100644
index 0000000..16427b6
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/tests/apm_config_b_205808571_7_0.xml
@@ -0,0 +1,446 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (c) 2016-2021, The Linux Foundation. All rights reserved
+ Not a Contribution.
+-->
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<audioPolicyConfiguration version="7.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <!-- version section contains a “version” tag in the form “major.minor” e.g. version=”1.0” -->
+
+ <!-- Global configuration Decalaration -->
+ <globalConfiguration speaker_drc_enabled="true" call_screen_mode_supported="true"/>
+
+
+ <!-- Modules section:
+ There is one section per audio HW module present on the platform.
+ Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”.
+ The module names are the same as in current .conf file:
+ “primary”, “A2DP”, “remote_submix”, “USB”
+ Each module will contain the following sections:
+ “devicePorts”: a list of device descriptors for all input and output devices accessible via this
+ module.
+ This contains both permanently attached devices and removable devices.
+ “mixPorts”: listing all output and input streams exposed by the audio HAL
+ “routes”: list of possible connections between input and output devices or between stream and
+ devices.
+ "route": is defined by an attribute:
+ -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
+ -"sink": the sink involved in this route
+ -"sources": all the sources than can be connected to the sink via vis route
+ “attachedDevices”: permanently attached devices.
+ The attachedDevices section is a list of devices names. The names correspond to device names
+ defined in <devicePorts> section.
+ “defaultOutputDevice”: device to be used by default when no policy rule applies
+ -->
+ <modules>
+ <!-- Primary Audio HAL -->
+ <module name="primary" halVersion="2.0">
+ <attachedDevices>
+ <item>Earpiece</item>
+ <item>Speaker</item>
+ <item>Telephony Tx</item>
+ <item>Built-In Mic</item>
+ <item>Built-In Back Mic</item>
+ <item>FM Tuner</item>
+ <item>Telephony Rx</item>
+ </attachedDevices>
+ <defaultOutputDevice>Speaker</defaultOutputDevice>
+ <mixPorts>
+ <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_FAST AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="raw" role="source"
+ flags="AUDIO_OUTPUT_FLAG_FAST AUDIO_OUTPUT_FLAG_RAW">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="haptics output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A"/>
+ </mixPort>
+ <mixPort name="deep_buffer" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="mmap_no_irq_out" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="hifi_playback" role="source" />
+ <mixPort name="compress_passthrough" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+ </mixPort>
+ <mixPort name="direct_pcm" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000 352800 384000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000 352800 384000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000 352800 384000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+ </mixPort>
+ <mixPort name="compressed_offload" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+ <profile name="" format="AUDIO_FORMAT_MP3"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_FLAC"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_ALAC"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_APE"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_LC"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_HE_V1"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_HE_V2"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_DTS"
+ samplingRates="32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_DTS_HD"
+ samplingRates="32000 44100 48000 64000 88200 96000 128000 176400 192000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_WMA"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_WMA_PRO"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_VORBIS"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_ADTS_LC"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_ADTS_HE_V1"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_ADTS_HE_V2"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+ </mixPort>
+ <mixPort name="voice_tx" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000 48000" channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="voip_rx" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_VOIP_RX">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="incall_music_uplink" role="source"
+ flags="AUDIO_OUTPUT_FLAG_INCALL_MUSIC">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000 48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+
+ <mixPort name="primary input" role="sink" maxOpenCount="2" maxActiveCount="2">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </mixPort>
+ <mixPort name="fast input" role="sink"
+ flags="AUDIO_INPUT_FLAG_FAST">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </mixPort>
+ <mixPort name="quad mic" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_INDEX_MASK_4"/>
+ </mixPort>
+ <mixPort name="voip_tx" role="sink"
+ flags="AUDIO_INPUT_FLAG_VOIP_TX">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </mixPort>
+ <mixPort name="usb_surround_sound" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 88200 96000 176400 192000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK AUDIO_CHANNEL_INDEX_MASK_3 AUDIO_CHANNEL_INDEX_MASK_4 AUDIO_CHANNEL_IN_5POINT1 AUDIO_CHANNEL_INDEX_MASK_6"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 88200 96000 176400 192000"
+ channelMasks="AUDIO_CHANNEL_IN_5POINT1 AUDIO_CHANNEL_INDEX_MASK_6"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_FLOAT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 88200 96000 176400 192000"
+ channelMasks="AUDIO_CHANNEL_IN_5POINT1 AUDIO_CHANNEL_INDEX_MASK_6"/>
+ </mixPort>
+ <mixPort name="record_24" role="sink" maxOpenCount="2" maxActiveCount="2">
+ <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 96000 192000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK AUDIO_CHANNEL_INDEX_MASK_3 AUDIO_CHANNEL_INDEX_MASK_4"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 96000 192000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK AUDIO_CHANNEL_INDEX_MASK_3 AUDIO_CHANNEL_INDEX_MASK_4"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_FLOAT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 96000 192000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK AUDIO_CHANNEL_INDEX_MASK_3 AUDIO_CHANNEL_INDEX_MASK_4"/>
+ </mixPort>
+ <mixPort name="voice_rx" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ <mixPort name="mmap_no_irq_in" role="sink" flags="AUDIO_INPUT_FLAG_MMAP_NOIRQ">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK AUDIO_CHANNEL_INDEX_MASK_3"/>
+ </mixPort>
+ <mixPort name="hifi_input" role="sink" />
+ </mixPorts>
+
+ <devicePorts>
+ <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
+ <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Line" type="AUDIO_DEVICE_OUT_LINE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="HDMI" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 16000 22050 32000 44100 48000 64000 88200 96000 128000 176400 192000"/>
+ </devicePort>
+ <devicePort tagName="Proxy" type="AUDIO_DEVICE_OUT_PROXY" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 16000 22050 32000 44100 48000 64000 88200 96000 128000 176400 192000"/>
+ </devicePort>
+ <devicePort tagName="FM" type="AUDIO_DEVICE_OUT_FM" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink"
+ encodedFormats="AUDIO_FORMAT_SBC AUDIO_FORMAT_AAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_LDAC AUDIO_FORMAT_CELT AUDIO_FORMAT_APTX_ADAPTIVE AUDIO_FORMAT_APTX_TWSP VX_AUDIO_FORMAT_LC3">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink"
+ encodedFormats="AUDIO_FORMAT_SBC AUDIO_FORMAT_AAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_LDAC AUDIO_FORMAT_CELT AUDIO_FORMAT_APTX_ADAPTIVE AUDIO_FORMAT_APTX_TWSP VX_AUDIO_FORMAT_LC3">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink"
+ encodedFormats="AUDIO_FORMAT_SBC AUDIO_FORMAT_AAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_LDAC AUDIO_FORMAT_CELT AUDIO_FORMAT_APTX_ADAPTIVE AUDIO_FORMAT_APTX_TWSP VX_AUDIO_FORMAT_LC3">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="USB Device Out" type="AUDIO_DEVICE_OUT_USB_DEVICE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100 48000 64000 88200 96000 128000 176400 192000"/>
+ </devicePort>
+ <devicePort tagName="USB Headset Out" type="AUDIO_DEVICE_OUT_USB_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100 48000 64000 88200 96000 128000 176400 192000"/>
+ </devicePort>
+
+ <!-- Input devices declaration, i.e. Source DEVICE PORT -->
+ <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="FM Tuner" type="AUDIO_DEVICE_IN_FM_TUNER" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ <devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000 48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ <devicePort tagName="USB Device In" type="AUDIO_DEVICE_IN_USB_DEVICE" role="source">
+ </devicePort>
+ <devicePort tagName="USB Headset In" type="AUDIO_DEVICE_IN_USB_HEADSET" role="source">
+ </devicePort>
+ <devicePort tagName="A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source"
+ encodedFormats="VX_AUDIO_FORMAT_LC3">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+ </devicePort>
+
+ </devicePorts>
+ <!-- route declaration, i.e. list all available sources for a given sink -->
+ <routes>
+ <route type="mix" sink="Earpiece"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+ <route type="mix" sink="Speaker"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+ <route type="mix" sink="Wired Headset"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+ <route type="mix" sink="Wired Headphones"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+ <route type="mix" sink="Line"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+ <route type="mix" sink="HDMI"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,compress_passthrough,voip_rx,haptics output"/>
+ <route type="mix" sink="Proxy"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,haptics output"/>
+ <route type="mix" sink="FM"
+ sources="primary output"/>
+ <route type="mix" sink="BT SCO"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+ <route type="mix" sink="BT SCO Headset"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+ <route type="mix" sink="BT SCO Car Kit"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+ <route type="mix" sink="USB Device Out"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,hifi_playback,haptics output"/>
+ <route type="mix" sink="USB Headset Out"
+ sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,hifi_playback,haptics output"/>
+ <route type="mix" sink="Telephony Tx"
+ sources="voice_tx,incall_music_uplink"/>
+ <route type="mix" sink="voice_rx"
+ sources="Telephony Rx"/>
+ <route type="mix" sink="primary input"
+ sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic,FM Tuner,Telephony Rx,A2DP In"/>
+ <route type="mix" sink="usb_surround_sound"
+ sources="USB Device In,USB Headset In"/>
+ <route type="mix" sink="fast input"
+ sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,Wired Headset Mic"/>
+ <route type="mix" sink="quad mic"
+ sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,Wired Headset Mic"/>
+ <route type="mix" sink="voip_tx"
+ sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,USB Device In,USB Headset In,Wired Headset Mic"/>
+ <route type="mix" sink="record_24"
+ sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,A2DP In"/>
+ <route type="mix" sink="mmap_no_irq_in"
+ sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,USB Device In,USB Headset In"/>
+ <route type="mix" sink="BT A2DP Out"
+ sources="primary output,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+ <route type="mix" sink="BT A2DP Headphones"
+ sources="primary output,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+ <route type="mix" sink="BT A2DP Speaker"
+ sources="primary output,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+ <route type="mix" sink="hifi_input" sources="USB Device In,USB Headset In" />
+ </routes>
+
+ </module>
+
+ <!-- A2DP Audio HAL -->
+ <module name="a2dp" halVersion="2.0">
+ <mixPorts>
+ <mixPort name="a2dp input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ </mixPorts>
+
+ <devicePorts>
+ <devicePort tagName="BT A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+ </devicePort>
+ </devicePorts>
+
+ <routes>
+ <route type="mix" sink="a2dp input"
+ sources="BT A2DP In"/>
+ </routes>
+ </module>
+
+ <!-- Usb Audio HAL -->
+ <module name="usb" halVersion="2.0">
+ <mixPorts>
+ <mixPort name="usb_accessory output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="USB Host Out" type="AUDIO_DEVICE_OUT_USB_ACCESSORY" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="USB Host Out"
+ sources="usb_accessory output"/>
+ </routes>
+ </module>
+
+ <!-- Remote Submix Audio HAL -->
+
+ <!-- Bluetooth Audio HAL for hearing aid -->
+
+ </modules>
+ <!-- End of Modules section -->
+
+ <!-- Volume section -->
+
+ <!-- End of Volume section -->
+
+</audioPolicyConfiguration>
diff --git a/audio/core/all-versions/vts/functional/tests/generators_tests.cpp b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
index 583ff01..3fdd8e6 100644
--- a/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
+++ b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
@@ -128,5 +128,46 @@
}
// Target file names are the same for all versions, see 'HalAudioVx_0GeneratorTest.xml' test configs
+// clang-format off
INSTANTIATE_TEST_SUITE_P(Generators, GeneratorsTest,
- ::testing::Values("apm_config_no_vx.xml", "apm_config_with_vx.xml"));
+ ::testing::Values("apm_config_no_vx.xml", "apm_config_with_vx.xml"
+#if MAJOR_VERSION == 6
+ , "apm_config_b_205808571_6_0.xml"
+#elif MAJOR_VERSION == 7
+ , "apm_config_b_204314749_7_0.xml"
+ , "apm_config_b_205808571_7_0.xml"
+#endif
+ ));
+// clang-format on
+
+TEST(GeneratorsDeviceTest, AttachedDevicesOnly) {
+ static const std::string kTestFile =
+ "apm_config_b_205808571_" STRINGIFY(MAJOR_VERSION) "_0.xml";
+ ASSERT_TRUE(PolicyConfigManager::getInstance().init(kDataDir, kTestFile));
+ EXPECT_NE(nullptr, getCachedPolicyConfig().getPrimaryModule());
+ const auto allInConfigs = generateInputDeviceConfigParameters(false /*oneProfilePerDevice*/);
+ EXPECT_FALSE(allInConfigs.empty());
+ for (const auto& configParam : allInConfigs) {
+ const AudioConfig& config = std::get<PARAM_CONFIG>(configParam);
+ // The config contains multichannel masks for mixPort connected to
+ // input devicePorts that are not attached. These multichannel masks must
+ // not appear among generated masks.
+ const uint32_t channelCount =
+#if MAJOR_VERSION == 6
+ audio_channel_count_from_in_mask(
+ static_cast<audio_channel_mask_t>(config.channelMask));
+#elif MAJOR_VERSION == 7
+ xsd::getChannelCount(config.base.channelMask);
+#endif
+ EXPECT_TRUE(channelCount <= 4) << "Unexpected channel count: " << channelCount << " " <<
+#if MAJOR_VERSION == 6
+ ::testing::PrintToString(config.format) << ", "
+ << ::testing::PrintToString(config.sampleRateHz) << ", "
+ << ::testing::PrintToString(config.channelMask);
+#elif MAJOR_VERSION == 7
+ ::testing::PrintToString(config.base.format) << ", "
+ << ::testing::PrintToString(config.base.sampleRateHz) << ", "
+ << ::testing::PrintToString(config.base.channelMask);
+#endif
+ }
+}
diff --git a/automotive/can/1.0/default/Android.bp b/automotive/can/1.0/default/Android.bp
index c0c17e2..163fdb7 100644
--- a/automotive/can/1.0/default/Android.bp
+++ b/automotive/can/1.0/default/Android.bp
@@ -64,4 +64,5 @@
"android.hardware.automotive@libc++fs",
"libnl++",
],
+ vintf_fragments: ["manifest_android.hardware.automotive.can@1.0.xml"],
}
diff --git a/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml b/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml
new file mode 100644
index 0000000..2078ce5
--- /dev/null
+++ b/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<manifest version="1.0" type="device" >
+ <hal format="hidl">
+ <name>android.hardware.automotive.can</name>
+ <transport>hwbinder</transport>
+ <fqname>@1.0::ICanController/socketcan</fqname>
+ </hal>
+</manifest>
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 8cc1882..1216d36 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -79,19 +79,24 @@
using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
using IEvsDisplay_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsDisplay;
+namespace {
+
/*
* Plese note that this is different from what is defined in
* libhardware/modules/camera/3_4/metadata/types.h; this has one additional
* field to store a framerate.
*/
-const size_t kStreamCfgSz = 5;
typedef struct {
+ int32_t id;
int32_t width;
int32_t height;
int32_t format;
int32_t direction;
int32_t framerate;
} RawStreamConfig;
+constexpr const size_t kStreamCfgSz = sizeof(RawStreamConfig) / sizeof(int32_t);
+
+} // anonymous namespace
// The main test class for EVS
@@ -236,6 +241,28 @@
return physicalCameras;
}
+ Stream getFirstStreamConfiguration(camera_metadata_t* metadata) {
+ Stream targetCfg = {};
+ camera_metadata_entry_t streamCfgs;
+ if (!find_camera_metadata_entry(metadata,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ &streamCfgs)) {
+ // Stream configurations are found in metadata
+ RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
+ for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
+ if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+ ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+ targetCfg.width = ptr->width;
+ targetCfg.height = ptr->height;
+ targetCfg.format = static_cast<PixelFormat>(ptr->format);
+ break;
+ }
+ ++ptr;
+ }
+ }
+
+ return targetCfg;
+ }
sp<IEvsEnumerator> pEnumerator; // Every test needs access to the service
std::vector<CameraDesc> cameraInfo; // Empty unless/until loadCameraList() is called
@@ -265,10 +292,6 @@
// Get the camera list
loadCameraList();
- // Using null stream configuration makes EVS uses the default resolution and
- // output format.
- Stream nullCfg = {};
-
// Open and close each camera twice
for (auto&& cam: cameraInfo) {
bool isLogicalCam = false;
@@ -278,8 +301,14 @@
continue;
}
+ // Read a target resolution from the metadata
+ Stream targetCfg =
+ getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
for (int pass = 0; pass < 2; pass++) {
- sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg);
+ sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam, nullptr);
for (auto&& devName : devices) {
@@ -343,10 +372,6 @@
// Get the camera list
loadCameraList();
- // Using null stream configuration makes EVS uses the default resolution and
- // output format.
- Stream nullCfg = {};
-
// Open and close each camera twice
for (auto&& cam: cameraInfo) {
bool isLogicalCam = false;
@@ -356,10 +381,14 @@
continue;
}
+ // Read a target resolution from the metadata
+ Stream targetCfg =
+ getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
activeCameras.clear();
- sp<IEvsCamera_1_1> pCam =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam, nullptr);
// Store a camera handle for a clean-up
@@ -372,9 +401,7 @@
}
);
- sp<IEvsCamera_1_1> pCam2 =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCam2 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam2, nullptr);
// Store a camera handle for a clean-up
@@ -422,10 +449,6 @@
// Get the camera list
loadCameraList();
- // Using null stream configuration makes EVS uses the default resolution and
- // output format.
- Stream nullCfg = {};
-
// Test each reported camera
for (auto&& cam: cameraInfo) {
bool isLogicalCam = false;
@@ -435,9 +458,13 @@
continue;
}
- sp<IEvsCamera_1_1> pCam =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ // Read a target resolution from the metadata
+ Stream targetCfg =
+ getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam, nullptr);
// Store a camera handle for a clean-up
@@ -519,10 +546,6 @@
// Get the camera list
loadCameraList();
- // Using null stream configuration makes EVS uses the default resolution and
- // output format.
- Stream nullCfg = {};
-
// Test each reported camera
for (auto&& cam: cameraInfo) {
bool isLogicalCam = false;
@@ -532,9 +555,13 @@
continue;
}
- sp<IEvsCamera_1_1> pCam =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ // Read a target resolution from the metadata
+ Stream targetCfg =
+ getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam, nullptr);
// Store a camera handle for a clean-up
@@ -601,10 +628,6 @@
// Get the camera list
loadCameraList();
- // Using null stream configuration makes EVS uses the default resolution and
- // output format.
- Stream nullCfg = {};
-
// Request available display IDs
uint8_t targetDisplayId = 0;
pEnumerator->getDisplayIdList([&targetDisplayId](auto ids) {
@@ -642,9 +665,13 @@
continue;
}
- sp<IEvsCamera_1_1> pCam =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ // Read a target resolution from the metadata
+ Stream targetCfg =
+ getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
+ sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam, nullptr);
// Store a camera handle for a clean-up
@@ -708,24 +735,22 @@
// Get the camera list
loadCameraList();
- // Using null stream configuration makes EVS uses the default resolution and
- // output format.
- Stream nullCfg = {};
-
// Test each reported camera
for (auto&& cam: cameraInfo) {
+ // Read a target resolution from the metadata
+ Stream targetCfg =
+ getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
// Create two camera clients.
- sp<IEvsCamera_1_1> pCam0 =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam0, nullptr);
// Store a camera handle for a clean-up
activeCameras.push_back(pCam0);
- sp<IEvsCamera_1_1> pCam1 =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam1, nullptr);
// Store a camera handle for a clean-up
@@ -812,10 +837,6 @@
// Get the camera list
loadCameraList();
- // Using null stream configuration makes EVS uses the default resolution and
- // output format.
- Stream nullCfg = {};
-
// Test each reported camera
Return<EvsResult> result = EvsResult::OK;
for (auto&& cam: cameraInfo) {
@@ -828,10 +849,14 @@
continue;
}
+ // Read a target resolution from the metadata
+ Stream targetCfg =
+ getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
// Create a camera client
- sp<IEvsCamera_1_1> pCam =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam, nullptr);
// Store a camera
@@ -961,10 +986,6 @@
// Get the camera list
loadCameraList();
- // Using null stream configuration makes EVS uses the default resolution and
- // output format.
- Stream nullCfg = {};
-
// Test each reported camera
for (auto&& cam: cameraInfo) {
bool isLogicalCam = false;
@@ -976,18 +997,20 @@
continue;
}
+ // Read a target resolution from the metadata
+ Stream targetCfg =
+ getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
// Create two camera clients.
- sp<IEvsCamera_1_1> pCamPrimary =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCamPrimary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCamPrimary, nullptr);
// Store a camera handle for a clean-up
activeCameras.push_back(pCamPrimary);
- sp<IEvsCamera_1_1> pCamSecondary =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCamSecondary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCamSecondary, nullptr);
// Store a camera handle for a clean-up
@@ -1142,10 +1165,6 @@
// Get the camera list
loadCameraList();
- // Using null stream configuration makes EVS uses the default resolution and
- // output format.
- Stream nullCfg = {};
-
// Test each reported camera
for (auto&& cam: cameraInfo) {
bool isLogicalCam = false;
@@ -1157,18 +1176,20 @@
continue;
}
+ // Read a target resolution from the metadata
+ Stream targetCfg =
+ getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
// Create two camera clients.
- sp<IEvsCamera_1_1> pCamPrimary =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCamPrimary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCamPrimary, nullptr);
// Store a camera handle for a clean-up
activeCameras.push_back(pCamPrimary);
- sp<IEvsCamera_1_1> pCamSecondary =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCamSecondary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCamSecondary, nullptr);
// Store a camera handle for a clean-up
@@ -1615,28 +1636,26 @@
// Get the camera list
loadCameraList();
- // Using null stream configuration makes EVS uses the default resolution and
- // output format.
- Stream nullCfg = {};
-
// Request exclusive access to the EVS display
sp<IEvsDisplay_1_0> pDisplay = pEnumerator->openDisplay();
ASSERT_NE(pDisplay, nullptr);
// Test each reported camera
for (auto&& cam: cameraInfo) {
+ // Read a target resolution from the metadata
+ Stream targetCfg =
+ getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
+
// Create two clients
- sp<IEvsCamera_1_1> pCam0 =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam0, nullptr);
// Store a camera handle for a clean-up
activeCameras.push_back(pCam0);
- sp<IEvsCamera_1_1> pCam1 =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam1, nullptr);
// Store a camera handle for a clean-up
@@ -2001,7 +2020,7 @@
&streamCfgs)) {
// Stream configurations are found in metadata
RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
- for (unsigned idx = 0; idx < streamCfgs.count; idx += kStreamCfgSz) {
+ for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
@@ -2026,9 +2045,7 @@
continue;
}
- sp<IEvsCamera_1_1> pCam =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam, nullptr);
// Store a camera handle for a clean-up
@@ -2106,7 +2123,7 @@
&streamCfgs)) {
// Stream configurations are found in metadata
RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
- for (unsigned idx = 0; idx < streamCfgs.count; idx += kStreamCfgSz) {
+ for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
@@ -2132,9 +2149,7 @@
}
// Create the first camera client with a selected stream configuration.
- sp<IEvsCamera_1_1> pCam0 =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam0, nullptr);
// Store a camera handle for a clean-up
@@ -2144,9 +2159,7 @@
// configuration.
int32_t id = targetCfg.id;
targetCfg.id += 1; // EVS manager sees only the stream id.
- sp<IEvsCamera_1_1> pCam1 =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_EQ(pCam1, nullptr);
// Store a camera handle for a clean-up
@@ -2154,9 +2167,7 @@
// Try again with same stream configuration.
targetCfg.id = id;
- pCam1 =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
- .withDefault(nullptr);
+ pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam1, nullptr);
// Set up per-client frame receiver objects which will fire up its own thread
@@ -2258,52 +2269,23 @@
LOG(INFO) << "Starting CameraStreamExternalBuffering test";
// Arbitrary constant (should be > 1 and not too big)
- static const unsigned int kBuffersToHold = 6;
+ static const unsigned int kBuffersToHold = 3;
// Get the camera list
loadCameraList();
- // Using null stream configuration makes EVS uses the default resolution and
- // output format.
- Stream nullCfg = {};
-
// Acquire the graphics buffer allocator
android::GraphicBufferAllocator& alloc(android::GraphicBufferAllocator::get());
const auto usage =
GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
- const auto format = HAL_PIXEL_FORMAT_RGBA_8888;
- uint32_t width = 640;
- uint32_t height = 360;
- camera_metadata_entry_t streamCfgs;
// Test each reported camera
for (auto&& cam : cameraInfo) {
- bool foundCfg = false;
- if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()),
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
- &streamCfgs)) {
- // Stream configurations are found in metadata
- RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
-
- LOG(DEBUG) << __LINE__ << " start searching " << streamCfgs.count;
- for (unsigned idx = 0; idx < streamCfgs.count; idx++) {
- LOG(DEBUG) << "ptr->direction= " << ptr->direction
- << " ptr->format= " << ptr->format;
- if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
- ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
- width = ptr->width;
- height = ptr->height;
- foundCfg = true;
- // Always use the 1st available configuration
- break;
- }
- ++ptr;
- }
- }
-
- if (!foundCfg) {
- LOG(INFO) << "No configuration found. Use default stream configurations.";
- }
+ // Read a target resolution from the metadata
+ Stream targetCfg =
+ getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+ ASSERT_GT(targetCfg.width, 0);
+ ASSERT_GT(targetCfg.height, 0);
// Allocate buffers to use
hidl_vec<BufferDesc> buffers;
@@ -2312,8 +2294,11 @@
unsigned pixelsPerLine;
buffer_handle_t memHandle = nullptr;
android::status_t result =
- alloc.allocate(width, height, format, 1, usage, &memHandle, &pixelsPerLine, 0,
- "CameraStreamExternalBufferingTest");
+ alloc.allocate(targetCfg.width, targetCfg.height,
+ (android::PixelFormat)targetCfg.format,
+ /* layerCount = */ 1, usage, &memHandle, &pixelsPerLine,
+ /* graphicBufferId = */ 0,
+ /* requestorName = */ "CameraStreamExternalBufferingTest");
if (result != android::NO_ERROR) {
LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
// Release previous allocated buffers
@@ -2325,10 +2310,10 @@
BufferDesc buf;
AHardwareBuffer_Desc* pDesc =
reinterpret_cast<AHardwareBuffer_Desc*>(&buf.buffer.description);
- pDesc->width = width;
- pDesc->height = height;
+ pDesc->width = targetCfg.width;
+ pDesc->height = targetCfg.height;
pDesc->layers = 1;
- pDesc->format = format;
+ pDesc->format = static_cast<uint32_t>(targetCfg.format);
pDesc->usage = usage;
pDesc->stride = pixelsPerLine;
buf.buffer.nativeHandle = memHandle;
@@ -2340,9 +2325,7 @@
bool isLogicalCam = false;
getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);
- sp<IEvsCamera_1_1> pCam =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
ASSERT_NE(pCam, nullptr);
// Store a camera handle for a clean-up
@@ -2362,7 +2345,7 @@
}
EXPECT_EQ(result, EvsResult::OK);
- EXPECT_GE(delta, 0);
+ EXPECT_GE(delta, kBuffersToHold);
// Set up a frame receiver object which will fire up its own thread.
sp<FrameHandler> frameHandler = new FrameHandler(pCam, cam,
@@ -2378,7 +2361,7 @@
sleep(1); // 1 second should be enough for at least 5 frames to be delivered worst case
unsigned framesReceived = 0;
frameHandler->getFramesCounters(&framesReceived, nullptr);
- ASSERT_EQ(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
+ ASSERT_LE(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
// Give back one buffer
@@ -2387,9 +2370,10 @@
// Once we return a buffer, it shouldn't take more than 1/10 second to get a new one
// filled since we require 10fps minimum -- but give a 10% allowance just in case.
+ unsigned framesReceivedAfter = 0;
usleep(110 * kMillisecondsToMicroseconds);
- frameHandler->getFramesCounters(&framesReceived, nullptr);
- EXPECT_EQ(kBuffersToHold+1, framesReceived) << "Stream should've resumed";
+ frameHandler->getFramesCounters(&framesReceivedAfter, nullptr);
+ EXPECT_EQ(framesReceived + 1, framesReceivedAfter) << "Stream should've resumed";
// Even when the camera pointer goes out of scope, the FrameHandler object will
// keep the stream alive unless we tell it to shutdown.
diff --git a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
index 583a455..58423c8 100644
--- a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
+++ b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <fuzzer/FuzzedDataProvider.h>
#include <cmath>
#include <cstdlib>
#include <cstring>
@@ -21,36 +22,43 @@
#include "FormatConvert.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, std::size_t size) {
- if (size < 256) {
+ // 1 random value (4bytes) + min imagesize = 16*2 times bytes per pixel (worse case 2)
+ if (size < (4 + 16 * 2 * 2)) {
return 0;
}
+ FuzzedDataProvider fdp(data, size);
+ std::size_t image_pixel_size = size - 4;
+ image_pixel_size = (image_pixel_size & INT_MAX) / 2;
- std::srand(std::time(nullptr)); // use current time as seed for random generator
- int random_variable = std::rand() % 10;
- int width = (int)sqrt(size);
- int height = width * ((float)random_variable / 10.0);
+ // API have a requirement that width must be divied by 16 except yuyvtorgb
+ int min_height = 2;
+ int max_height = (image_pixel_size / 16) & ~(1); // must be even number
+ int height = fdp.ConsumeIntegralInRange<uint32_t>(min_height, max_height);
+ int width = (image_pixel_size / height) & ~(16); // must be divisible by 16
- uint8_t* src = (uint8_t*)malloc(sizeof(uint8_t) * size);
- memcpy(src, data, sizeof(uint8_t) * (size));
- uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * size);
+ uint8_t* src = (uint8_t*)(data + 4);
+ uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * image_pixel_size);
#ifdef COPY_NV21_TO_RGB32
- android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt, 0);
+ android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt,
+ width);
#elif COPY_NV21_TO_BGR32
- android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt, 0);
+ android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt,
+ width);
#elif COPY_YV12_TO_RGB32
- android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt, 0);
+ android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt,
+ width);
#elif COPY_YV12_TO_BGR32
- android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt, 0);
+ android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt,
+ width);
#elif COPY_YUYV_TO_RGB32
- android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, 0, tgt,
- 0);
+ android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, width,
+ tgt, width);
#elif COPY_YUYV_TO_BGR32
- android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, 0, tgt,
- 0);
+ android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, width,
+ tgt, width);
#endif
- free(src);
free(tgt);
return 0;
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index ffa0c13..0b49ef9 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -182,6 +182,7 @@
],
shared_libs: [
"libbase",
+ "libcutils",
],
header_libs: ["libbase_headers"],
test_suites: ["general-tests"],
diff --git a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
index c8c89dc..44f9134 100644
--- a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
+++ b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
@@ -1,4 +1,4 @@
service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
- class hal
+ class early_hal
user vehicle_network
group system inet
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
index fcfe761..6706258 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
@@ -76,6 +76,9 @@
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
private:
+ // Set unit test class as friend class to test private functions.
+ friend class VehicleHalManagerTestHelper;
+
using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr;
// Returns true if needs to call again shortly.
using RetriableAction = std::function<bool()>;
@@ -105,14 +108,20 @@
void cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId);
void cmdDumpOneProperty(int fd, int rowNumber, const VehiclePropConfig& config);
+ bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);
+
static bool checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options, size_t minSize);
static bool checkCallerHasWritePermissions(int fd);
- static bool safelyParseInt(int fd, int index, std::string s, int* out);
+ template <typename T>
+ static bool safelyParseInt(int fd, int index, const std::string& s, T* out);
+ static bool safelyParseFloat(int fd, int index, const std::string& s, float* out);
+ // Parses "s" as a hex string and populate "*bytes". The hex string must be in the format of
+ // valid hex format, e.g. "0xABCD".
+ static bool parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes);
void cmdHelp(int fd) const;
void cmdListAllProperties(int fd) const;
void cmdDumpAllProperties(int fd);
void cmdDumpSpecificProperties(int fd, const hidl_vec<hidl_string>& options);
- void cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);
static bool isSubscribable(const VehiclePropConfig& config,
SubscribeFlags flags);
@@ -120,7 +129,18 @@
static float checkSampleRate(const VehiclePropConfig& config,
float sampleRate);
static ClientId getClientId(const sp<IVehicleCallback>& callback);
-private:
+
+ // Parses the cmdline options for "--set" command. "*prop" would be populated with the
+ // the properties to be set. Returns true when the cmdline options are valid, false otherwise.
+ static bool parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
+ VehiclePropValue* prop);
+ // Parses the options and get the values for the current option specified by "*index". "*index"
+ // would advance to the next option field (e.g., the next "-f"). Returns a list of values for
+ // the current option.
+ static std::vector<std::string> getOptionValues(const hidl_vec<hidl_string>& options,
+ size_t* index);
+
+ private:
VehicleHal* mHal;
std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;
SubscriptionManager mSubscriptionManager;
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index dc5d3d3..e34e692 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -20,7 +20,9 @@
#include <cmath>
#include <fstream>
+#include <unordered_set>
+#include <android-base/parsedouble.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android/hardware/automotive/vehicle/2.0/BpHwVehicleCallback.h>
@@ -44,15 +46,34 @@
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
+namespace {
+
constexpr std::chrono::milliseconds kHalEventBatchingTimeWindow(10);
const VehiclePropValue kEmptyValue{};
+// A list of supported options for "--set" command.
+const std::unordered_set<std::string> kSetPropOptions = {
+ // integer.
+ "-i",
+ // 64bit integer.
+ "-i64",
+ // float.
+ "-f",
+ // string.
+ "-s",
+ // bytes in hex format, e.g. 0xDEADBEEF.
+ "-b",
+ // Area id in integer.
+ "-a"};
+
+} // namespace
+
/**
* Indicates what's the maximum size of hidl_vec<VehiclePropValue> we want
* to store in reusable object pool.
*/
-constexpr auto kMaxHidlVecOfVehiclPropValuePoolSize = 20;
+constexpr auto kMaxHidlVecOfVehiclePropValuePoolSize = 20;
Return<void> VehicleHalManager::getAllPropConfigs(getAllPropConfigs_cb _hidl_cb) {
ALOGI("getAllPropConfigs called");
@@ -213,6 +234,11 @@
} else if (EqualsIgnoreCase(option, "--get")) {
cmdDumpSpecificProperties(fd, options);
} else if (EqualsIgnoreCase(option, "--set")) {
+ if (!checkCallerHasWritePermissions(fd)) {
+ dprintf(fd, "Caller does not have write permission\n");
+ return;
+ }
+ // Ignore the return value for this.
cmdSetOneProperty(fd, options);
} else {
dprintf(fd, "Invalid option: %s\n", option.c_str());
@@ -239,7 +265,8 @@
return false;
}
-bool VehicleHalManager::safelyParseInt(int fd, int index, std::string s, int* out) {
+template <typename T>
+bool VehicleHalManager::safelyParseInt(int fd, int index, const std::string& s, T* out) {
if (!android::base::ParseInt(s, out)) {
dprintf(fd, "non-integer argument at index %d: %s\n", index, s.c_str());
return false;
@@ -247,19 +274,27 @@
return true;
}
+bool VehicleHalManager::safelyParseFloat(int fd, int index, const std::string& s, float* out) {
+ if (!android::base::ParseFloat(s, out)) {
+ dprintf(fd, "non-float argument at index %d: %s\n", index, s.c_str());
+ return false;
+ }
+ return true;
+}
+
void VehicleHalManager::cmdHelp(int fd) const {
dprintf(fd, "Usage: \n\n");
dprintf(fd, "[no args]: dumps (id and value) all supported properties \n");
dprintf(fd, "--help: shows this help\n");
dprintf(fd, "--list: lists the ids of all supported properties\n");
dprintf(fd, "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties \n");
- // TODO: support other formats (int64, float, bytes)
dprintf(fd,
- "--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>] [a AREA_ID] : sets the value of "
- "property PROP, using arbitrary number of key/value parameters (i for int32, "
- "s for string) and an optional area.\n"
- "Notice that the string value can be set just once, while the other can have multiple "
- "values (so they're used in the respective array)\n");
+ "--set <PROP> [-i INT_VALUE [INT_VALUE ...]] [-i64 INT64_VALUE [INT64_VALUE ...]] "
+ "[-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] "
+ "[-b BYTES_VALUE] [-a AREA_ID] : sets the value of property PROP. "
+ "Notice that the string, bytes and area value can be set just once, while the other can"
+ " have multiple values (so they're used in the respective array), "
+ "BYTES_VALUE is in the form of 0xXXXX, e.g. 0xdeadbeef.\n");
}
void VehicleHalManager::cmdListAllProperties(int fd) const {
@@ -337,102 +372,49 @@
VehiclePropValue input;
input.prop = prop;
input.areaId = areaId;
- auto callback = [&](StatusCode status, const VehiclePropValue& output) {
+ auto callback = [&fd, &prop](StatusCode status, const VehiclePropValue& output) {
if (status == StatusCode::OK) {
dprintf(fd, "%s\n", toString(output).c_str());
} else {
dprintf(fd, "Could not get property %d. Error: %s\n", prop, toString(status).c_str());
}
};
- get(input, callback);
+
+ StatusCode status;
+ auto value = mHal->get(input, &status);
+ callback(status, value.get() ? *value : kEmptyValue);
}
-void VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
- if (!checkCallerHasWritePermissions(fd) || !checkArgumentsSize(fd, options, 3)) return;
-
- size_t size = options.size();
-
- // Syntax is --set PROP Type1 Value1 TypeN ValueN, so number of arguments must be even
- if (size % 2 != 0) {
- dprintf(fd, "must pass even number of arguments (passed %zu)\n", size);
- return;
+bool VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
+ if (!checkArgumentsSize(fd, options, 4)) {
+ dprintf(fd, "Requires at least 4 options, see help\n");
+ return false;
}
- int numberValues = (size - 2) / 2;
- VehiclePropValue prop;
- if (!safelyParseInt(fd, 1, options[1], &prop.prop)) return;
- prop.timestamp = elapsedRealtimeNano();
- prop.status = VehiclePropertyStatus::AVAILABLE;
-
- // First pass: calculate sizes
- int sizeInt32 = 0;
- int stringIndex = 0;
- int areaIndex = 0;
- for (int i = 2, kv = 1; kv <= numberValues; kv++) {
- // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
- std::string type = options[i];
- std::string value = options[i + 1];
- if (EqualsIgnoreCase(type, "i")) {
- sizeInt32++;
- } else if (EqualsIgnoreCase(type, "s")) {
- if (stringIndex != 0) {
- dprintf(fd,
- "defining string value (%s) again at index %d (already defined at %d=%s"
- ")\n",
- value.c_str(), i, stringIndex, options[stringIndex + 1].c_str());
- return;
- }
- stringIndex = i;
- } else if (EqualsIgnoreCase(type, "a")) {
- if (areaIndex != 0) {
- dprintf(fd,
- "defining area value (%s) again at index %d (already defined at %d=%s"
- ")\n",
- value.c_str(), i, areaIndex, options[areaIndex + 1].c_str());
- return;
- }
- areaIndex = i;
- } else {
- dprintf(fd, "invalid (%s) type at index %d\n", type.c_str(), i);
- return;
- }
- i += 2;
- }
- prop.value.int32Values.resize(sizeInt32);
-
- // Second pass: populate it
- int indexInt32 = 0;
- for (int i = 2, kv = 1; kv <= numberValues; kv++) {
- // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
- int valueIndex = i + 1;
- std::string type = options[i];
- std::string value = options[valueIndex];
- if (EqualsIgnoreCase(type, "i")) {
- int safeInt;
- if (!safelyParseInt(fd, valueIndex, value, &safeInt)) return;
- prop.value.int32Values[indexInt32++] = safeInt;
- } else if (EqualsIgnoreCase(type, "s")) {
- prop.value.stringValue = value;
- } else if (EqualsIgnoreCase(type, "a")) {
- if (!safelyParseInt(fd, valueIndex, value, &prop.areaId)) return;
- }
- i += 2;
+ VehiclePropValue prop = {};
+ if (!parseSetPropOptions(fd, options, &prop)) {
+ return false;
}
ALOGD("Setting prop %s", toString(prop).c_str());
- auto status = set(prop);
+
+ // Do not use VehicleHalManager::set here because we don't want to check write permission.
+ // Caller should be able to use the debug interface to set read-only properties.
+ handlePropertySetEvent(prop);
+ auto status = mHal->set(prop);
+
if (status == StatusCode::OK) {
dprintf(fd, "Set property %s\n", toString(prop).c_str());
- } else {
- dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
- toString(status).c_str());
+ return true;
}
+ dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
+ toString(status).c_str());
+ return false;
}
void VehicleHalManager::init() {
ALOGI("VehicleHalManager::init");
- mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclPropValuePoolSize);
-
+ mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclePropValuePoolSize);
mBatchingConsumer.run(&mEventQueue,
kHalEventBatchingTimeWindow,
@@ -486,7 +468,7 @@
for (const HalClientValues& cv : clientValues) {
auto vecSize = cv.values.size();
hidl_vec<VehiclePropValue> vec;
- if (vecSize < kMaxHidlVecOfVehiclPropValuePoolSize) {
+ if (vecSize < kMaxHidlVecOfVehiclePropValuePoolSize) {
vec.setToExternal(&mHidlVecOfVehiclePropValuePool[0], vecSize);
} else {
vec.resize(vecSize);
@@ -595,6 +577,158 @@
}
}
+std::vector<std::string> VehicleHalManager::getOptionValues(const hidl_vec<hidl_string>& options,
+ size_t* index) {
+ std::vector<std::string> values;
+ while (*index < options.size()) {
+ std::string option = options[*index];
+ if (kSetPropOptions.find(option) != kSetPropOptions.end()) {
+ return std::move(values);
+ }
+ values.push_back(option);
+ (*index)++;
+ }
+ return std::move(values);
+}
+
+bool VehicleHalManager::parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
+ VehiclePropValue* prop) {
+ // Options format:
+ // --set PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...] [-b b1 b2...] [-a a]
+ size_t optionIndex = 1;
+ int propValue;
+ if (!safelyParseInt(fd, optionIndex, options[optionIndex], &propValue)) {
+ dprintf(fd, "property value: \"%s\" is not a valid int\n", options[optionIndex].c_str());
+ return false;
+ }
+ prop->prop = propValue;
+ prop->timestamp = elapsedRealtimeNano();
+ prop->status = VehiclePropertyStatus::AVAILABLE;
+ optionIndex++;
+ std::unordered_set<std::string> parsedOptions;
+
+ while (optionIndex < options.size()) {
+ std::string type = options[optionIndex];
+ optionIndex++;
+ size_t currentIndex = optionIndex;
+ std::vector<std::string> values = getOptionValues(options, &optionIndex);
+ if (parsedOptions.find(type) != parsedOptions.end()) {
+ dprintf(fd, "duplicate \"%s\" options\n", type.c_str());
+ return false;
+ }
+ parsedOptions.insert(type);
+ if (EqualsIgnoreCase(type, "-i")) {
+ if (values.size() == 0) {
+ dprintf(fd, "no values specified when using \"-i\"\n");
+ return false;
+ }
+ prop->value.int32Values.resize(values.size());
+ for (size_t i = 0; i < values.size(); i++) {
+ int32_t safeInt;
+ if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
+ dprintf(fd, "value: \"%s\" is not a valid int\n", values[i].c_str());
+ return false;
+ }
+ prop->value.int32Values[i] = safeInt;
+ }
+ } else if (EqualsIgnoreCase(type, "-i64")) {
+ if (values.size() == 0) {
+ dprintf(fd, "no values specified when using \"-i64\"\n");
+ return false;
+ }
+ prop->value.int64Values.resize(values.size());
+ for (size_t i = 0; i < values.size(); i++) {
+ int64_t safeInt;
+ if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
+ dprintf(fd, "value: \"%s\" is not a valid int64\n", values[i].c_str());
+ return false;
+ }
+ prop->value.int64Values[i] = safeInt;
+ }
+ } else if (EqualsIgnoreCase(type, "-f")) {
+ if (values.size() == 0) {
+ dprintf(fd, "no values specified when using \"-f\"\n");
+ return false;
+ }
+ prop->value.floatValues.resize(values.size());
+ for (size_t i = 0; i < values.size(); i++) {
+ float safeFloat;
+ if (!safelyParseFloat(fd, currentIndex + i, values[i], &safeFloat)) {
+ dprintf(fd, "value: \"%s\" is not a valid float\n", values[i].c_str());
+ return false;
+ }
+ prop->value.floatValues[i] = safeFloat;
+ }
+ } else if (EqualsIgnoreCase(type, "-s")) {
+ if (values.size() != 1) {
+ dprintf(fd, "expect exact one value when using \"-s\"\n");
+ return false;
+ }
+ prop->value.stringValue = values[0];
+ } else if (EqualsIgnoreCase(type, "-b")) {
+ if (values.size() != 1) {
+ dprintf(fd, "expect exact one value when using \"-b\"\n");
+ return false;
+ }
+ std::vector<uint8_t> bytes;
+ if (!parseHexString(fd, values[0], &bytes)) {
+ dprintf(fd, "value: \"%s\" is not a valid hex string\n", values[0].c_str());
+ return false;
+ }
+ prop->value.bytes = bytes;
+ } else if (EqualsIgnoreCase(type, "-a")) {
+ if (values.size() != 1) {
+ dprintf(fd, "expect exact one value when using \"-a\"\n");
+ return false;
+ }
+ if (!safelyParseInt(fd, currentIndex, values[0], &(prop->areaId))) {
+ dprintf(fd, "area ID: \"%s\" is not a valid int\n", values[0].c_str());
+ return false;
+ }
+ } else {
+ dprintf(fd, "unknown option: %s\n", type.c_str());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool VehicleHalManager::parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes) {
+ if (s.size() % 2 != 0) {
+ dprintf(fd, "invalid hex string: %s, should have even size\n", s.c_str());
+ return false;
+ }
+ if (strncmp(s.substr(0, 2).c_str(), "0x", 2)) {
+ dprintf(fd, "hex string should start with \"0x\", got %s\n", s.c_str());
+ return false;
+ }
+ std::string subs = s.substr(2);
+ std::transform(subs.begin(), subs.end(), subs.begin(),
+ [](unsigned char c) { return std::tolower(c); });
+
+ bool highDigit = true;
+ for (size_t i = 0; i < subs.size(); i++) {
+ char c = subs[i];
+ uint8_t v;
+ if (c >= '0' && c <= '9') {
+ v = c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ v = c - 'a' + 10;
+ } else {
+ dprintf(fd, "invalid character %c in hex string %s\n", c, subs.c_str());
+ return false;
+ }
+ if (highDigit) {
+ (*bytes).push_back(v * 16);
+ } else {
+ (*bytes)[bytes->size() - 1] += v;
+ }
+ highDigit = !highDigit;
+ }
+ return true;
+}
+
} // namespace V2_0
} // namespace vehicle
} // namespace automotive
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 8ff4924..55617be 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -307,6 +307,18 @@
.prop = toInt(VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::STATIC,
+ .areaConfigs = {VehicleAreaConfig{
+ .areaId = WHEEL_FRONT_LEFT,
+ },
+ VehicleAreaConfig{
+ .areaId = WHEEL_FRONT_RIGHT,
+ },
+ VehicleAreaConfig{
+ .areaId = WHEEL_REAR_LEFT,
+ },
+ VehicleAreaConfig{
+ .areaId = WHEEL_REAR_RIGHT,
+ }},
},
.initialAreaValues = {{WHEEL_FRONT_LEFT, {.floatValues = {137.0f}}},
{WHEEL_FRONT_RIGHT, {.floatValues = {137.0f}}},
@@ -1032,14 +1044,6 @@
{
.config =
{
- .prop = toInt(VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
.prop = toInt(VehicleProperty::WATCHDOG_ALIVE),
.access = VehiclePropertyAccess::WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -1105,6 +1109,42 @@
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
},
},
+ {
+ .config =
+ {
+ .prop = PLACEHOLDER_PROPERTY_INT,
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = {.int32Values = {0}},
+ },
+ {
+ .config =
+ {
+ .prop = PLACEHOLDER_PROPERTY_FLOAT,
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = {.floatValues = {0.0f}},
+ },
+ {
+ .config =
+ {
+ .prop = PLACEHOLDER_PROPERTY_BOOLEAN,
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = {.int32Values = {0 /* false */}},
+ },
+ {
+ .config =
+ {
+ .prop = PLACEHOLDER_PROPERTY_STRING,
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = {.stringValue = {"Test"}},
+ },
#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
// Vendor propetry for E2E ClusterHomeService testing.
{
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
index d5f6a18..51251a7 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
@@ -189,6 +189,19 @@
KeyPress = 100,
};
+/**
+ * These properties are placeholder properties for developers to test new features without
+ * implementing a real property.
+ */
+constexpr int32_t PLACEHOLDER_PROPERTY_INT =
+ 0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::INT32;
+constexpr int32_t PLACEHOLDER_PROPERTY_FLOAT =
+ 0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::FLOAT;
+constexpr int32_t PLACEHOLDER_PROPERTY_BOOLEAN =
+ 0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::BOOLEAN;
+constexpr int32_t PLACEHOLDER_PROPERTY_STRING =
+ 0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::STRING;
+
const int32_t kHvacPowerProperties[] = {
toInt(VehicleProperty::HVAC_FAN_SPEED),
toInt(VehicleProperty::HVAC_FAN_DIRECTION),
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
index 0975071..bdf46fb 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -18,6 +18,7 @@
#include <iostream>
#include <android-base/macros.h>
+#include <cutils/native_handle.h>
#include <utils/SystemClock.h>
#include <gtest/gtest.h>
@@ -32,6 +33,18 @@
namespace vehicle {
namespace V2_0 {
+// A simple helper class to expose 'cmdSetOneProperty' to the unit tests.
+class VehicleHalManagerTestHelper {
+ public:
+ VehicleHalManagerTestHelper(VehicleHalManager* manager) { mManager = manager; }
+ bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
+ return mManager->cmdSetOneProperty(fd, options);
+ }
+
+ public:
+ VehicleHalManager* mManager;
+};
+
namespace {
using namespace std::placeholders;
@@ -57,33 +70,21 @@
auto property = static_cast<VehicleProperty>(requestedPropValue.prop);
int32_t areaId = requestedPropValue.areaId;
- switch (property) {
- case VehicleProperty::INFO_MAKE:
- pValue = getValuePool()->obtainString(kCarMake);
- break;
- case VehicleProperty::INFO_FUEL_CAPACITY:
- if (fuelCapacityAttemptsLeft-- > 0) {
- // Emulate property not ready yet.
- *outStatus = StatusCode::TRY_AGAIN;
- } else {
- pValue = getValuePool()->obtainFloat(42.42);
- }
- break;
- default:
- if (requestedPropValue.prop == kCustomComplexProperty) {
- pValue = getValuePool()->obtainComplex();
- pValue->value.int32Values = hidl_vec<int32_t> { 10, 20 };
- pValue->value.int64Values = hidl_vec<int64_t> { 30, 40 };
- pValue->value.floatValues = hidl_vec<float_t> { 1.1, 2.2 };
- pValue->value.bytes = hidl_vec<uint8_t> { 1, 2, 3 };
- pValue->value.stringValue = kCarMake;
- break;
- }
- auto key = makeKey(toInt(property), areaId);
- if (mValues.count(key) == 0) {
- ALOGW("");
- }
- pValue = getValuePool()->obtain(mValues[key]);
+ if (property == VehicleProperty::INFO_FUEL_CAPACITY) {
+ if (fuelCapacityAttemptsLeft-- > 0) {
+ // Emulate property not ready yet.
+ *outStatus = StatusCode::TRY_AGAIN;
+ } else {
+ pValue = getValuePool()->obtainFloat(42.42);
+ }
+ } else {
+ auto key = makeKey(requestedPropValue);
+ if (mValues.count(key) == 0) {
+ ALOGW("key not found\n");
+ *outStatus = StatusCode::INVALID_ARG;
+ return pValue;
+ }
+ pValue = getValuePool()->obtain(mValues[key]);
}
if (*outStatus == StatusCode::OK && pValue.get() != nullptr) {
@@ -100,7 +101,6 @@
&& mirrorFoldAttemptsLeft-- > 0) {
return StatusCode::TRY_AGAIN;
}
-
mValues[makeKey(propValue)] = propValue;
return StatusCode::OK;
}
@@ -181,6 +181,18 @@
actualStatusCode = refStatus;
}
+ MockedVehicleHal::VehiclePropValuePtr getComplexProperty() {
+ auto pValue = objectPool->obtainComplex();
+ pValue->prop = kCustomComplexProperty;
+ pValue->areaId = 0;
+ pValue->value.int32Values = hidl_vec<int32_t>{10, 20};
+ pValue->value.int64Values = hidl_vec<int64_t>{30, 40};
+ pValue->value.floatValues = hidl_vec<float_t>{1.1, 2.2};
+ pValue->value.bytes = hidl_vec<uint8_t>{1, 2, 3};
+ pValue->value.stringValue = kCarMake;
+ return pValue;
+ }
+
public:
VehiclePropValue actualValue;
StatusCode actualStatusCode;
@@ -308,6 +320,8 @@
}
TEST_F(VehicleHalManagerTest, get_Complex) {
+ ASSERT_EQ(StatusCode::OK, hal->set(*getComplexProperty().get()));
+
invokeGet(kCustomComplexProperty, 0);
ASSERT_EQ(StatusCode::OK, actualStatusCode);
@@ -334,6 +348,11 @@
}
TEST_F(VehicleHalManagerTest, get_StaticString) {
+ auto pValue = objectPool->obtainString(kCarMake);
+ pValue->prop = toInt(VehicleProperty::INFO_MAKE);
+ pValue->areaId = 0;
+ ASSERT_EQ(StatusCode::OK, hal->set(*pValue.get()));
+
invokeGet(toInt(VehicleProperty::INFO_MAKE), 0);
ASSERT_EQ(StatusCode::OK, actualStatusCode);
@@ -458,6 +477,138 @@
ASSERT_TRUE(clients.isEmpty());
}
+TEST_F(VehicleHalManagerTest, debug) {
+ hidl_handle fd = {};
+ fd.setTo(native_handle_create(/*numFds=*/1, /*numInts=*/0), /*shouldOwn=*/true);
+
+ // Because debug function returns void, so no way to check return value.
+ manager->debug(fd, {});
+ manager->debug(fd, {"--help"});
+ manager->debug(fd, {"--list"});
+ manager->debug(fd, {"--get"});
+ manager->debug(fd, {"--set"});
+ manager->debug(fd, {"invalid"});
+}
+
+struct SetPropTestCase {
+ std::string test_name;
+ const hidl_vec<hidl_string> configs;
+ bool success;
+};
+
+class VehicleHalManagerSetPropTest : public VehicleHalManagerTest,
+ public testing::WithParamInterface<SetPropTestCase> {};
+
+TEST_P(VehicleHalManagerSetPropTest, cmdSetOneProperty) {
+ const SetPropTestCase& tc = GetParam();
+ VehicleHalManagerTestHelper helper(manager.get());
+ ASSERT_EQ(tc.success, helper.cmdSetOneProperty(STDERR_FILENO, tc.configs));
+}
+
+std::vector<SetPropTestCase> GenSetPropParams() {
+ char infoMakeProperty[100] = {};
+ snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
+ return {
+ {"success_set_string", {"--set", infoMakeProperty, "-s", kCarMake}, true},
+ {"success_set_bytes", {"--set", infoMakeProperty, "-b", "0xdeadbeef"}, true},
+ {"success_set_bytes_caps", {"--set", infoMakeProperty, "-b", "0xDEADBEEF"}, true},
+ {"success_set_int", {"--set", infoMakeProperty, "-i", "2147483647"}, true},
+ {"success_set_ints",
+ {"--set", infoMakeProperty, "-i", "2147483647", "0", "-2147483648"},
+ true},
+ {"success_set_int64",
+ {"--set", infoMakeProperty, "-i64", "-9223372036854775808"},
+ true},
+ {"success_set_int64s",
+ {"--set", infoMakeProperty, "-i64", "-9223372036854775808", "0",
+ "9223372036854775807"},
+ true},
+ {"success_set_float", {"--set", infoMakeProperty, "-f", "1.175494351E-38"}, true},
+ {"success_set_floats",
+ {"--set", infoMakeProperty, "-f", "-3.402823466E+38", "0", "3.402823466E+38"},
+ true},
+ {"success_set_area", {"--set", infoMakeProperty, "-a", "2147483647"}, true},
+ {"fail_no_options", {}, false},
+ {"fail_less_than_4_options", {"--set", infoMakeProperty, "-i"}, false},
+ {"fail_unknown_options", {"--set", infoMakeProperty, "-s", kCarMake, "-abcd"}, false},
+ {"fail_invalid_property", {"--set", "not valid", "-s", kCarMake}, false},
+ {"fail_duplicate_string",
+ {"--set", infoMakeProperty, "-s", kCarMake, "-s", kCarMake},
+ false},
+ {"fail_multiple_strings", {"--set", infoMakeProperty, "-s", kCarMake, kCarMake}, false},
+ {"fail_no_string_value", {"--set", infoMakeProperty, "-s", "-a", "1234"}, false},
+ {"fail_duplicate_bytes",
+ {"--set", infoMakeProperty, "-b", "0xdeadbeef", "-b", "0xdeadbeef"},
+ false},
+ {"fail_multiple_bytes",
+ {"--set", infoMakeProperty, "-b", "0xdeadbeef", "0xdeadbeef"},
+ false},
+ {"fail_invalid_bytes", {"--set", infoMakeProperty, "-b", "0xgood"}, false},
+ {"fail_invalid_bytes_no_prefix", {"--set", infoMakeProperty, "-b", "deadbeef"}, false},
+ {"fail_invalid_int", {"--set", infoMakeProperty, "-i", "abc"}, false},
+ {"fail_int_out_of_range", {"--set", infoMakeProperty, "-i", "2147483648"}, false},
+ {"fail_no_int_value", {"--set", infoMakeProperty, "-i", "-s", kCarMake}, false},
+ {"fail_invalid_int64", {"--set", infoMakeProperty, "-i64", "abc"}, false},
+ {"fail_int64_out_of_range",
+ {"--set", infoMakeProperty, "-i64", "-9223372036854775809"},
+ false},
+ {"fail_no_int64_value", {"--set", infoMakeProperty, "-i64", "-s", kCarMake}, false},
+ {"fail_invalid_float", {"--set", infoMakeProperty, "-f", "abc"}, false},
+ {"fail_float_out_of_range",
+ {"--set", infoMakeProperty, "-f", "-3.402823466E+39"},
+ false},
+ {"fail_no_float_value", {"--set", infoMakeProperty, "-f", "-s", kCarMake}, false},
+ {"fail_multiple_areas", {"--set", infoMakeProperty, "-a", "2147483648", "0"}, false},
+ {"fail_invalid_area", {"--set", infoMakeProperty, "-a", "abc"}, false},
+ {"fail_area_out_of_range", {"--set", infoMakeProperty, "-a", "2147483648"}, false},
+ {"fail_no_area_value", {"--set", infoMakeProperty, "-a", "-s", kCarMake}, false},
+ };
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ VehicleHalManagerSetPropTests, VehicleHalManagerSetPropTest,
+ testing::ValuesIn(GenSetPropParams()),
+ [](const testing::TestParamInfo<VehicleHalManagerSetPropTest::ParamType>& info) {
+ return info.param.test_name;
+ });
+
+TEST_F(VehicleHalManagerTest, SetComplexPropTest) {
+ char infoMakeProperty[100] = {};
+ snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
+ VehicleHalManagerTestHelper helper(manager.get());
+ ASSERT_TRUE(helper.cmdSetOneProperty(
+ STDERR_FILENO, {"--set", infoMakeProperty, "-s", kCarMake,
+ "-b", "0xdeadbeef", "-i", "2147483647",
+ "0", "-2147483648", "-i64", "-9223372036854775808",
+ "0", "9223372036854775807", "-f", "-3.402823466E+38",
+ "0", "3.402823466E+38", "-a", "123"}));
+ StatusCode status = StatusCode::OK;
+ VehiclePropValue requestProp;
+ requestProp.prop = toInt(VehicleProperty::INFO_MAKE);
+ requestProp.areaId = 123;
+ auto value = hal->get(requestProp, &status);
+ ASSERT_EQ(StatusCode::OK, status);
+ ASSERT_EQ(value->prop, toInt(VehicleProperty::INFO_MAKE));
+ ASSERT_EQ(value->areaId, 123);
+ ASSERT_STREQ(kCarMake, value->value.stringValue.c_str());
+ uint8_t bytes[] = {0xde, 0xad, 0xbe, 0xef};
+ ASSERT_FALSE(memcmp(bytes, value->value.bytes.data(), sizeof(bytes)));
+ ASSERT_EQ(3u, value->value.int32Values.size());
+ ASSERT_EQ(2147483647, value->value.int32Values[0]);
+ ASSERT_EQ(0, value->value.int32Values[1]);
+ ASSERT_EQ(-2147483648, value->value.int32Values[2]);
+ ASSERT_EQ(3u, value->value.int64Values.size());
+ // -9223372036854775808 is not a valid literal since '-' and '9223372036854775808' would be two
+ // tokens and the later does not fit in unsigned long long.
+ ASSERT_EQ(-9223372036854775807 - 1, value->value.int64Values[0]);
+ ASSERT_EQ(0, value->value.int64Values[1]);
+ ASSERT_EQ(9223372036854775807, value->value.int64Values[2]);
+ ASSERT_EQ(3u, value->value.floatValues.size());
+ ASSERT_EQ(-3.402823466E+38f, value->value.floatValues[0]);
+ ASSERT_EQ(0.0f, value->value.floatValues[1]);
+ ASSERT_EQ(3.402823466E+38f, value->value.floatValues[2]);
+}
+
} // namespace anonymous
} // namespace V2_0
diff --git a/automotive/vehicle/2.0/utils/UserHalHelper.cpp b/automotive/vehicle/2.0/utils/UserHalHelper.cpp
index abf59b7..dccdb2b 100644
--- a/automotive/vehicle/2.0/utils/UserHalHelper.cpp
+++ b/automotive/vehicle/2.0/utils/UserHalHelper.cpp
@@ -60,11 +60,22 @@
<< int32Values.size();
}
userInfo->userId = int32Values[startPos];
- auto userFlags = verifyAndCast<UserFlags>(int32Values[startPos + 1]);
- if (!userFlags.ok()) {
- return Error() << "Invalid user flags: " << userFlags.error();
+ int32_t intUserFlags = int32Values[startPos + 1];
+ int32_t expectedUserFlags = 0;
+ for (const auto& v : hidl_enum_range<UserFlags>()) {
+ int32_t intEnumUserFlag = static_cast<int32_t>(v);
+ if ((intUserFlags & intEnumUserFlag) != 0) {
+ expectedUserFlags |= intEnumUserFlag;
+ }
}
- userInfo->flags = *userFlags;
+ if (intUserFlags != expectedUserFlags) {
+ return Error() << "Invalid user flags: " << intUserFlags << ", must be '|' of UserFlags";
+ }
+ // intUserFlags is actually not a valid UserFlags enum, instead, it is a 'bit or' of possible
+ // multiple UserFlags. However, because the HAL interface was defined incorrectly, we have to
+ // cast it to UserFlags here, which is defined behavior because the underlying type for
+ // UserFlags is int32_t and our intUserFlags is within the range of int32_t.
+ userInfo->flags = static_cast<UserFlags>(intUserFlags);
return {};
}
diff --git a/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp b/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp
index 7da87a2..0562a54 100644
--- a/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp
+++ b/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp
@@ -54,6 +54,10 @@
constexpr int32_t GUEST_USER = static_cast<int32_t>(UserFlags::GUEST);
constexpr int32_t NONE_USER = static_cast<int32_t>(UserFlags::NONE);
constexpr int32_t SYSTEM_USER = static_cast<int32_t>(UserFlags::SYSTEM);
+constexpr int32_t ADMIN_USER = static_cast<int32_t>(UserFlags::ADMIN);
+constexpr int32_t SYSTEM_ADMIN_USER = static_cast<int32_t>(UserFlags::SYSTEM | UserFlags::ADMIN);
+// 0x1111 is not a valid UserFlags combination.
+constexpr int32_t INVALID_USER_FLAG = 0x1111;
constexpr int32_t USER_ID_ASSOC_KEY_FOB =
static_cast<int32_t>(UserIdentificationAssociationType::KEY_FOB);
@@ -72,7 +76,7 @@
} // namespace
-TEST(UserHalHelperTest, TestToInitialUserInfoRequest) {
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestSystemUser) {
VehiclePropValue propValue{
.prop = INITIAL_USER_INFO,
.value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER,
@@ -92,6 +96,58 @@
EXPECT_THAT(actual.value(), Eq(expected));
}
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestAdminUser) {
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, ADMIN_USER, 10,
+ NONE_USER}},
+ };
+ InitialUserInfoRequest expected{
+ .requestId = 23,
+ .requestType = InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA,
+ .usersInfo = {{10, UserFlags::NONE}, 2, {{0, UserFlags::ADMIN}, {10, UserFlags::NONE}}},
+ };
+
+ auto actual = toInitialUserInfoRequest(propValue);
+
+ ASSERT_TRUE(actual.ok()) << actual.error().message();
+ EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestUserFlagsBitCombination) {
+ // SYSTEM_ADMIN_USER is two UserFlags combined and is itself not a defined UserFlags enum.
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0,
+ SYSTEM_ADMIN_USER, 10, NONE_USER}},
+ };
+ InitialUserInfoRequest expected{
+ .requestId = 23,
+ .requestType = InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA,
+ .usersInfo = {{10, UserFlags::NONE},
+ 2,
+ {{0, static_cast<UserFlags>(SYSTEM_ADMIN_USER)}, {10, UserFlags::NONE}}},
+ };
+
+ auto actual = toInitialUserInfoRequest(propValue);
+
+ ASSERT_TRUE(actual.ok()) << actual.error().message();
+ EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestUserInvalidUserFlag) {
+ // 0x1111 is not a valid UserFlags flag combination.
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0,
+ INVALID_USER_FLAG, 10, NONE_USER}},
+ };
+
+ auto actual = toInitialUserInfoRequest(propValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on invalid user flags";
+}
+
TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithMismatchingPropType) {
VehiclePropValue propValue{
.prop = INT32_MAX,
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.xml b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.xml
index 09463c9..ea7adc9 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.xml
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.xml
@@ -22,8 +22,11 @@
<target_preparer class="com.android.tradefed.targetprep.StopServicesSetup">
</target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
- <option name="bluetooth" value="off" />
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="settings put global ble_scan_always_enabled 0" />
+ <option name="run-command" value="su u$(am get-current-user)_system svc bluetooth disable" />
+ <option name="teardown-command" value="su u$(am get-current-user)_system svc bluetooth enable" />
+ <option name="teardown-command" value="settings put global ble_scan_always_enabled 1" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
diff --git a/broadcastradio/2.0/default/Android.bp b/broadcastradio/2.0/default/Android.bp
index 870c944..38eeb15 100644
--- a/broadcastradio/2.0/default/Android.bp
+++ b/broadcastradio/2.0/default/Android.bp
@@ -25,6 +25,9 @@
cc_binary {
name: "android.hardware.broadcastradio@2.0-service",
+ vintf_fragments: [
+ "android.hardware.broadcastradio@2.0-service.xml",
+ ],
init_rc: ["android.hardware.broadcastradio@2.0-service.rc"],
vendor: true,
relative_install_path: "hw",
@@ -41,7 +44,7 @@
"TunerSession.cpp",
"VirtualProgram.cpp",
"VirtualRadio.cpp",
- "service.cpp"
+ "service.cpp",
],
static_libs: [
"android.hardware.broadcastradio@common-utils-2x-lib",
diff --git a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.xml b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.xml
new file mode 100644
index 0000000..97f2e4d
--- /dev/null
+++ b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.xml
@@ -0,0 +1,12 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.broadcastradio</name>
+ <transport>hwbinder</transport>
+ <version>2.0</version>
+ <interface>
+ <name>IBroadcastRadio</name>
+ <instance>amfm</instance>
+ <instance>dab</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/camera/metadata/3.7/types.hal b/camera/metadata/3.7/types.hal
new file mode 100644
index 0000000..a09bdf9
--- /dev/null
+++ b/camera/metadata/3.7/types.hal
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata@3.7;
+
+import android.hardware.camera.metadata@3.2;
+import android.hardware.camera.metadata@3.3;
+import android.hardware.camera.metadata@3.4;
+import android.hardware.camera.metadata@3.5;
+import android.hardware.camera.metadata@3.6;
+
+// No new metadata sections added in this revision
+
+/**
+ * Main enumeration for defining camera metadata tags added in this revision
+ *
+ * <p>Partial documentation is included for each tag; for complete documentation, reference
+ * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
+ */
+enum CameraMetadataTag : @3.6::CameraMetadataTag {
+ /** android.info.deviceStateOrientations [static, int64[], ndk_public]
+ */
+ ANDROID_INFO_DEVICE_STATE_ORIENTATIONS = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_INFO_END_3_4,
+
+ ANDROID_INFO_END_3_7,
+
+};
+
+/*
+ * Enumeration definitions for the various entries that need them
+ */
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 7727547..052103d 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -882,6 +882,7 @@
camera_metadata* oldSessionParams, camera_metadata* newSessionParams);
void verifyRequestTemplate(const camera_metadata_t* metadata, RequestTemplate requestTemplate);
+ static void overrideRotateAndCrop(::android::hardware::hidl_vec<uint8_t> *settings /*in/out*/);
static bool isDepthOnly(const camera_metadata_t* staticMeta);
@@ -935,7 +936,9 @@
camera_metadata_ro_entry* streamConfigs,
camera_metadata_ro_entry* maxResolutionStreamConfigs,
const camera_metadata_t* staticMetadata);
- static bool isColorCamera(const camera_metadata_t *metadata);
+ void getPrivacyTestPatternModes(
+ const camera_metadata_t* staticMetadata,
+ std::unordered_set<int32_t>* privacyTestPatternModes/*out*/);
static V3_2::DataspaceFlags getDataspace(PixelFormat format);
@@ -4660,6 +4663,7 @@
settings = req;
});
ASSERT_TRUE(ret.isOk());
+ overrideRotateAndCrop(&settings);
hidl_handle buffer_handle;
StreamBuffer outputBuffer;
@@ -4836,6 +4840,7 @@
settings.setToExternal(
reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (settingsBuffer)),
get_camera_metadata_size(settingsBuffer));
+ overrideRotateAndCrop(&settings);
free_camera_metadata(staticMeta);
ret = session->close();
@@ -4913,6 +4918,7 @@
reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (
filteredSettingsBuffer)),
get_camera_metadata_size(filteredSettingsBuffer));
+ overrideRotateAndCrop(&camSettings[0].settings);
camSettings[0].fmqSettingsSize = 0;
camSettings[0].physicalCameraId = physicalDeviceId;
@@ -5070,6 +5076,7 @@
settings.setToExternal(
reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(settingsBuffer)),
get_camera_metadata_size(settingsBuffer));
+ overrideRotateAndCrop(&settings);
free_camera_metadata(staticMeta);
ret = session->close();
@@ -5305,6 +5312,7 @@
camera_metadata_t *metaBuffer = requestMeta.release();
requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
get_camera_metadata_size(metaBuffer), true);
+ overrideRotateAndCrop(&requestSettings[i]);
requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
emptyInputBuffer, {outputBuffers[i]}};
@@ -5531,6 +5539,7 @@
camera_metadata_t *metaBuffer = requestMeta.release();
requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
get_camera_metadata_size(metaBuffer), true);
+ overrideRotateAndCrop(&requestSettings[i]);
requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
emptyInputBuffer, {outputBuffers[i]}};
@@ -5671,6 +5680,7 @@
settings = req;
});
ASSERT_TRUE(ret.isOk());
+ overrideRotateAndCrop(&settings);
::android::hardware::hidl_vec<StreamBuffer> emptyOutputBuffers;
StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr,
@@ -5755,6 +5765,7 @@
settings = req;
});
ASSERT_TRUE(ret.isOk());
+ overrideRotateAndCrop(&settings);
hidl_handle buffer_handle;
if (useHalBufManager) {
@@ -6187,167 +6198,6 @@
}
}
-// Test the multi-camera API requirement for Google Requirement Freeze S
-// Note that this requirement can only be partially tested. If a vendor
-// device doesn't expose a physical camera in any shape or form, there is no way
-// the test can catch it.
-TEST_P(CameraHidlTest, grfSMultiCameraTest) {
- const int socGrfApi = property_get_int32("ro.board.first_api_level", /*default*/ -1);
- if (socGrfApi < 31 /*S*/) {
- // Non-GRF devices, or version < 31 Skip
- ALOGI("%s: socGrfApi level is %d. Skipping", __FUNCTION__, socGrfApi);
- return;
- }
-
- // Test that if more than one color cameras facing the same direction are
- // supported, there must be at least one logical camera facing that
- // direction.
- hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
- // Front and back facing non-logical color cameras
- std::set<std::string> frontColorCameras, rearColorCameras;
- // Front and back facing logical cameras' physical camera Id sets
- std::set<std::set<std::string>> frontPhysicalIds, rearPhysicalIds;
- for (const auto& name : cameraDeviceNames) {
- std::string cameraId;
- int deviceVersion = getCameraDeviceVersionAndId(name, mProviderType, &cameraId);
- switch (deviceVersion) {
- case CAMERA_DEVICE_API_VERSION_3_7:
- case CAMERA_DEVICE_API_VERSION_3_6:
- case CAMERA_DEVICE_API_VERSION_3_5:
- case CAMERA_DEVICE_API_VERSION_3_4:
- case CAMERA_DEVICE_API_VERSION_3_3:
- case CAMERA_DEVICE_API_VERSION_3_2: {
- ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x;
- ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
- Return<void> ret;
- ret = mProvider->getCameraDeviceInterface_V3_x(
- name, [&](auto status, const auto& device) {
- ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
- ASSERT_EQ(Status::OK, status);
- ASSERT_NE(device, nullptr);
- device3_x = device;
- });
- ASSERT_TRUE(ret.isOk());
-
- ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) {
- ASSERT_EQ(Status::OK, status);
- const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
-
- // Skip if this is not a color camera.
- if (!CameraHidlTest::isColorCamera(metadata)) {
- return;
- }
-
- // Check camera facing. Skip if facing is neither FRONT
- // nor BACK. If this is not a logical camera, only note down
- // the camera ID, and skip.
- camera_metadata_ro_entry entry;
- int retcode = find_camera_metadata_ro_entry(
- metadata, ANDROID_LENS_FACING, &entry);
- ASSERT_EQ(retcode, 0);
- ASSERT_GT(entry.count, 0);
- uint8_t facing = entry.data.u8[0];
- bool isLogicalCamera = (isLogicalMultiCamera(metadata) == Status::OK);
- if (facing == ANDROID_LENS_FACING_FRONT) {
- if (!isLogicalCamera) {
- frontColorCameras.insert(cameraId);
- return;
- }
- } else if (facing == ANDROID_LENS_FACING_BACK) {
- if (!isLogicalCamera) {
- rearColorCameras.insert(cameraId);
- return;
- }
- } else {
- // Not FRONT or BACK facing. Skip.
- return;
- }
-
- // Check logical camera's physical camera IDs for color
- // cameras.
- std::unordered_set<std::string> physicalCameraIds;
- Status s = getPhysicalCameraIds(metadata, &physicalCameraIds);
- ASSERT_EQ(Status::OK, s);
- if (facing == ANDROID_LENS_FACING_FRONT) {
- frontPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end());
- } else {
- rearPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end());
- }
- for (const auto& physicalId : physicalCameraIds) {
- // Skip if the physicalId is publicly available
- for (auto& deviceName : cameraDeviceNames) {
- std::string publicVersion, publicId;
- ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType,
- &publicVersion, &publicId));
- if (physicalId == publicId) {
- // Skip because public Ids will be iterated in outer loop.
- return;
- }
- }
-
- auto castResult = device::V3_5::ICameraDevice::castFrom(device3_x);
- ASSERT_TRUE(castResult.isOk());
- ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice>
- device3_5 = castResult;
- ASSERT_NE(device3_5, nullptr);
-
- // Check camera characteristics for hidden camera id
- Return<void> ret = device3_5->getPhysicalCameraCharacteristics(
- physicalId, [&](auto status, const auto& chars) {
- ASSERT_EQ(Status::OK, status);
- const camera_metadata_t* physicalMetadata =
- (camera_metadata_t*)chars.data();
-
- if (CameraHidlTest::isColorCamera(physicalMetadata)) {
- if (facing == ANDROID_LENS_FACING_FRONT) {
- frontColorCameras.insert(physicalId);
- } else if (facing == ANDROID_LENS_FACING_BACK) {
- rearColorCameras.insert(physicalId);
- }
- }
- });
- ASSERT_TRUE(ret.isOk());
- }
- });
- ASSERT_TRUE(ret.isOk());
- } break;
- case CAMERA_DEVICE_API_VERSION_1_0: {
- // Not applicable
- } break;
- default: {
- ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
- ADD_FAILURE();
- } break;
- }
- }
-
- // If there are more than one color cameras facing one direction, a logical
- // multi-camera must be defined consisting of all color cameras facing that
- // direction.
- if (frontColorCameras.size() > 1) {
- bool hasFrontLogical = false;
- for (const auto& physicalIds : frontPhysicalIds) {
- if (std::includes(physicalIds.begin(), physicalIds.end(),
- frontColorCameras.begin(), frontColorCameras.end())) {
- hasFrontLogical = true;
- break;
- }
- }
- ASSERT_TRUE(hasFrontLogical);
- }
- if (rearColorCameras.size() > 1) {
- bool hasRearLogical = false;
- for (const auto& physicalIds : rearPhysicalIds) {
- if (std::includes(physicalIds.begin(), physicalIds.end(),
- rearColorCameras.begin(), rearColorCameras.end())) {
- hasRearLogical = true;
- break;
- }
- }
- ASSERT_TRUE(hasRearLogical);
- }
-}
-
// Retrieve all valid output stream resolutions from the camera
// static characteristics.
Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta,
@@ -6779,6 +6629,25 @@
ASSERT_TRUE(-ENOENT == retcode || 0 == retcode);
}
+void CameraHidlTest::getPrivacyTestPatternModes(
+ const camera_metadata_t* staticMetadata,
+ std::unordered_set<int32_t>* privacyTestPatternModes/*out*/) {
+ ASSERT_NE(staticMetadata, nullptr);
+ ASSERT_NE(privacyTestPatternModes, nullptr);
+
+ camera_metadata_ro_entry entry;
+ int retcode = find_camera_metadata_ro_entry(
+ staticMetadata, ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, &entry);
+ ASSERT_TRUE(0 == retcode);
+
+ for (auto i = 0; i < entry.count; i++) {
+ if (entry.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR ||
+ entry.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK) {
+ privacyTestPatternModes->insert(entry.data.i32[i]);
+ }
+ }
+}
+
// Select an appropriate dataspace given a specific pixel format.
V3_2::DataspaceFlags CameraHidlTest::getDataspace(PixelFormat format) {
switch (format) {
@@ -6820,23 +6689,6 @@
return ret;
}
-bool CameraHidlTest::isColorCamera(const camera_metadata_t *metadata) {
- camera_metadata_ro_entry entry;
- int retcode = find_camera_metadata_ro_entry(
- metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
- if ((0 == retcode) && (entry.count > 0)) {
- bool isBackwardCompatible = (std::find(entry.data.u8, entry.data.u8 + entry.count,
- ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) !=
- entry.data.u8 + entry.count);
- bool isMonochrome = (std::find(entry.data.u8, entry.data.u8 + entry.count,
- ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) !=
- entry.data.u8 + entry.count);
- bool isColor = isBackwardCompatible && !isMonochrome;
- return isColor;
- }
- return false;
-}
-
// Retrieve the reprocess input-output format map from the static
// camera characteristics.
Status CameraHidlTest::getZSLInputOutputMap(camera_metadata_t *staticMeta,
@@ -7833,6 +7685,16 @@
ASSERT_TRUE(isUltraHighResCamera && !isMultiCamera);
physicalIds.insert(cameraId);
}
+
+ std::unordered_set<int32_t> physicalRequestKeyIDs;
+ rc = getSupportedKeys(const_cast<camera_metadata_t *>(metadata),
+ ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS, &physicalRequestKeyIDs);
+ ASSERT_TRUE(Status::OK == rc);
+ bool hasTestPatternPhysicalRequestKey = physicalRequestKeyIDs.find(
+ ANDROID_SENSOR_TEST_PATTERN_MODE) != physicalRequestKeyIDs.end();
+ std::unordered_set<int32_t> privacyTestPatternModes;
+ getPrivacyTestPatternModes(metadata, &privacyTestPatternModes);
+
// Map from image format to number of multi-resolution sizes for that format
std::unordered_map<int32_t, size_t> multiResOutputFormatCounterMap;
std::unordered_map<int32_t, size_t> multiResInputFormatCounterMap;
@@ -7854,6 +7716,7 @@
camera_metadata_ro_entry physicalStreamConfigs;
camera_metadata_ro_entry physicalMaxResolutionStreamConfigs;
bool isUltraHighRes = false;
+ std::unordered_set<int32_t> subCameraPrivacyTestPatterns;
if (isPublicId) {
::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> subDevice;
Return<void> ret;
@@ -7884,6 +7747,8 @@
&physicalMultiResStreamConfigs, &physicalStreamConfigs,
&physicalMaxResolutionStreamConfigs, staticMetadata);
isUltraHighRes = isUltraHighResolution(staticMetadata);
+
+ getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns);
});
ASSERT_TRUE(ret.isOk());
} else {
@@ -7910,6 +7775,7 @@
&physicalMultiResStreamConfigs, &physicalStreamConfigs,
&physicalMaxResolutionStreamConfigs, staticMetadata);
isUltraHighRes = isUltraHighResolution(staticMetadata);
+ getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns);
});
ASSERT_TRUE(ret.isOk());
@@ -7926,6 +7792,10 @@
ASSERT_TRUE(ret.isOk());
}
+ if (hasTestPatternPhysicalRequestKey) {
+ ASSERT_TRUE(privacyTestPatternModes == subCameraPrivacyTestPatterns);
+ }
+
if (physicalMultiResStreamConfigs.count > 0) {
ASSERT_GE(deviceVersion, CAMERA_DEVICE_API_VERSION_3_7);
ASSERT_EQ(physicalMultiResStreamConfigs.count % 4, 0);
@@ -8161,6 +8031,20 @@
poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA);
}
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_INFO_DEVICE_STATE_ORIENTATIONS, &entry);
+ if (0 == retcode && entry.count > 0) {
+ ASSERT_TRUE((entry.count % 2) == 0);
+ uint64_t maxPublicState = ((uint64_t) provider::V2_5::DeviceState::FOLDED) << 1;
+ uint64_t vendorStateStart = 1UL << 31; // Reserved for vendor specific states
+ uint64_t stateMask = (1 << vendorStateStart) - 1;
+ stateMask &= ~((1 << maxPublicState) - 1);
+ for (int i = 0; i < entry.count; i += 2){
+ ASSERT_TRUE((entry.data.i64[i] & stateMask) == 0);
+ ASSERT_TRUE((entry.data.i64[i+1] % 90) == 0);
+ }
+ }
+
verifyExtendedSceneModeCharacteristics(metadata);
verifyZoomCharacteristics(metadata);
}
@@ -8921,6 +8805,25 @@
}
}
+void CameraHidlTest::overrideRotateAndCrop(
+ ::android::hardware::hidl_vec<uint8_t> *settings /*in/out*/) {
+ if (settings == nullptr) {
+ return;
+ }
+
+ ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
+ requestMeta.append(reinterpret_cast<camera_metadata_t *> (settings->data()));
+ auto entry = requestMeta.find(ANDROID_SCALER_ROTATE_AND_CROP);
+ if ((entry.count > 0) && (entry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO)) {
+ uint8_t disableRotateAndCrop = ANDROID_SCALER_ROTATE_AND_CROP_NONE;
+ requestMeta.update(ANDROID_SCALER_ROTATE_AND_CROP, &disableRotateAndCrop, 1);
+ settings->releaseData();
+ camera_metadata_t *metaBuffer = requestMeta.release();
+ settings->setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
+ get_camera_metadata_size(metaBuffer), true);
+ }
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CameraHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, CameraHidlTest,
diff --git a/current.txt b/current.txt
index 3893d07..2373c39 100644
--- a/current.txt
+++ b/current.txt
@@ -901,4 +901,7 @@
4a087a308608d146b022ebc15633de989f5f4dfe1491a83fa41763290a82e40d android.hardware.automotive.vehicle@2.0::types
70eb14415391f835fb218b43a1e25f5d6495f098f96fa2acaea70985e98e1ce8 android.hardware.automotive.vehicle@2.0::types
+# HALs released in Android SCv2
+77f6fcf3fd0dd3e424d8a0292094ebd17e4c35454bb9abbd3a6cbed1aba70765 android.hardware.camera.metadata@3.7::types
+
# There should be no more HIDL HALs - please use AIDL instead.
diff --git a/gnss/aidl/default/GnssMeasurementInterface.cpp b/gnss/aidl/default/GnssMeasurementInterface.cpp
index fcc1f98..9e4f7c7 100644
--- a/gnss/aidl/default/GnssMeasurementInterface.cpp
+++ b/gnss/aidl/default/GnssMeasurementInterface.cpp
@@ -19,11 +19,17 @@
#include "GnssMeasurementInterface.h"
#include <aidl/android/hardware/gnss/BnGnss.h>
#include <log/log.h>
+#include "DeviceFileReader.h"
+#include "GnssRawMeasurementParser.h"
+#include "GnssReplayUtils.h"
#include "Utils.h"
namespace aidl::android::hardware::gnss {
using Utils = ::android::hardware::gnss::common::Utils;
+using ReplayUtils = ::android::hardware::gnss::common::ReplayUtils;
+using GnssRawMeasurementParser = ::android::hardware::gnss::common::GnssRawMeasurementParser;
+using DeviceFileReader = ::android::hardware::gnss::common::DeviceFileReader;
std::shared_ptr<IGnssMeasurementCallback> GnssMeasurementInterface::sCallback = nullptr;
@@ -63,9 +69,22 @@
mIsActive = true;
mThread = std::thread([this, enableCorrVecOutputs]() {
while (mIsActive == true) {
- auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
- this->reportMeasurement(measurement);
-
+ std::string rawMeasurementStr = "";
+ if (ReplayUtils::hasGnssDeviceFile() &&
+ ReplayUtils::isGnssRawMeasurement(
+ rawMeasurementStr =
+ DeviceFileReader::Instance().getGnssRawMeasurementData())) {
+ ALOGD("rawMeasurementStr(size: %zu) from device file: %s", rawMeasurementStr.size(),
+ rawMeasurementStr.c_str());
+ auto measurement =
+ GnssRawMeasurementParser::getMeasurementFromStrs(rawMeasurementStr);
+ if (measurement != nullptr) {
+ this->reportMeasurement(*measurement);
+ }
+ } else {
+ auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
+ this->reportMeasurement(measurement);
+ }
std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
}
});
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index 43db873..bdb1569 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -38,9 +38,14 @@
"v2_1/GnssDebug.cpp",
"v2_1/GnssMeasurement.cpp",
"v2_1/GnssMeasurementCorrections.cpp",
+ "DeviceFileReader.cpp",
+ "FixLocationParser.cpp",
+ "GnssRawMeasurementParser.cpp",
+ "GnssReplayUtils.cpp",
"MockLocation.cpp",
- "Utils.cpp",
"NmeaFixInfo.cpp",
+ "ParseUtils.cpp",
+ "Utils.cpp",
],
export_include_dirs: ["include"],
shared_libs: [
diff --git a/gnss/common/utils/default/DeviceFileReader.cpp b/gnss/common/utils/default/DeviceFileReader.cpp
new file mode 100644
index 0000000..dfc086a
--- /dev/null
+++ b/gnss/common/utils/default/DeviceFileReader.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2021 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 "DeviceFileReader.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+void DeviceFileReader::getDataFromDeviceFile(const std::string& command, int mMinIntervalMs) {
+ char inputBuffer[INPUT_BUFFER_SIZE];
+ std::string deviceFilePath = "";
+ if (command == CMD_GET_LOCATION) {
+ deviceFilePath = ReplayUtils::getFixedLocationPath();
+ } else if (command == CMD_GET_RAWMEASUREMENT) {
+ deviceFilePath = ReplayUtils::getGnssPath();
+ } else {
+ // Invalid command
+ return;
+ }
+
+ int mGnssFd = open(deviceFilePath.c_str(), O_RDWR | O_NONBLOCK);
+
+ if (mGnssFd == -1) {
+ return;
+ }
+
+ int bytes_write = write(mGnssFd, command.c_str(), command.size());
+ if (bytes_write <= 0) {
+ close(mGnssFd);
+ return;
+ }
+
+ struct epoll_event ev, events[1];
+ ev.data.fd = mGnssFd;
+ ev.events = EPOLLIN;
+ int epoll_fd = epoll_create1(0);
+ epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mGnssFd, &ev);
+ int bytes_read = -1;
+ std::string inputStr = "";
+ int epoll_ret = epoll_wait(epoll_fd, events, 1, mMinIntervalMs);
+
+ if (epoll_ret == -1) {
+ close(mGnssFd);
+ return;
+ }
+ while (true) {
+ memset(inputBuffer, 0, INPUT_BUFFER_SIZE);
+ bytes_read = read(mGnssFd, &inputBuffer, INPUT_BUFFER_SIZE);
+ if (bytes_read <= 0) {
+ break;
+ }
+ s_buffer_ += std::string(inputBuffer, bytes_read);
+ }
+ close(mGnssFd);
+
+ // Trim end of file mark(\n\n\n\n).
+ auto pos = s_buffer_.find("\n\n\n\n");
+ if (pos != std::string::npos) {
+ inputStr = s_buffer_.substr(0, pos);
+ s_buffer_ = s_buffer_.substr(pos + 4);
+ } else {
+ return;
+ }
+
+ // Cache the injected data.
+ if (command == CMD_GET_LOCATION) {
+ // TODO validate data
+ data_[CMD_GET_LOCATION] = inputStr;
+ } else if (command == CMD_GET_RAWMEASUREMENT) {
+ if (ReplayUtils::isGnssRawMeasurement(inputStr)) {
+ data_[CMD_GET_RAWMEASUREMENT] = inputStr;
+ }
+ }
+}
+
+std::string DeviceFileReader::getLocationData() {
+ std::unique_lock<std::mutex> lock(mMutex);
+ getDataFromDeviceFile(CMD_GET_LOCATION, 20);
+ return data_[CMD_GET_LOCATION];
+}
+
+std::string DeviceFileReader::getGnssRawMeasurementData() {
+ std::unique_lock<std::mutex> lock(mMutex);
+ getDataFromDeviceFile(CMD_GET_RAWMEASUREMENT, 20);
+ return data_[CMD_GET_RAWMEASUREMENT];
+}
+
+DeviceFileReader::DeviceFileReader() {}
+
+DeviceFileReader::~DeviceFileReader() {}
+
+} // namespace common
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/common/utils/default/FixLocationParser.cpp b/gnss/common/utils/default/FixLocationParser.cpp
new file mode 100644
index 0000000..f0177b4
--- /dev/null
+++ b/gnss/common/utils/default/FixLocationParser.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 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 "FixLocationParser.h"
+
+#include <android/hardware/gnss/1.0/IGnss.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+std::unique_ptr<V2_0::GnssLocation> FixLocationParser::getLocationFromInputStr(
+ const std::string& locationStr) {
+ /*
+ * Fix,Provider,LatitudeDegrees,LongitudeDegrees,AltitudeMeters,SpeedMps,
+ * AccuracyMeters,BearingDegrees,UnixTimeMillis,SpeedAccuracyMps,BearingAccuracyDegrees,
+ * elapsedRealtimeNanos
+ */
+ if (locationStr.empty()) {
+ return nullptr;
+ }
+ std::vector<std::string> locationStrRecords;
+ ParseUtils::splitStr(locationStr, LINE_SEPARATOR, locationStrRecords);
+ if (locationStrRecords.empty()) {
+ return nullptr;
+ }
+
+ std::vector<std::string> locationValues;
+ ParseUtils::splitStr(locationStrRecords[0], COMMA_SEPARATOR, locationValues);
+ if (locationValues.size() < 12) {
+ return nullptr;
+ }
+ V2_0::ElapsedRealtime elapsedRealtime = {
+ .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
+ V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
+ .timestampNs = static_cast<uint64_t>(::android::elapsedRealtimeNano()),
+ // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
+ // In an actual implementation provide an estimate of the synchronization uncertainty
+ // or don't set the field.
+ .timeUncertaintyNs = 1020400};
+
+ V1_0::GnssLocation locationV1 = {
+ .gnssLocationFlags = 0xFF,
+ .latitudeDegrees = ParseUtils::tryParseDouble(locationValues[2], 0),
+ .longitudeDegrees = ParseUtils::tryParseDouble(locationValues[3], 0),
+ .altitudeMeters = ParseUtils::tryParseDouble(locationValues[4], 0),
+ .speedMetersPerSec = ParseUtils::tryParsefloat(locationValues[5], 0),
+ .bearingDegrees = ParseUtils::tryParsefloat(locationValues[7], 0),
+ .horizontalAccuracyMeters = ParseUtils::tryParsefloat(locationValues[6], 0),
+ .verticalAccuracyMeters = ParseUtils::tryParsefloat(locationValues[6], 0),
+ .speedAccuracyMetersPerSecond = ParseUtils::tryParsefloat(locationValues[9], 0),
+ .bearingAccuracyDegrees = ParseUtils::tryParsefloat(locationValues[10], 0),
+ .timestamp = ParseUtils::tryParseLongLong(locationValues[8], 0)};
+
+ V2_0::GnssLocation locationV2 = {.v1_0 = locationV1, .elapsedRealtime = elapsedRealtime};
+ return std::make_unique<V2_0::GnssLocation>(locationV2);
+}
+
+} // namespace common
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/common/utils/default/GnssRawMeasurementParser.cpp b/gnss/common/utils/default/GnssRawMeasurementParser.cpp
new file mode 100644
index 0000000..c066229
--- /dev/null
+++ b/gnss/common/utils/default/GnssRawMeasurementParser.cpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2021 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 "GnssRawMeasurementParser.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+using aidl::android::hardware::gnss::ElapsedRealtime;
+using aidl::android::hardware::gnss::GnssClock;
+using aidl::android::hardware::gnss::GnssConstellationType;
+using aidl::android::hardware::gnss::GnssData;
+using aidl::android::hardware::gnss::GnssMeasurement;
+using aidl::android::hardware::gnss::GnssMultipathIndicator;
+using aidl::android::hardware::gnss::GnssSignalType;
+
+using ParseUtils = ::android::hardware::gnss::common::ParseUtils;
+
+std::unordered_map<std::string, int> GnssRawMeasurementParser::getColumnIdNameMappingFromHeader(
+ const std::string& header) {
+ std::vector<std::string> columnNames;
+ std::unordered_map<std::string, int> columnNameIdMapping;
+ std::string s = header;
+ // Trim left spaces
+ s.erase(s.begin(),
+ std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
+ // Trim right spaces
+ s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); })
+ .base(),
+ s.end());
+ // Remove comment symbol, start from `Raw`.
+ s = s.substr(s.find("Raw"));
+
+ ParseUtils::splitStr(s, COMMA_SEPARATOR, columnNames);
+ int columnId = 0;
+ for (auto& name : columnNames) {
+ columnNameIdMapping[name] = columnId++;
+ }
+
+ return columnNameIdMapping;
+}
+
+int GnssRawMeasurementParser::getClockFlags(
+ const std::vector<std::string>& rawMeasurementRecordValues,
+ const std::unordered_map<std::string, int>& columnNameIdMapping) {
+ int clockFlags = 0;
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("LeapSecond")].empty()) {
+ clockFlags |= GnssClock::HAS_LEAP_SECOND;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullBiasNanos")].empty()) {
+ clockFlags |= GnssClock::HAS_FULL_BIAS;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("BiasNanos")].empty()) {
+ clockFlags |= GnssClock::HAS_BIAS;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("BiasUncertaintyNanos")].empty()) {
+ clockFlags |= GnssClock::HAS_BIAS_UNCERTAINTY;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")].empty()) {
+ clockFlags |= GnssClock::HAS_DRIFT;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("DriftUncertaintyNanosPerSecond")]
+ .empty()) {
+ clockFlags |= GnssClock::HAS_DRIFT_UNCERTAINTY;
+ }
+ return clockFlags;
+}
+
+int GnssRawMeasurementParser::getElapsedRealtimeFlags(
+ const std::vector<std::string>& rawMeasurementRecordValues,
+ const std::unordered_map<std::string, int>& columnNameIdMapping) {
+ int elapsedRealtimeFlags = ElapsedRealtime::HAS_TIMESTAMP_NS;
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("TimeUncertaintyNanos")].empty()) {
+ elapsedRealtimeFlags |= ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS;
+ }
+ return elapsedRealtimeFlags;
+}
+
+int GnssRawMeasurementParser::getRawMeasurementFlags(
+ const std::vector<std::string>& rawMeasurementRecordValues,
+ const std::unordered_map<std::string, int>& columnNameIdMapping) {
+ int rawMeasurementFlags = 0;
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("SnrInDb")].empty()) {
+ rawMeasurementFlags |= GnssMeasurement::HAS_SNR;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierFrequencyHz")].empty()) {
+ rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_FREQUENCY;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierCycles")].empty()) {
+ rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_CYCLES;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierPhase")].empty()) {
+ rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_PHASE;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierPhaseUncertainty")].empty()) {
+ rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("AgcDb")].empty()) {
+ rawMeasurementFlags |= GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullInterSignalBiasNanos")].empty()) {
+ rawMeasurementFlags |= GnssMeasurement::HAS_FULL_ISB;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullInterSignalBiasUncertaintyNanos")]
+ .empty()) {
+ rawMeasurementFlags |= GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at("SatelliteInterSignalBiasNanos")]
+ .empty()) {
+ rawMeasurementFlags |= GnssMeasurement::HAS_SATELLITE_ISB;
+ }
+ if (!rawMeasurementRecordValues[columnNameIdMapping.at(
+ "SatelliteInterSignalBiasUncertaintyNanos")]
+ .empty()) {
+ rawMeasurementFlags |= GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY;
+ }
+ // HAS_SATELLITE_PVT and HAS_CORRELATION_VECTOR fields currently not in rawmeasurement
+ // output, need add them later.
+ return rawMeasurementFlags;
+}
+
+GnssConstellationType GnssRawMeasurementParser::getGnssConstellationType(int constellationType) {
+ GnssConstellationType gnssConstellationType =
+ aidl::android::hardware::gnss::GnssConstellationType::UNKNOWN;
+
+ switch (constellationType) {
+ case 1:
+ gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GPS;
+ break;
+ case 2:
+ gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::SBAS;
+ break;
+ case 3:
+ gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GLONASS;
+ break;
+ case 4:
+ gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::QZSS;
+ break;
+ case 5:
+ gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::BEIDOU;
+ break;
+ case 6:
+ gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GALILEO;
+ break;
+ default:
+ gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::UNKNOWN;
+ }
+
+ return gnssConstellationType;
+}
+
+std::unique_ptr<GnssData> GnssRawMeasurementParser::getMeasurementFromStrs(
+ std::string& rawMeasurementStr) {
+ /*
+ * Raw,utcTimeMillis,TimeNanos,LeapSecond,TimeUncertaintyNanos,FullBiasNanos,BiasNanos,
+ * BiasUncertaintyNanos,DriftNanosPerSecond,DriftUncertaintyNanosPerSecond,
+ * HardwareClockDiscontinuityCount,Svid,TimeOffsetNanos,State,ReceivedSvTimeNanos,
+ * ReceivedSvTimeUncertaintyNanos,Cn0DbHz,PseudorangeRateMetersPerSecond,
+ * PseudorangeRateUncertaintyMetersPerSecond,AccumulatedDeltaRangeState,
+ * AccumulatedDeltaRangeMeters,AccumulatedDeltaRangeUncertaintyMeters,CarrierFrequencyHz,
+ * CarrierCycles,CarrierPhase,CarrierPhaseUncertainty,MultipathIndicator,SnrInDb,
+ * ConstellationType,AgcDb,BasebandCn0DbHz,FullInterSignalBiasNanos,
+ * FullInterSignalBiasUncertaintyNanos,SatelliteInterSignalBiasNanos,
+ * SatelliteInterSignalBiasUncertaintyNanos,CodeType,ChipsetElapsedRealtimeNanos
+ */
+ ALOGD("Parsing %zu bytes rawMeasurementStr.", rawMeasurementStr.size());
+ if (rawMeasurementStr.empty()) {
+ return nullptr;
+ }
+ std::vector<std::string> rawMeasurementStrRecords;
+ ParseUtils::splitStr(rawMeasurementStr, LINE_SEPARATOR, rawMeasurementStrRecords);
+ if (rawMeasurementStrRecords.size() <= 1) {
+ ALOGE("Raw GNSS Measurements parser failed. (No records) ");
+ return nullptr;
+ }
+
+ // Get the column name mapping from the header.
+ std::unordered_map<std::string, int> columnNameIdMapping =
+ getColumnIdNameMappingFromHeader(rawMeasurementStrRecords[0]);
+
+ if (columnNameIdMapping.size() < 37 || !ParseUtils::isValidHeader(columnNameIdMapping)) {
+ ALOGE("Raw GNSS Measurements parser failed. (No header or missing columns.) ");
+ return nullptr;
+ }
+
+ // Set GnssClock from 1st record.
+ std::size_t pointer = 1;
+ std::vector<std::string> firstRecordValues;
+ ParseUtils::splitStr(rawMeasurementStrRecords[pointer], COMMA_SEPARATOR, firstRecordValues);
+ GnssClock clock = {
+ .gnssClockFlags = getClockFlags(firstRecordValues, columnNameIdMapping),
+ .timeNs = ParseUtils::tryParseLongLong(
+ firstRecordValues[columnNameIdMapping.at("TimeNanos")], 0),
+ .fullBiasNs = ParseUtils::tryParseLongLong(
+ firstRecordValues[columnNameIdMapping.at("FullBiasNanos")], 0),
+ .biasNs = ParseUtils::tryParseDouble(
+ firstRecordValues[columnNameIdMapping.at("BiasNanos")], 0),
+ .biasUncertaintyNs = ParseUtils::tryParseDouble(
+ firstRecordValues[columnNameIdMapping.at("BiasUncertaintyNanos")], 0),
+ .driftNsps = ParseUtils::tryParseDouble(
+ firstRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")], 0),
+ .driftUncertaintyNsps = ParseUtils::tryParseDouble(
+ firstRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")], 0),
+ .hwClockDiscontinuityCount = ParseUtils::tryParseInt(
+ firstRecordValues[columnNameIdMapping.at("HardwareClockDiscontinuityCount")],
+ 0)};
+
+ ElapsedRealtime timestamp = {
+ .flags = getElapsedRealtimeFlags(firstRecordValues, columnNameIdMapping),
+ .timestampNs = ParseUtils::tryParseLongLong(
+ firstRecordValues[columnNameIdMapping.at("ChipsetElapsedRealtimeNanos")]),
+ .timeUncertaintyNs = ParseUtils::tryParseDouble(
+ firstRecordValues[columnNameIdMapping.at("TimeUncertaintyNanos")], 0)};
+
+ std::vector<GnssMeasurement> measurementsVec;
+ for (pointer = 1; pointer < rawMeasurementStrRecords.size(); pointer++) {
+ std::vector<std::string> rawMeasurementValues;
+ std::string line = rawMeasurementStrRecords[pointer];
+ ParseUtils::splitStr(line, COMMA_SEPARATOR, rawMeasurementValues);
+ GnssSignalType signalType = {
+ .constellation = getGnssConstellationType(ParseUtils::tryParseInt(
+ rawMeasurementValues[columnNameIdMapping.at("ConstellationType")], 0)),
+ .carrierFrequencyHz = ParseUtils::tryParseDouble(
+ rawMeasurementValues[columnNameIdMapping.at("CarrierFrequencyHz")], 0),
+ .codeType = rawMeasurementValues[columnNameIdMapping.at("CodeType")],
+ };
+ GnssMeasurement measurement = {
+ .flags = getRawMeasurementFlags(rawMeasurementValues, columnNameIdMapping),
+ .svid = ParseUtils::tryParseInt(
+ rawMeasurementValues[columnNameIdMapping.at("Svid")], 0),
+ .signalType = signalType,
+ .receivedSvTimeInNs = ParseUtils::tryParseLongLong(
+ rawMeasurementValues[columnNameIdMapping.at("ReceivedSvTimeNanos")], 0),
+ .receivedSvTimeUncertaintyInNs =
+ ParseUtils::tryParseLongLong(rawMeasurementValues[columnNameIdMapping.at(
+ "ReceivedSvTimeUncertaintyNanos")],
+ 0),
+ .antennaCN0DbHz = ParseUtils::tryParseDouble(
+ rawMeasurementValues[columnNameIdMapping.at("Cn0DbHz")], 0),
+ .basebandCN0DbHz = ParseUtils::tryParseDouble(
+ rawMeasurementValues[columnNameIdMapping.at("BasebandCn0DbHz")], 0),
+ .agcLevelDb = ParseUtils::tryParseDouble(
+ rawMeasurementValues[columnNameIdMapping.at("AgcDb")], 0),
+ .pseudorangeRateMps =
+ ParseUtils::tryParseDouble(rawMeasurementValues[columnNameIdMapping.at(
+ "PseudorangeRateMetersPerSecond")],
+ 0),
+ .pseudorangeRateUncertaintyMps = ParseUtils::tryParseDouble(
+ rawMeasurementValues[columnNameIdMapping.at(
+ "PseudorangeRateUncertaintyMetersPerSecond")],
+ 0),
+ .accumulatedDeltaRangeState = ParseUtils::tryParseInt(
+ rawMeasurementValues[columnNameIdMapping.at("AccumulatedDeltaRangeState")],
+ 0),
+ .accumulatedDeltaRangeM = ParseUtils::tryParseDouble(
+ rawMeasurementValues[columnNameIdMapping.at("AccumulatedDeltaRangeMeters")],
+ 0),
+ .accumulatedDeltaRangeUncertaintyM = ParseUtils::tryParseDouble(
+ rawMeasurementValues[columnNameIdMapping.at(
+ "AccumulatedDeltaRangeUncertaintyMeters")],
+ 0),
+ .multipathIndicator = GnssMultipathIndicator::UNKNOWN, // Not in GnssLogger yet.
+ .state = ParseUtils::tryParseInt(
+ rawMeasurementValues[columnNameIdMapping.at("State")], 0),
+ .fullInterSignalBiasNs = ParseUtils::tryParseDouble(rawMeasurementValues[31], 0),
+ .fullInterSignalBiasUncertaintyNs = ParseUtils::tryParseDouble(
+ rawMeasurementValues[columnNameIdMapping.at("FullInterSignalBiasNanos")],
+ 0),
+ .satelliteInterSignalBiasNs =
+ ParseUtils::tryParseDouble(rawMeasurementValues[columnNameIdMapping.at(
+ "SatelliteInterSignalBiasNanos")],
+ 0),
+ .satelliteInterSignalBiasUncertaintyNs = ParseUtils::tryParseDouble(
+ rawMeasurementValues[columnNameIdMapping.at(
+ "SatelliteInterSignalBiasUncertaintyNanos")],
+ 0),
+ .satellitePvt = {},
+ .correlationVectors = {}};
+ measurementsVec.push_back(measurement);
+ }
+
+ GnssData gnssData = {
+ .measurements = measurementsVec, .clock = clock, .elapsedRealtime = timestamp};
+ return std::make_unique<GnssData>(gnssData);
+}
+
+} // namespace common
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/common/utils/default/GnssReplayUtils.cpp b/gnss/common/utils/default/GnssReplayUtils.cpp
new file mode 100644
index 0000000..d6769bd
--- /dev/null
+++ b/gnss/common/utils/default/GnssReplayUtils.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2021 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 "GnssReplayUtils.h"
+
+#include <array>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+std::string ReplayUtils::getGnssPath() {
+ std::array<char, PROPERTY_VALUE_MAX> devname_value;
+
+ devname_value.fill(0);
+ if (property_get("debug.location.gnss.devname", devname_value.begin(), NULL) > 0) {
+ return devname_value.begin();
+ }
+
+ devname_value.fill(0);
+ if (property_get("vendor.ser.gnss-uart", devname_value.begin(), NULL) > 0) {
+ return devname_value.begin();
+ }
+
+ return GNSS_PATH;
+}
+
+std::string ReplayUtils::getFixedLocationPath() {
+ std::array<char, PROPERTY_VALUE_MAX> devname_value;
+
+ devname_value.fill(0);
+ if (property_get("debug.location.fixedlocation.devname", devname_value.begin(), NULL) > 0) {
+ return devname_value.begin();
+ }
+
+ devname_value.fill(0);
+ if (property_get("vendor.ser.gnss-uart", devname_value.begin(), NULL) > 0) {
+ return devname_value.begin();
+ }
+
+ return FIXED_LOCATION_PATH;
+}
+
+bool ReplayUtils::hasGnssDeviceFile() {
+ struct stat sb;
+ return stat(getGnssPath().c_str(), &sb) != -1;
+}
+
+bool ReplayUtils::hasFixedLocationDeviceFile() {
+ struct stat sb;
+ return stat(getFixedLocationPath().c_str(), &sb) != -1;
+}
+
+bool ReplayUtils::isGnssRawMeasurement(const std::string& inputStr) {
+ // TODO: add more logic check to by pass invalid data.
+ return !inputStr.empty() && (inputStr.find("Raw") != std::string::npos);
+}
+
+bool ReplayUtils::isNMEA(const std::string& inputStr) {
+ return !inputStr.empty() && (inputStr.find("$GPRMC,", 0) != std::string::npos ||
+ inputStr.find("$GPRMA,", 0) != std::string::npos);
+}
+
+} // namespace common
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/common/utils/default/ParseUtils.cpp b/gnss/common/utils/default/ParseUtils.cpp
new file mode 100644
index 0000000..648edf7
--- /dev/null
+++ b/gnss/common/utils/default/ParseUtils.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2021 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 <ParseUtils.h>
+#include <sstream>
+#include <stdexcept>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+int ParseUtils::tryParseInt(const std::string& s, int defaultVal) {
+ if (s.empty()) {
+ return defaultVal;
+ } else {
+ return std::stoi(s);
+ }
+}
+
+float ParseUtils::tryParsefloat(const std::string& s, float defaultVal) {
+ if (s.empty()) {
+ return defaultVal;
+ } else {
+ return std::stof(s);
+ }
+}
+
+double ParseUtils::tryParseDouble(const std::string& s, double defaultVal) {
+ if (s.empty()) {
+ return defaultVal;
+ } else {
+ return std::stod(s);
+ }
+}
+
+long ParseUtils::tryParseLong(const std::string& s, long defaultVal) {
+ if (s.empty()) {
+ return defaultVal;
+ } else {
+ return std::stol(s);
+ }
+}
+
+long long ParseUtils::tryParseLongLong(const std::string& s, long long defaultVal) {
+ if (s.empty()) {
+ return defaultVal;
+ } else {
+ return std::stoll(s);
+ }
+}
+
+void ParseUtils::splitStr(const std::string& line, const char& delimiter,
+ std::vector<std::string>& out) {
+ std::istringstream iss(line);
+ std::string item;
+ while (std::getline(iss, item, delimiter)) {
+ out.push_back(item);
+ }
+}
+
+bool ParseUtils::isValidHeader(const std::unordered_map<std::string, int>& columnNameIdMapping) {
+ std::vector<std::string> requiredHeaderColumns = {"Raw",
+ "utcTimeMillis",
+ "TimeNanos",
+ "LeapSecond",
+ "TimeUncertaintyNanos",
+ "FullBiasNanos",
+ "BiasNanos",
+ "BiasUncertaintyNanos",
+ "DriftNanosPerSecond",
+ "DriftUncertaintyNanosPerSecond",
+ "HardwareClockDiscontinuityCount",
+ "Svid",
+ "TimeOffsetNanos",
+ "State",
+ "ReceivedSvTimeNanos",
+ "ReceivedSvTimeUncertaintyNanos",
+ "Cn0DbHz",
+ "PseudorangeRateMetersPerSecond",
+ "PseudorangeRateUncertaintyMetersPerSecond",
+ "AccumulatedDeltaRangeState",
+ "AccumulatedDeltaRangeMeters",
+ "AccumulatedDeltaRangeUncertaintyMeters",
+ "CarrierFrequencyHz",
+ "CarrierCycles",
+ "CarrierPhase",
+ "CarrierPhaseUncertainty",
+ "MultipathIndicator",
+ "SnrInDb",
+ "ConstellationType",
+ "AgcDb",
+ "BasebandCn0DbHz",
+ "FullInterSignalBiasNanos",
+ "FullInterSignalBiasUncertaintyNanos",
+ "SatelliteInterSignalBiasNanos",
+ "SatelliteInterSignalBiasUncertaintyNanos",
+ "CodeType",
+ "ChipsetElapsedRealtimeNanos"};
+
+ for (const auto& columnName : requiredHeaderColumns) {
+ if (columnNameIdMapping.find(columnName) == columnNameIdMapping.end()) {
+ ALOGE("Missing column %s in header.", columnName.c_str());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace common
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/common/utils/default/include/Constants.h b/gnss/common/utils/default/include/Constants.h
index 22afee1..489413e 100644
--- a/gnss/common/utils/default/include/Constants.h
+++ b/gnss/common/utils/default/include/Constants.h
@@ -34,6 +34,19 @@
const float kGloG1FreqHz = 1602.0 * 1e6;
const float kIrnssL5FreqHz = 1176.45 * 1e6;
+// Location replay constants
+constexpr char GNSS_PATH[] = "/dev/gnss0";
+constexpr char FIXED_LOCATION_PATH[] = "/dev/gnss1";
+constexpr int INPUT_BUFFER_SIZE = 256;
+constexpr char CMD_GET_LOCATION[] = "CMD_GET_LOCATION";
+constexpr char CMD_GET_RAWMEASUREMENT[] = "CMD_GET_RAWMEASUREMENT";
+constexpr char LINE_SEPARATOR = '\n';
+constexpr char COMMA_SEPARATOR = ',';
+constexpr char GPGA_RECORD_TAG[] = "$GPGGA";
+constexpr char GPRMC_RECORD_TAG[] = "$GPRMC";
+constexpr double TIMESTAMP_EPSILON = 0.001;
+constexpr int MIN_COL_NUM = 13;
+
} // namespace common
} // namespace gnss
} // namespace hardware
diff --git a/gnss/common/utils/default/include/DeviceFileReader.h b/gnss/common/utils/default/include/DeviceFileReader.h
new file mode 100644
index 0000000..c2a5c5f
--- /dev/null
+++ b/gnss/common/utils/default/include/DeviceFileReader.h
@@ -0,0 +1,53 @@
+
+/*
+ * Copyright (C) 2021 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_gnss_common_default_DeviceFileReader_H_
+#define android_hardware_gnss_common_default_DeviceFileReader_H_
+
+#include <log/log.h>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include "Constants.h"
+#include "GnssReplayUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+class DeviceFileReader {
+ public:
+ static DeviceFileReader& Instance() {
+ static DeviceFileReader reader;
+ return reader;
+ }
+ std::string getLocationData();
+ std::string getGnssRawMeasurementData();
+ void getDataFromDeviceFile(const std::string& command, int mMinIntervalMs);
+
+ private:
+ DeviceFileReader();
+ ~DeviceFileReader();
+ std::unordered_map<std::string, std::string> data_;
+ std::string s_buffer_;
+ std::mutex mMutex;
+};
+} // namespace common
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_common_default_DeviceFileReader_H_
\ No newline at end of file
diff --git a/gnss/common/utils/default/include/FixLocationParser.h b/gnss/common/utils/default/include/FixLocationParser.h
new file mode 100644
index 0000000..19748a9
--- /dev/null
+++ b/gnss/common/utils/default/include/FixLocationParser.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 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_gnss_common_default_FixLocationParser_H_
+#define android_hardware_gnss_common_default_FixLocationParser_H_
+
+#include <android/hardware/gnss/2.0/IGnss.h>
+
+#include <utils/SystemClock.h>
+#include <string>
+#include <vector>
+
+#include <Constants.h>
+#include <Utils.h>
+#include <log/log.h>
+#include "Constants.h"
+#include "ParseUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+struct FixLocationParser {
+ public:
+ static std::unique_ptr<V2_0::GnssLocation> getLocationFromInputStr(const std::string& inputStr);
+};
+
+} // namespace common
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_common_default_FixLocationParser_H_
diff --git a/gnss/common/utils/default/include/GnssRawMeasurementParser.h b/gnss/common/utils/default/include/GnssRawMeasurementParser.h
new file mode 100644
index 0000000..7d6b4ef
--- /dev/null
+++ b/gnss/common/utils/default/include/GnssRawMeasurementParser.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 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_gnss_common_default_GnssRawMeasurementParser_H_
+#define android_hardware_gnss_common_default_GnssRawMeasurementParser_H_
+
+#include <aidl/android/hardware/gnss/BnGnss.h>
+#include <log/log.h>
+#include <utils/SystemClock.h>
+#include <string>
+#include <unordered_map>
+
+#include "Constants.h"
+#include "ParseUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+struct GnssRawMeasurementParser {
+ static std::unique_ptr<aidl::android::hardware::gnss::GnssData> getMeasurementFromStrs(
+ std::string& rawMeasurementStr);
+ static int getClockFlags(const std::vector<std::string>& rawMeasurementRecordValues,
+ const std::unordered_map<std::string, int>& columnNameIdMapping);
+ static int getElapsedRealtimeFlags(
+ const std::vector<std::string>& rawMeasurementRecordValues,
+ const std::unordered_map<std::string, int>& columnNameIdMapping);
+ static int getRawMeasurementFlags(
+ const std::vector<std::string>& rawMeasurementRecordValues,
+ const std::unordered_map<std::string, int>& columnNameIdMapping);
+ static std::unordered_map<std::string, int> getColumnIdNameMappingFromHeader(
+ const std::string& header);
+ static aidl::android::hardware::gnss::GnssConstellationType getGnssConstellationType(
+ int constellationType);
+};
+
+} // namespace common
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_common_default_GnssRawMeasurementParser_H_
\ No newline at end of file
diff --git a/gnss/common/utils/default/include/GnssReplayUtils.h b/gnss/common/utils/default/include/GnssReplayUtils.h
new file mode 100644
index 0000000..d1bbed4
--- /dev/null
+++ b/gnss/common/utils/default/include/GnssReplayUtils.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 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_gnss_common_GnssReplayUtils_H_
+#define android_hardware_gnss_common_GnssReplayUtils_H_
+
+#include <cutils/properties.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <log/log.h>
+#include <sys/epoll.h>
+#include <sys/stat.h>
+#include <chrono>
+#include <string>
+#include <thread>
+
+#include "Constants.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+struct ReplayUtils {
+ static std::string getGnssPath();
+
+ static std::string getFixedLocationPath();
+
+ static std::string getDataFromDeviceFile(const std::string& command, int mMinIntervalMs);
+
+ static bool hasGnssDeviceFile();
+
+ static bool hasFixedLocationDeviceFile();
+
+ static bool isGnssRawMeasurement(const std::string& inputStr);
+
+ static bool isNMEA(const std::string& inputStr);
+};
+
+} // namespace common
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_common_GnssReplayUtils_H_
diff --git a/gnss/common/utils/default/include/NmeaFixInfo.h b/gnss/common/utils/default/include/NmeaFixInfo.h
index c96eece..5c27045 100644
--- a/gnss/common/utils/default/include/NmeaFixInfo.h
+++ b/gnss/common/utils/default/include/NmeaFixInfo.h
@@ -27,13 +27,6 @@
namespace gnss {
namespace common {
-constexpr char GPGA_RECORD_TAG[] = "$GPGGA";
-constexpr char GPRMC_RECORD_TAG[] = "$GPRMC";
-constexpr char LINE_SEPARATOR = '\n';
-constexpr char COMMA_SEPARATOR = ',';
-constexpr double TIMESTAMP_EPSILON = 0.001;
-constexpr int MIN_COL_NUM = 13;
-
/** Helper class to parse and store the GNSS fix details information. */
class NmeaFixInfo {
private:
diff --git a/gnss/common/utils/default/include/ParseUtils.h b/gnss/common/utils/default/include/ParseUtils.h
new file mode 100644
index 0000000..3a56313
--- /dev/null
+++ b/gnss/common/utils/default/include/ParseUtils.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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_gnss_common_default_ParseUtils_H_
+#define android_hardware_gnss_common_default_ParseUtils_H_
+
+#include <log/log.h>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+struct ParseUtils {
+ static int tryParseInt(const std::string& s, int defaultVal = 0);
+ static float tryParsefloat(const std::string& s, float defaultVal = 0.0);
+ static double tryParseDouble(const std::string& s, double defaultVal = 0.0);
+ static long tryParseLong(const std::string& s, long defaultVal = 0);
+ static long long tryParseLongLong(const std::string& s, long long defaultVal = 0);
+ static void splitStr(const std::string& line, const char& delimiter,
+ std::vector<std::string>& out);
+ static bool isValidHeader(const std::unordered_map<std::string, int>& columnNameIdMapping);
+};
+
+} // namespace common
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_common_default_ParseUtils_H_
\ No newline at end of file
diff --git a/gnss/common/utils/default/include/v2_1/GnssTemplate.h b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
index 131af24..473e587 100644
--- a/gnss/common/utils/default/include/v2_1/GnssTemplate.h
+++ b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
@@ -30,13 +30,15 @@
#include <cutils/properties.h>
+#include "DeviceFileReader.h"
+#include "FixLocationParser.h"
#include "GnssAntennaInfo.h"
#include "GnssConfiguration.h"
#include "GnssDebug.h"
#include "GnssMeasurement.h"
#include "GnssMeasurementCorrections.h"
+#include "GnssReplayUtils.h"
#include "MockLocation.h"
-#include "NmeaFixInfo.h"
#include "Utils.h"
namespace android::hardware::gnss::common::implementation {
@@ -159,53 +161,13 @@
template <class T_IGnss>
std::unique_ptr<V2_0::GnssLocation> GnssTemplate<T_IGnss>::getLocationFromHW() {
- char inputBuffer[INPUT_BUFFER_SIZE];
- if (!mHardwareModeChecked) {
- // default using gnss0
- const char * gnss_dev_path = GNSS_PATH;
- char devname_value[PROPERTY_VALUE_MAX] = "";
- if (property_get("debug.location.gnss.devname", devname_value, NULL) > 0) {
- gnss_dev_path = devname_value;
- ALOGD("using %s instead of the default %s", gnss_dev_path, GNSS_PATH);
- }
-
- mGnssFd = open(gnss_dev_path, O_RDWR | O_NONBLOCK);
- if (mGnssFd == -1) {
- ALOGW("Failed to open %s errno: %d", gnss_dev_path, errno);
- }
- mHardwareModeChecked = true;
- }
-
- if (mGnssFd == -1) {
+ mHardwareModeChecked = true;
+ if (!ReplayUtils::hasFixedLocationDeviceFile()) {
return nullptr;
}
-
- int bytes_write = write(mGnssFd, CMD_GET_LOCATION, strlen(CMD_GET_LOCATION));
- if (bytes_write <= 0) {
- return nullptr;
- }
-
- struct epoll_event ev, events[1];
- ev.data.fd = mGnssFd;
- ev.events = EPOLLIN;
- int epoll_fd = epoll_create1(0);
- epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mGnssFd, &ev);
- int bytes_read = -1;
- std::string inputStr = "";
- int epoll_ret = epoll_wait(epoll_fd, events, 1, mMinIntervalMs);
-
- if (epoll_ret == -1) {
- return nullptr;
- }
- while (true) {
- memset(inputBuffer, 0, INPUT_BUFFER_SIZE);
- bytes_read = read(mGnssFd, &inputBuffer, INPUT_BUFFER_SIZE);
- if (bytes_read <= 0) {
- break;
- }
- inputStr += std::string(inputBuffer, bytes_read);
- }
- return NmeaFixInfo::getLocationFromInputStr(inputStr);
+ std::string inputStr =
+ ::android::hardware::gnss::common::DeviceFileReader::Instance().getLocationData();
+ return FixLocationParser::getLocationFromInputStr(inputStr);
}
template <class T_IGnss>
@@ -223,14 +185,8 @@
this->reportSvStatus(svStatus);
auto currentLocation = getLocationFromHW();
notePowerConsumption();
- if (mGnssFd != -1) {
- // Only report location if the return from hardware is valid
- // note that we can not merge these two "if" together, if didn't
- // get location from hardware, we shouldn't report location, not
- // report the "default" one.
- if (currentLocation != nullptr) {
- this->reportLocation(*currentLocation);
- }
+ if (currentLocation != nullptr) {
+ this->reportLocation(*currentLocation);
} else {
if (sGnssCallback_2_1 != nullptr || sGnssCallback_2_0 != nullptr) {
const auto location = Utils::getMockLocationV2_0();
diff --git a/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
index 1ead138..ccbc5b1 100644
--- a/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
+++ b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
@@ -30,7 +30,7 @@
std::vector<Display> GraphicsComposerCallback::getDisplays() const {
std::lock_guard<std::mutex> lock(mMutex);
- return std::vector<Display>(mDisplays.begin(), mDisplays.end());
+ return mDisplays;
}
int GraphicsComposerCallback::getInvalidHotplugCount() const {
@@ -51,12 +51,17 @@
Return<void> GraphicsComposerCallback::onHotplug(Display display, Connection connection) {
std::lock_guard<std::mutex> lock(mMutex);
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
if (connection == Connection::CONNECTED) {
- if (!mDisplays.insert(display).second) {
+ if (it == mDisplays.end()) {
+ mDisplays.push_back(display);
+ } else {
mInvalidHotplugCount++;
}
} else if (connection == Connection::DISCONNECTED) {
- if (!mDisplays.erase(display)) {
+ if (it != mDisplays.end()) {
+ mDisplays.erase(it);
+ } else {
mInvalidHotplugCount++;
}
}
@@ -67,7 +72,8 @@
Return<void> GraphicsComposerCallback::onRefresh(Display display) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mDisplays.count(display) == 0) {
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+ if (it == mDisplays.end()) {
mInvalidRefreshCount++;
}
@@ -77,7 +83,8 @@
Return<void> GraphicsComposerCallback::onVsync(Display display, int64_t) {
std::lock_guard<std::mutex> lock(mMutex);
- if (!mVsyncAllowed || mDisplays.count(display) == 0) {
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+ if (!mVsyncAllowed || it == mDisplays.end()) {
mInvalidVsyncCount++;
}
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
index e3c348f..da64052 100644
--- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
@@ -19,7 +19,7 @@
#include <android/hardware/graphics/composer/2.1/IComposerCallback.h>
#include <mutex>
-#include <unordered_set>
+#include <vector>
namespace android {
namespace hardware {
@@ -48,7 +48,7 @@
mutable std::mutex mMutex;
// the set of all currently connected displays
- std::unordered_set<Display> mDisplays;
+ std::vector<Display> mDisplays;
// true only when vsync is enabled
bool mVsyncAllowed = true;
diff --git a/graphics/composer/2.4/utils/vts/GraphicsComposerCallback.cpp b/graphics/composer/2.4/utils/vts/GraphicsComposerCallback.cpp
index c9366a8..51e1ab7 100644
--- a/graphics/composer/2.4/utils/vts/GraphicsComposerCallback.cpp
+++ b/graphics/composer/2.4/utils/vts/GraphicsComposerCallback.cpp
@@ -25,7 +25,7 @@
std::vector<Display> GraphicsComposerCallback::getDisplays() const {
std::lock_guard<std::mutex> lock(mMutex);
- return std::vector<Display>(mDisplays.begin(), mDisplays.end());
+ return mDisplays;
}
int32_t GraphicsComposerCallback::getInvalidHotplugCount() const {
@@ -71,12 +71,17 @@
Return<void> GraphicsComposerCallback::onHotplug(Display display, Connection connection) {
std::lock_guard<std::mutex> lock(mMutex);
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
if (connection == Connection::CONNECTED) {
- if (!mDisplays.insert(display).second) {
+ if (it == mDisplays.end()) {
+ mDisplays.push_back(display);
+ } else {
mInvalidHotplugCount++;
}
} else if (connection == Connection::DISCONNECTED) {
- if (!mDisplays.erase(display)) {
+ if (it != mDisplays.end()) {
+ mDisplays.erase(it);
+ } else {
mInvalidHotplugCount++;
}
}
@@ -87,7 +92,8 @@
Return<void> GraphicsComposerCallback::onRefresh(Display display) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mDisplays.count(display) == 0) {
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+ if (it == mDisplays.end()) {
mInvalidRefreshCount++;
}
@@ -106,7 +112,8 @@
Return<void> GraphicsComposerCallback::onVsync_2_4(Display display, int64_t, VsyncPeriodNanos) {
std::lock_guard<std::mutex> lock(mMutex);
- if (!mVsyncAllowed || mDisplays.count(display) == 0) {
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+ if (!mVsyncAllowed || it == mDisplays.end()) {
mInvalidVsync_2_4Count++;
}
@@ -117,7 +124,8 @@
Display display, const VsyncPeriodChangeTimeline& updatedTimeline) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mDisplays.count(display) == 0) {
+ auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+ if (it == mDisplays.end()) {
mInvalidVsyncPeriodChangeCount++;
}
@@ -134,4 +142,4 @@
return Void();
}
-} // namespace android::hardware::graphics::composer::V2_4::vts
\ No newline at end of file
+} // namespace android::hardware::graphics::composer::V2_4::vts
diff --git a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h
index f4e23ae..c03070b 100644
--- a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h
+++ b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h
@@ -18,7 +18,7 @@
#include <android/hardware/graphics/composer/2.4/IComposerCallback.h>
#include <mutex>
-#include <unordered_set>
+#include <vector>
namespace android::hardware::graphics::composer::V2_4::vts {
@@ -56,7 +56,7 @@
mutable std::mutex mMutex;
// the set of all currently connected displays
- std::unordered_set<Display> mDisplays;
+ std::vector<Display> mDisplays;
// true only when vsync is enabled
bool mVsyncAllowed = true;
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index 5aceda7..b071f71 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -19,8 +19,6 @@
#include <algorithm>
#include <regex>
#include <thread>
-#include <unordered_map>
-#include <utility>
#include <android-base/logging.h>
#include <android-base/properties.h>
@@ -317,59 +315,6 @@
}
}
-TEST_P(GraphicsComposerHidlTest, GetDisplayAttribute_2_4_ConfigsInAGroupDifferOnlyByVsyncPeriod) {
- struct Resolution {
- int32_t width, height;
- };
- struct Dpi {
- int32_t x, y;
- };
- for (const auto& display : mDisplays) {
- std::vector<Config> configs = mComposerClient->getDisplayConfigs(display.get());
- std::unordered_map<int32_t, Resolution> configGroupToResolutionMap;
- std::unordered_map<int32_t, Dpi> configGroupToDpiMap;
- for (auto config : configs) {
- const auto configGroup = mComposerClient->getDisplayAttribute_2_4(
- display.get(), config, IComposerClient::Attribute::CONFIG_GROUP);
- const auto width = mComposerClient->getDisplayAttribute_2_4(
- display.get(), config, IComposerClient::Attribute::WIDTH);
- const auto height = mComposerClient->getDisplayAttribute_2_4(
- display.get(), config, IComposerClient::Attribute::HEIGHT);
- if (configGroupToResolutionMap.find(configGroup) == configGroupToResolutionMap.end()) {
- configGroupToResolutionMap[configGroup] = {width, height};
- }
- EXPECT_EQ(configGroupToResolutionMap[configGroup].width, width);
- EXPECT_EQ(configGroupToResolutionMap[configGroup].height, height);
-
- int32_t dpiX = -1;
- mComposerClient->getRaw()->getDisplayAttribute_2_4(
- display.get(), config, IComposerClient::Attribute::DPI_X,
- [&](const auto& tmpError, const auto& value) {
- if (tmpError == Error::NONE) {
- dpiX = value;
- }
- });
- int32_t dpiY = -1;
- mComposerClient->getRaw()->getDisplayAttribute_2_4(
- display.get(), config, IComposerClient::Attribute::DPI_Y,
- [&](const auto& tmpError, const auto& value) {
- if (tmpError == Error::NONE) {
- dpiY = value;
- }
- });
- if (dpiX == -1 && dpiY == -1) {
- continue;
- }
-
- if (configGroupToDpiMap.find(configGroup) == configGroupToDpiMap.end()) {
- configGroupToDpiMap[configGroup] = {dpiX, dpiY};
- }
- EXPECT_EQ(configGroupToDpiMap[configGroup].x, dpiX);
- EXPECT_EQ(configGroupToDpiMap[configGroup].y, dpiY);
- }
- }
-}
-
TEST_P(GraphicsComposerHidlTest, getDisplayVsyncPeriod_BadDisplay) {
VsyncPeriodNanos vsyncPeriodNanos;
EXPECT_EQ(Error::BAD_DISPLAY,
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index f8f5cff..4549f51 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -32,23 +32,17 @@
EXPECT_EQ(std::cv_status::no_timeout, wait());
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-
- if (getRadioHalCapabilities()) {
- ASSERT_TRUE(CheckAnyOfErrors(
- radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
- } else {
- ASSERT_TRUE(CheckAnyOfErrors(
- radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::NONE,
- ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
- ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
- ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
- ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
- ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
- ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
- ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
- }
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
+ ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
}
/*
@@ -74,23 +68,17 @@
EXPECT_EQ(std::cv_status::no_timeout, wait());
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-
- if (getRadioHalCapabilities()) {
- ASSERT_TRUE(CheckAnyOfErrors(
- radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
- } else {
- ASSERT_TRUE(CheckAnyOfErrors(
- radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::NONE,
- ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
- ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
- ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
- ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
- ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
- ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
- ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
- }
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
+ ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
}
}
@@ -515,7 +503,8 @@
if (getRadioHalCapabilities()) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+ {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::NONE}));
} else {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
@@ -537,7 +526,8 @@
if (getRadioHalCapabilities()) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+ {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::NONE}));
} else {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
@@ -559,7 +549,8 @@
if (getRadioHalCapabilities()) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+ {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::NONE}));
} else {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
@@ -580,7 +571,8 @@
if (getRadioHalCapabilities()) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+ {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::NONE}));
} else {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_6->rspInfo.error,
@@ -609,12 +601,16 @@
::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE}));
+ // Give some time for modem to fully power up the SIM card
+ sleep(MODEM_SET_SIM_POWER_DELAY_IN_SECONDS);
+
// setSimCardPower_1_6 does not return until the request is handled, and should not trigger
// CardState::ABSENT when turning off power
if (radioRsp_v1_6->rspInfo.error == ::android::hardware::radio::V1_6::RadioError::NONE) {
/* Wait some time for setting sim power down and then verify it */
updateSimCardStatus();
- EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.base.cardState);
+ // We cannot assert the consistency of CardState here due to b/203031664
+ // EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.base.cardState);
// applications should be an empty vector of AppStatus
EXPECT_EQ(0, cardStatus.applications.size());
}
@@ -631,6 +627,9 @@
::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE}));
+ // Give some time for modem to fully power up the SIM card
+ sleep(MODEM_SET_SIM_POWER_DELAY_IN_SECONDS);
+
// setSimCardPower_1_6 does not return until the request is handled. Just verify that we still
// have CardState::PRESENT after turning the power back on
if (radioRsp_v1_6->rspInfo.error == ::android::hardware::radio::V1_6::RadioError::NONE) {
@@ -646,6 +645,10 @@
if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
ALOGI("Skipping emergencyDial because voice call is not supported in device");
return;
+ } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+ !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+ ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+ return;
} else {
ALOGI("Running emergencyDial because voice call is supported in device");
}
@@ -700,6 +703,10 @@
if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
ALOGI("Skipping emergencyDial because voice call is not supported in device");
return;
+ } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+ !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+ ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+ return;
} else {
ALOGI("Running emergencyDial because voice call is supported in device");
}
@@ -753,6 +760,10 @@
if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
ALOGI("Skipping emergencyDial because voice call is not supported in device");
return;
+ } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+ !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+ ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+ return;
} else {
ALOGI("Running emergencyDial because voice call is supported in device");
}
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
index 54c2977..f041865 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
+++ b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
@@ -47,6 +47,7 @@
#define MODEM_EMERGENCY_CALL_ESTABLISH_TIME 3
#define MODEM_EMERGENCY_CALL_DISCONNECT_TIME 3
+#define MODEM_SET_SIM_POWER_DELAY_IN_SECONDS 2
#define RADIO_SERVICE_SLOT1_NAME "slot1" // HAL instance name for SIM slot 1 or single SIM device
#define RADIO_SERVICE_SLOT2_NAME "slot2" // HAL instance name for SIM slot 2 on dual SIM device
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 26ed344..64550ef 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -50,7 +50,7 @@
vector<KeyCharacteristics> attest_key_characteristics;
vector<Certificate> attest_key_cert_chain;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(size, 65537)
+ .RsaKey(size, 65537)
.AttestKey()
.SetDefaultValidity(),
{} /* attestation signing key */, &attest_key.keyBlob,
@@ -200,7 +200,7 @@
vector<Certificate> attest_key_cert_chain;
ASSERT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(2048, 65537)
+ .RsaKey(2048, 65537)
.AttestKey()
.AttestationChallenge(challenge)
.AttestationApplicationId(app_id)
@@ -299,7 +299,7 @@
EXPECT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(2048, 65537)
+ .RsaKey(2048, 65537)
.AttestKey()
.AttestationChallenge("foo")
.AttestationApplicationId("bar")
@@ -371,7 +371,7 @@
EXPECT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(EcCurve::P_256)
+ .EcdsaKey(EcCurve::P_256)
.AttestKey()
.AttestationChallenge("foo")
.AttestationApplicationId("bar")
@@ -446,7 +446,7 @@
if ((i & 0x1) == 1) {
EXPECT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(EcCurve::P_256)
+ .EcdsaKey(EcCurve::P_256)
.AttestKey()
.AttestationChallenge("foo")
.AttestationApplicationId("bar")
@@ -459,7 +459,7 @@
} else {
EXPECT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(2048, 65537)
+ .RsaKey(2048, 65537)
.AttestKey()
.AttestationChallenge("foo")
.AttestationApplicationId("bar")
@@ -509,7 +509,7 @@
vector<KeyCharacteristics> attest_key_characteristics;
vector<Certificate> attest_key_cert_chain;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(size, 65537)
+ .RsaKey(size, 65537)
.AttestKey()
.SetDefaultValidity(),
{} /* attestation signing key */, &attest_key.keyBlob,
@@ -555,12 +555,12 @@
AttestationKey attest_key;
vector<KeyCharacteristics> attest_key_characteristics;
vector<Certificate> attest_key_cert_chain;
- ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(curve)
- .AttestKey()
- .SetDefaultValidity(),
- {} /* attestation signing key */, &attest_key.keyBlob,
- &attest_key_characteristics, &attest_key_cert_chain));
+ ASSERT_EQ(
+ ErrorCode::OK,
+ GenerateKey(
+ AuthorizationSetBuilder().EcdsaKey(curve).AttestKey().SetDefaultValidity(),
+ {} /* attestation signing key */, &attest_key.keyBlob,
+ &attest_key_characteristics, &attest_key_cert_chain));
ASSERT_GT(attest_key_cert_chain.size(), 0);
EXPECT_EQ(attest_key_cert_chain.size(), 1);
@@ -671,7 +671,7 @@
vector<KeyCharacteristics> attest_key_characteristics;
vector<Certificate> attest_key_cert_chain;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(EcCurve::P_256)
+ .EcdsaKey(EcCurve::P_256)
.AttestKey()
.SetDefaultValidity(),
{} /* attestation signing key */, &attest_key.keyBlob,
@@ -735,7 +735,7 @@
vector<KeyCharacteristics> attest_key_characteristics;
vector<Certificate> attest_key_cert_chain;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(EcCurve::P_256)
+ .EcdsaKey(EcCurve::P_256)
.AttestKey()
.SetDefaultValidity(),
{} /* attestation signing key */, &attest_key.keyBlob,
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
index d7abf07..79716b1 100644
--- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -76,6 +76,7 @@
.Digest(Digest::SHA_2_256)
.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
.Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .Authorization(TAG_CREATION_DATETIME, 1619621648000)
.AttestationChallenge("challenge")
.AttestationApplicationId("foo")
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -102,6 +103,7 @@
.EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .Authorization(TAG_CREATION_DATETIME, 1619621648000)
.AttestationChallenge("challenge")
.AttestationApplicationId("foo")
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -129,6 +131,7 @@
.Digest(Digest::SHA_2_256)
.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
.Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .Authorization(TAG_CREATION_DATETIME, 1619621648000)
.AttestationChallenge("challenge")
.AttestationApplicationId("foo")
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -184,6 +187,7 @@
.EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .Authorization(TAG_CREATION_DATETIME, 1619621648000)
.AttestationChallenge("challenge")
.AttestationApplicationId("foo")
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -242,14 +246,16 @@
for (const KeyParameter& tag : attestation_id_tags) {
SCOPED_TRACE(testing::Message() << "+tag-" << tag);
- AuthorizationSetBuilder builder = AuthorizationSetBuilder()
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(EcCurve::P_256)
- .Digest(Digest::SHA_2_256)
- .Authorization(TAG_INCLUDE_UNIQUE_ID)
- .AttestationChallenge("challenge")
- .AttestationApplicationId("foo")
- .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
+ AuthorizationSetBuilder builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
builder.push_back(tag);
auto result = GenerateKey(builder, &key_blob, &key_characteristics);
@@ -310,14 +316,16 @@
for (const KeyParameter& invalid_tag : attestation_id_tags) {
SCOPED_TRACE(testing::Message() << "+tag-" << invalid_tag);
- AuthorizationSetBuilder builder = AuthorizationSetBuilder()
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(EcCurve::P_256)
- .Digest(Digest::SHA_2_256)
- .Authorization(TAG_INCLUDE_UNIQUE_ID)
- .AttestationChallenge("challenge")
- .AttestationApplicationId("foo")
- .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
+ AuthorizationSetBuilder builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
// Add the tag that doesn't match the local device's real ID.
builder.push_back(invalid_tag);
auto result = GenerateKey(builder, &key_blob, &key_characteristics);
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 2032411..8e35c91 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -1298,7 +1298,8 @@
AuthorizationSet expected_sw_enforced, //
AuthorizationSet expected_hw_enforced, //
SecurityLevel security_level,
- const vector<uint8_t>& attestation_cert) {
+ const vector<uint8_t>& attestation_cert,
+ vector<uint8_t>* unique_id) {
X509_Ptr cert(parse_cert_blob(attestation_cert));
EXPECT_TRUE(!!cert.get());
if (!cert.get()) return false;
@@ -1458,6 +1459,10 @@
expected_hw_enforced.Sort();
EXPECT_EQ(filtered_tags(expected_hw_enforced), filtered_tags(att_hw_enforced));
+ if (unique_id != nullptr) {
+ *unique_id = att_unique_id;
+ }
+
return true;
}
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index ec3fcf6..7b3b9d4 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -338,7 +338,8 @@
AuthorizationSet expected_sw_enforced, //
AuthorizationSet expected_hw_enforced, //
SecurityLevel security_level,
- const vector<uint8_t>& attestation_cert);
+ const vector<uint8_t>& attestation_cert,
+ vector<uint8_t>* unique_id = nullptr);
string bin2hex(const vector<uint8_t>& data);
X509_Ptr parse_cert_blob(const vector<uint8_t>& blob);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 2a0ee7f..4d7f1b8 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -1550,6 +1550,102 @@
}
/*
+ * NewKeyGenerationTest.EcdsaAttestationUniqueId
+ *
+ * Verifies that creation of an attested ECDSA key with a UNIQUE_ID included.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAttestationUniqueId) {
+ auto get_unique_id = [this](const std::string& app_id, uint64_t datetime,
+ vector<uint8_t>* unique_id, bool reset = false) {
+ auto challenge = "hello";
+ auto subject = "cert subj 2";
+ vector<uint8_t> subject_der(make_name_from_str(subject));
+ uint64_t serial_int = 0x1010;
+ vector<uint8_t> serial_blob(build_serial_blob(serial_int));
+ AuthorizationSetBuilder builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_CREATION_DATETIME, datetime)
+ .SetDefaultValidity();
+ if (reset) {
+ builder.Authorization(TAG_RESET_SINCE_ID_ROTATION);
+ }
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(builder));
+ ASSERT_GT(key_blob_.size(), 0U);
+
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+ ASSERT_GT(cert_chain_.size(), 0);
+ verify_subject_and_serial(cert_chain_[0], serial_int, subject, /* self_signed = */ false);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics_);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics_);
+
+ // Check that the unique ID field in the extension is non-empty.
+ EXPECT_TRUE(verify_attestation_record(challenge, app_id, sw_enforced, hw_enforced,
+ SecLevel(), cert_chain_[0].encodedCertificate,
+ unique_id));
+ EXPECT_GT(unique_id->size(), 0);
+ CheckedDeleteKey();
+ };
+
+ // Generate unique ID
+ auto app_id = "foo";
+ uint64_t cert_date = 1619621648000; // Wed Apr 28 14:54:08 2021 in ms since epoch
+ vector<uint8_t> unique_id;
+ get_unique_id(app_id, cert_date, &unique_id);
+
+ // Generating a new key with the same parameters should give the same unique ID.
+ vector<uint8_t> unique_id2;
+ get_unique_id(app_id, cert_date, &unique_id2);
+ EXPECT_EQ(unique_id, unique_id2);
+
+ // Generating a new key with a slightly different date should give the same unique ID.
+ uint64_t rounded_date = cert_date / 2592000000LLU;
+ uint64_t min_date = rounded_date * 2592000000LLU;
+ uint64_t max_date = ((rounded_date + 1) * 2592000000LLU) - 1;
+
+ vector<uint8_t> unique_id3;
+ get_unique_id(app_id, min_date, &unique_id3);
+ EXPECT_EQ(unique_id, unique_id3);
+
+ vector<uint8_t> unique_id4;
+ get_unique_id(app_id, max_date, &unique_id4);
+ EXPECT_EQ(unique_id, unique_id4);
+
+ // A different attestation application ID should yield a different unique ID.
+ auto app_id2 = "different_foo";
+ vector<uint8_t> unique_id5;
+ get_unique_id(app_id2, cert_date, &unique_id5);
+ EXPECT_NE(unique_id, unique_id5);
+
+ // A radically different date should yield a different unique ID.
+ vector<uint8_t> unique_id6;
+ get_unique_id(app_id, 1611621648000, &unique_id6);
+ EXPECT_NE(unique_id, unique_id6);
+
+ vector<uint8_t> unique_id7;
+ get_unique_id(app_id, max_date + 1, &unique_id7);
+ EXPECT_NE(unique_id, unique_id7);
+
+ vector<uint8_t> unique_id8;
+ get_unique_id(app_id, min_date - 1, &unique_id8);
+ EXPECT_NE(unique_id, unique_id8);
+
+ // Marking RESET_SINCE_ID_ROTATION should give a different unique ID.
+ vector<uint8_t> unique_id9;
+ get_unique_id(app_id, cert_date, &unique_id9, /* reset_id = */ true);
+ EXPECT_NE(unique_id, unique_id9);
+}
+
+/*
* NewKeyGenerationTest.EcdsaAttestationTagNoApplicationId
*
* Verifies that creation of an attested ECDSA key does not include APPLICATION_ID.
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index e4948b4..6c0ebf7 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -107,8 +107,10 @@
static_libs: [
"VtsHalWifiV1_0TargetTestUtil",
"android.hardware.wifi@1.0",
+ "android.hardware.wifi.hostapd@1.0",
"libwifi-system-iface",
],
+ disable_framework: true,
test_suites: [
"general-tests",
"vts",
diff --git a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
index 96b4501..28b1616 100644
--- a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -15,9 +15,9 @@
*/
#include <android-base/logging.h>
-
#include <android/hardware/wifi/1.0/IWifi.h>
#include <android/hardware/wifi/1.0/IWifiApIface.h>
+#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
@@ -26,6 +26,7 @@
#include "wifi_hidl_test_utils.h"
using ::android::sp;
+using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
using ::android::hardware::wifi::V1_0::IfaceType;
using ::android::hardware::wifi::V1_0::IWifi;
using ::android::hardware::wifi::V1_0::IWifiApIface;
@@ -38,6 +39,10 @@
class WifiApIfaceHidlTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
+ if (android::hardware::getAllHalInstanceNames(IHostapd::descriptor)
+ .empty()) {
+ GTEST_SKIP() << "Device does not support AP";
+ }
// Make sure test starts with a clean state
stopWifi(GetInstanceName());
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp
index 2e6ad32..66e1a80 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp
@@ -15,9 +15,9 @@
*/
#include <android-base/logging.h>
-
#include <android/hardware/wifi/1.0/IWifi.h>
#include <android/hardware/wifi/1.0/IWifiChip.h>
+#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
@@ -26,6 +26,7 @@
#include "wifi_hidl_test_utils.h"
using ::android::sp;
+using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
using ::android::hardware::wifi::V1_0::ChipModeId;
using ::android::hardware::wifi::V1_0::IfaceType;
using ::android::hardware::wifi::V1_0::IWifi;
@@ -41,6 +42,10 @@
class WifiChipHidlApTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
+ if (android::hardware::getAllHalInstanceNames(IHostapd::descriptor)
+ .empty()) {
+ GTEST_SKIP() << "Device does not support AP";
+ }
// Make sure test starts with a clean state
stopWifi(GetInstanceName());
diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp
index 8048642..a8f3470 100644
--- a/wifi/1.1/vts/functional/Android.bp
+++ b/wifi/1.1/vts/functional/Android.bp
@@ -39,6 +39,7 @@
"android.hardware.wifi@1.5",
"libwifi-system-iface",
],
+ disable_framework: true,
test_suites: [
"general-tests",
"vts",
diff --git a/wifi/1.4/vts/functional/Android.bp b/wifi/1.4/vts/functional/Android.bp
index 14ebbe3..f86869b 100644
--- a/wifi/1.4/vts/functional/Android.bp
+++ b/wifi/1.4/vts/functional/Android.bp
@@ -14,7 +14,6 @@
// limitations under the License.
//
-// SoftAP-specific tests, similar to VtsHalWifiApV1_0TargetTest.
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
@@ -25,10 +24,9 @@
}
cc_test {
- name: "VtsHalWifiApV1_4TargetTest",
+ name: "VtsHalWifiV1_4TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
- "wifi_ap_iface_hidl_test.cpp",
"wifi_chip_hidl_test.cpp",
],
static_libs: [
@@ -46,6 +44,30 @@
],
}
+// SoftAP-specific tests, similar to VtsHalWifiApV1_0TargetTest.
+cc_test {
+ name: "VtsHalWifiApV1_4TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "wifi_ap_iface_hidl_test.cpp",
+ ],
+ static_libs: [
+ "VtsHalWifiV1_0TargetTestUtil",
+ "android.hardware.wifi@1.0",
+ "android.hardware.wifi@1.1",
+ "android.hardware.wifi@1.2",
+ "android.hardware.wifi@1.3",
+ "android.hardware.wifi@1.4",
+ "android.hardware.wifi.hostapd@1.0",
+ "libwifi-system-iface",
+ ],
+ disable_framework: true,
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
+
// These tests are split out so that they can be conditioned on presence of the
// "android.hardware.wifi.aware" feature.
cc_test {
diff --git a/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp
index 5b0f173..756afa5 100644
--- a/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -16,6 +16,7 @@
#include <android/hardware/wifi/1.4/IWifi.h>
#include <android/hardware/wifi/1.4/IWifiApIface.h>
+#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
@@ -25,6 +26,7 @@
using ::android::sp;
using ::android::hardware::hidl_array;
+using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
using ::android::hardware::wifi::V1_0::WifiStatus;
using ::android::hardware::wifi::V1_0::WifiStatusCode;
using ::android::hardware::wifi::V1_4::IWifi;
@@ -36,6 +38,10 @@
class WifiApIfaceHidlTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
+ if (android::hardware::getAllHalInstanceNames(IHostapd::descriptor)
+ .empty()) {
+ GTEST_SKIP() << "Device does not support AP";
+ }
// Make sure to start with a clean state
stopWifi(GetInstanceName());
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index 8cb7e22..114fe4f 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -317,7 +317,7 @@
}
bool waitForFrameworkReady() {
- int waitCount = 10;
+ int waitCount = 15;
do {
// Check whether package service is ready or not.
if (!testing::checkSubstringInCommandOutput(
diff --git a/wifi/supplicant/1.4/vts/functional/Android.bp b/wifi/supplicant/1.4/vts/functional/Android.bp
index 8cbe04f..57ee830 100644
--- a/wifi/supplicant/1.4/vts/functional/Android.bp
+++ b/wifi/supplicant/1.4/vts/functional/Android.bp
@@ -77,7 +77,6 @@
"general-tests",
"vts",
],
- disable_framework: true,
}
cc_test {
@@ -108,5 +107,4 @@
"general-tests",
"vts",
],
- disable_framework: true,
}